Artifacts

An artifact is a file a run produces and keeps: a generated report, a rendered image, a diff, a CSV, a build output. The run's working directory is scratch and disappears when the run ends, so anything you want to hand back to a person or a downstream system becomes an artifact, stored durably and attached to the run.

What an artifact is

It belongs to the run that wrote it and, through it, to your org; like everything else, it is tenant-isolated. Each artifact record carries:

FieldWhat it is
NameThe file name, e.g. weekly-report.md.
Content typeA MIME type, e.g. text/markdown.
SizeThe size of the stored bytes.
MetadataOptional key/value data you attach, yours to read back later.
ExpiryWhen the artifact expires.

Writing one

From the program, call artifacts.write. Pass text or raw bytes; it stores the file and resolves to a reference with a download URL:

import { artifacts, agent } from "@boardwalk-labs/workflow";

export default async function run() {
  const report = await agent("Write the weekly metrics report as Markdown: ...");

  const ref = await artifacts.write(
    "weekly-report.md",
    "text/markdown",
    report,
    { week: "2026-W24" }, // optional metadata, yours to read back later
  );

  return { report: ref.url }; // ref = { id, name, url }
}

Binary is the same call with a Uint8Array body, so a generated PNG or a zipped bundle works exactly like text.

From an agent

The artifacts built-in tool is on by default, so an agent can persist its own output without you wiring anything: ask it to save its work and it writes the artifact, then you read the reference back. The program around it stays in control of what counts as a deliverable.

// The artifacts built-in tool is on by default: just ask.
await agent("Write the weekly metrics report as Markdown and save it as an artifact.");

Retrieving artifacts

List a run's artifacts, then fetch one:

SurfaceHow
DashboardThe run page lists every artifact with a download link.
CLIThe run's output and artifacts show up alongside its logs.
REST APIGET /v1/orgs/:slug/runs/:id/artifacts to list, then GET /v1/artifacts/:id/download (a 302 to a signed URL) or /download-url(the signed URL as JSON, for clients that can't attach a bearer token across a redirect).
MCPlist_artifacts then get_artifact_download_url.

Signed URLs & lifetime

Downloads go through short-lived signed URLs, so the bytes are served by the CDN without exposing the storage bucket, and a link you mint is only good for a window. Request a custom window with ttlSeconds when you mint one (up to a day). The artifact record itself persists with the run; the URL is the thing that expires, so mint a fresh one when you need it rather than storing it.

Artifacts vs. output

Reach for an artifact when the thing is a file: something to download, large, or binary. Reach for the run's output, the value your runfunction returns, when the thing is the run's result: a JSON value a person reads on the run page, a notification carries, or a calling workflow consumes. They compose well: return a small JSON summary that points at the heavier artifacts by URL.