Artifacts
Artifacts are structured outputs attached to a run — reports, measurement summaries, annotated images, and links to external files. They appear in the platform UI under the run's Artifacts tab and are persisted for traceability and downstream use.
unitelabs-sdk< 0.10.0, import flow and task from Prefect instead. Use flow in place of both workflow and phase decorators, and task as step decorators.Artifacts are distinct from logs: logs capture the execution narrative, artifacts capture the scientific results.
Producing artifacts
Use Prefect's artifact functions from any phase or step. The most common type is a markdown artifact, which can embed tables, images, and rich text directly in the run view.
Measurement report — summarize results as a markdown table:
from unitelabs.sdk import get_logger
from unitelabs.sdk.automate import phase
from prefect.artifacts import create_markdown_artifact
@phase()
async def report(plate_id: str, hits: list[str], hit_rate: float):
logger = get_logger()
rows = "\n".join(f"| {well} |" for well in hits) or "| — |"
await create_markdown_artifact(
key="plate-read-report",
markdown=f"""## Plate Read Report
**Plate:** `{plate_id}`
**Hit rate:** {hit_rate:.1f}%
| Hit well |
|----------|
{rows}
""",
description=f"{len(hits)} hits on {plate_id}",
)
logger.info(f"Report artifact published — {len(hits)} hits")
Annotated image — embed a base64-encoded image inline:
import base64
from unitelabs.sdk.automate import phase
from prefect.artifacts import create_markdown_artifact
@phase()
async def detection(camera_service_name: str) -> dict:
image = await capture_snapshot(camera_service_name)
result = detect_plate_in_roi(image)
_, buf = cv2.imencode(".png", image)
img_b64 = base64.b64encode(buf).decode()
await create_markdown_artifact(
key="detection-result",
markdown=f"""## Plate Detection
**Result:** {"✅ PLATE PRESENT" if result["plate_present"] else "❌ EMPTY"}

""",
description="Camera-based plate detection",
)
return result
External file link — reference a file in object storage or a local path:
from unitelabs.sdk.automate import phase
from prefect.artifacts import create_link_artifact
@phase()
async def imaging(target: Plate):
image_path = await microscope.capture(target)
await create_link_artifact(
key="plate-image",
link=str(image_path),
description="Captured plate image",
)
Accessing artifacts
Platform UI: open a run and navigate to the Artifacts tab. Each artifact shows its name, type, and the phase that produced it.
API:
curl https://api.unitelabs.io/v1/runs/{run_id}/artifacts \
-H "Authorization: Bearer $API_TOKEN"
Download a specific artifact:
curl https://api.unitelabs.io/v1/runs/{run_id}/artifacts/plate_image \
-H "Authorization: Bearer $API_TOKEN" \
-o plate_image.tiff
Artifact traceability
Every artifact is linked to:
- The run that produced it
- The workflow version that was executing
- The phase and step that created it
- The inputs the run was started with
This chain of custody makes it possible to reproduce any result or trace a measurement back to the exact protocol and reagent batch that generated it.