novo agents

Artifacts

Temporary Novo-managed transfer handles for generated media, workspace exports, browser screenshots, and document files.

Artifacts are not durable product records. Treat artifact.id as a retention-scoped Novo handle for fetching bytes while your app saves, previews, or forwards the file. If you configure top-level artifacts.exports, your result handler should return its own durable artifactId and/or url; those durable refs are what public streams prefer by default. For product-specific paste targets, the handler may also return ref or block; those fields surface on model-visible artifact output as artifact.ref and artifact.block.

Every deliverable carries a durable reference for the model to hand off. When no export handler is configured for it, artifact.ref is { kind: 'novo', id }: the retention-scoped Novo id, valid for the full retention window via novo.artifacts.get(id). The agent is instructed to reference deliverables by this durable handle, never by the temporary signed url (which expires within a day) or a bare workspace filename.

Methods

| Method | Route | |---|---| | novo.artifacts.get(id) | GET /v1/artifacts/:id |

Type signature

type ArtifactsNamespace = {
  get(id: string): Promise<Artifact>;
};

type ArtifactKind = 'image' | 'video' | 'audio' | 'json' | 'document' | 'file';

type Artifact = {
  id: string;
  object: 'artifact';
  kind: ArtifactKind;
  url: string;
  expiresAt: string;
  mimeType: string;
  bytes: number;
  sha256: string;
  metadata: Record<string, unknown>;
  retentionExpiresAt: string;
  createdAt: string;
};

url is a temporary Novo signed URL for fetching the artifact content; expiresAt is the URL expiry. retentionExpiresAt is the Novo artifact handle expiry. This authenticated SDK/API call returns the URL even when an agent's public stream uses the default artifacts.stream.urls: 'durable-only' projection.

Fetch Metadata

const artifact = await novo.artifacts.get('art_...');

const bytes = await fetch(artifact.url).then((response) => response.arrayBuffer());

Use this API as a programmatic escape hatch. Model-visible tool output should use explicit handoff through workspace_export_artifact({ path }) when an agent wants a workspace file promoted to a durable customer destination.

Public Stream Projection

Saved agents default to:

artifacts: {
  stream: { urls: 'durable-only' },
}

With that default, public tool results and UI chunks do not expose Novo signed ?token= URLs. They emit a durable handler URL when artifacts.exports returns one, or an id-only artifact ref (artifact.ref = { kind: 'novo', id }) when no durable URL exists. Set artifacts.stream.urls = 'include-novo-signed' only when your consumer explicitly wants temporary Novo URLs in public output; even then the durable artifact.ref rides alongside the signed url as the reference the agent hands off.

If the result handler returns a paste-ready reference, public/model-visible artifact output includes that handler artifact.ref (kind e.g. drive) and, when available, artifact.block, in place of the native novo ref. Those fields describe your durable customer-side object and do not change the authenticated novo.artifacts.get(id) response, which remains the temporary Novo transfer handle for fetching bytes.