Skip to main content

Artifacts

Artifacts

Artifacts are durable files produced by agents (or uploaded) and exposed through signed/public URLs. They back generated images, documents, and other binary outputs that flow to chat, native channels, Pipedream, and MCP. See the Artifacts guide for the conceptual overview.

The ArtifactReference JSON shape used everywhere an artifact is produced or consumed:

{
"id": "art_0123",
"contentType": "image/png",
"url": "https://<api-host>/api/artifacts/art_0123/signed?token=…",
"publicUrl": "https://<api-host>/api/artifacts/art_0123?token=…",
"fileName": "generated-1.png",
"sizeBytes": 84213
}

Tool results that produce files use the convention { artifacts: [ArtifactReference, …], … }.

Endpoints — ArtifactsController (api/artifacts)

MethodPathAuthPurpose
GET/api/artifacts/{id}JWT owner/project access or ?token=<signed>Stream artifact content (inline Content-Type)
GET/api/artifacts/{id}/signed?ttl=<seconds>JWT owner/project accessReturns a fresh signed URL { url, expiresAt }
POST/api/artifactsInternal / trusted caller (multipart)Upload bytes → ArtifactReference

GET /api/artifacts/{id} — streams the blob with its original Content-Type. Accepts either a bearer JWT (owner or project-scoped caller) or a token query parameter carrying a signed HMAC token, so the endpoint can be used directly as the src of an <img> / <video> tag without headers. Returns 404 if the artifact does not exist and 403 if the caller has no access and no valid token.

GET /api/artifacts/{id}/signed?ttl=<seconds> — mints a new signed URL for the artifact. Returns:

{ "url": "https://<api-host>/api/artifacts/art_0123?token=…", "expiresAt": "2026-08-19T13:25:00Z" }

Use a short ttl (e.g. 900s) when handing the URL to an external channel that fetches immediately, and a longer ttl (e.g. 3600s) for chat rendering.

POST /api/artifacts — internal multipart upload (multipart/form-data with a single file part). Returns the ArtifactReference for the stored blob:

{
"artifactId": "art_0123",
"contentType": "image/png",
"url": "https://<api-host>/api/artifacts/art_0123/signed?token=…",
"publicUrl": "https://<api-host>/api/artifacts/art_0123?token=…",
"fileName": "generated-1.png",
"sizeBytes": 84213
}

This endpoint is intended for trusted internal callers (e.g. the chat pipeline persisting a user upload). Agents and automations produce artifacts through generation tools such as generate_image, not by calling this endpoint directly.

Tool-result artifacts convention

A tool that produces files returns:

{
"artifacts": [
{ "id": "art_0123", "contentType": "image/png", "url": "…", "publicUrl": "…", "fileName": "generated-1.png", "sizeBytes": 84213 }
]
}

Downstream tools accept either artifactId (resolved to a freshly signed publicUrl by the action executor) or a direct publicUrl / imageUrl. See docs/WHATSAPP-BUSINESS.md, docs/FACEBOOK.md, docs/INSTAGRAM.md, and the Artifacts guide for the per-channel contract.

Configuration

Artifacts__Enabled=true
Artifacts__StorageProvider=Local # Local | Azure | Gcs
Artifacts__PublicBaseUrl=https://<api-host>
Artifacts__SigningKey=<HMAC secret>
Artifacts__Container=kroov-artifacts # Azure
Artifacts__Bucket=kroov-artifacts # GCS
Mcp__PersistImageResults=false

Artifacts__SigningKey is a secret; supply it via the environment or a secret manager, never in Git.