<@ULVA73B9P> can i update table/markdown artifacts...
# ask-marvin
c
@Marvin can i update table/markdown artifacts?
m
thought for 269.3 seconds
Short answer: yes—with caveats. - Progress artifacts: fully updatable in place - Use
create_progress_artifact
+
update_progress_artifact
- UI updates live without creating new versions - Docs: How-to: ArtifactsConcepts: Artifacts - Markdown/Table artifacts: no first-class “update” helper - Recommended: write a new artifact with the same
key
to create a new version (lineage in the UI) - If you truly need to overwrite the same artifact in place, you can patch it via the low-level client API. Recommended pattern (versioned updates via same key)
Copy code
from prefect.artifacts import create_markdown_artifact, create_table_artifact

# V1
create_markdown_artifact(
    key="daily-report",
    markdown="# Report\nStarting up...",
    description="Stage 1"
)

# Later — V2 (new version under the same key)
create_markdown_artifact(
    key="daily-report",
    markdown="# Report\nAll done.",
    description="Final"
)

# Same idea for tables
create_table_artifact(
    key="churn-table",
    table=[{"id": 1, "risk": "high"}],
    description="Initial"
)
create_table_artifact(
    key="churn-table",
    table=[{"id": 1, "risk": "medium"}],
    description="Updated"
)
In-place overwrite (advanced; bypasses versioning)
Copy code
from prefect.artifacts import create_markdown_artifact
from prefect.client.orchestration import get_client
from prefect.client.schemas.actions import ArtifactUpdate

# Create once and keep the returned artifact_id
artifact_id = create_markdown_artifact(markdown="# Start", key="live-report")

# Overwrite the same artifact in place (sync client shown)
with get_client(sync_client=True) as client:
    client.update_artifact(
        artifact_id=artifact_id,
        artifact=ArtifactUpdate(
            data="# Updated content",         # For tables, pass a dict/list
            description="Latest view"
        )
    )
Notes - Creating with the same
key
= new version (best for history/lineage in the UI). - Patching via
update_artifact
modifies the existing artifact (no history). - API ref: Python API: prefect.artifacts If you can share your exact goal (append vs replace, need for lineage vs single “live” artifact), I can suggest the cleanest pattern and a concrete snippet.
c
@Marvin I tried doing the first approach, i get dozens of tables in my artifacts tab. am i doing something wrong?
m
thought for 117.8 seconds
Short answer: you’re not doing anything wrong. That behavior is expected. What’s happening: - Each call to
create_table_artifact(...)
creates a new artifact instance. - In a run’s Artifacts tab, Prefect shows every artifact created in that run, so if you emit one per iteration you’ll see dozens there. - If you pass a
key=...
, the global Artifacts page will show just the latest version for that key (with version history behind it), but the run’s Artifacts tab will still list each artifact created during that run. If your goal is to see only one table for the run: - Emit once at the end. Accumulate rows during the run and call
create_table_artifact
a single time. Example: accumulate then emit once
Copy code
from prefect import flow
from prefect.artifacts import create_table_artifact

@flow
def my_flow():
    all_rows = []
    for i in range(50):
        # ... do work, produce rows ...
        all_rows.append({"i": i, "value": i * 2})
    create_table_artifact(
        key="my-table",  # optional; adds versioning on the global Artifacts page
        table=all_rows,
        description="Final aggregated results for this run"
    )
If you actually want snapshots along the way but don’t want clutter in the current run’s tab: - There isn’t an “update/append” API for table artifacts—only progress artifacts support in-place updates. - Use a control flag so you only emit the final snapshot in the main flow, or aggregate snapshots into a single markdown artifact. Option: combine multiple tables into one markdown artifact
Copy code
from prefect import flow
from prefect.artifacts import create_markdown_artifact

@flow
def report():
    md = """# Report

## Part A
| Col | Val |
|-----|-----|
| a1  | 10  |
| a2  | 20  |

## Part B
| Col | Val |
|-----|-----|
| b1  | 5   |
| b2  | 15  |
"""
    create_markdown_artifact(key="daily-report", markdown=md, description="Combined report")
Key points: - Multiple calls → multiple artifacts in the run’s tab (expected). - Use
key
to get a single “latest” entry on the global Artifacts page; versions are retained behind it. - There’s no “update/append” for table artifacts; emit once or version by re-creating. Docs and references: - Artifacts concepts - Artifacts how-to - Progress artifacts (the only updatable kind): update_progress_artifact API If I misunderstood your “first approach,” can you share a small snippet of how you’re creating the artifacts and what you want the UI to look like (single final table vs snapshots)? I can tailor the pattern to your case.