# Artifacts

Artifacts are durable outputs such as reviewed pull requests, reports,
or decision records. An artifact kind defines the data it accepts, and
the artifacts API tags or updates records by key. Records persist across
sessions and can be listed, streamed, or downloaded.

## Artifact kinds

Author `bot/artifacts.ts` with `defineArtifacts` from
`@grok/agent-sdk/artifacts`:

```ts
import { z } from "zod";
import { defineArtifacts } from "@grok/agent-sdk/artifacts";

export default defineArtifacts({
  kinds: {
    "reviewed-pr": {
      description: "A pull request this agent reviewed.",
      schema: z.object({ url: z.string(), verdict: z.string() }),
    },
    report: { description: "A generated report." },
  },
  agentTool: true,
});
```

| Option | Contract |
| --- | --- |
| `kinds` | Map of accepted kind names to a non-empty `description` and optional Zod `schema` |
| `agentTool` | Expose `tag_artifact` to the model; requires at least one declared kind |
| `max` | Positive retention cap, default `1000`. Local and self-hosted servers evict the oldest-updated record; hosted deployments don't evict. |

With declared kinds, `tag` rejects any other kind. With no registry, it
accepts free-form kind names and defaults an omitted kind to
`"artifact"`. A kind's schema validates `data`, and the parsed value is
stored, including schema defaults and coercions.

## Tag artifacts from host code

Tools, hooks, channel handlers, channel `onStart`, schedules, and
reminders receive an `ArtifactsApi` with `tag` and `list`.

```ts
await ctx.artifacts.tag({
  kind: "reviewed-pr",
  key: prUrl,
  title: `Reviewed ${prUrl}`,
  data: { url: prUrl, verdict: "approve" },
});
```

| Tag field | Contract |
| --- | --- |
| `data` | Required JSON data, validated when the kind has a schema |
| `kind` | Declared or free-form kind |
| `key` | Agent-wide upsert key; the same key updates one record across kinds |
| `title` | Optional display title |
| `contents` | String or bytes served by the content route |
| `contentType` | MIME type for `contents` |
| `sessionId`, `turnId` | Attribute the artifact to a session or turn |
| `source` | `"host"` or `"model"`; defaults to `"host"` |

Tool, hook, result, and channel-event contexts are session-bound, so
they fill `sessionId` and the current `turnId`. Channel routes,
`onStart`, schedules, and reminders receive an unbound facade; pass
`sessionId` to attribute an artifact.

Re-tagging a key without `contents` keeps its file or blob when the
`sessionId` stays the same. Rebinding the key to another session without
new contents removes the previous payload. `tag` returns the stored
`ArtifactRecord`.

| Record field | Contract |
| --- | --- |
| `id` | Stable ID derived from `key`, or a generated ID when no key is set |
| `kind`, `data` | Validated kind and JSON payload |
| `key`, `title` | Optional upsert key and display title |
| `content` | Optional `{ size, contentType? }` metadata |
| `sessionId`, `turnId` | Optional session attribution |
| `source` | `"host"` or `"model"` |
| `createdAt`, `updatedAt` | ISO-8601 timestamps |

## Expose `tag_artifact` to the model

With `agentTool: true`, the `tag_artifact` server tool materializes from
the kinds registry. Its input accepts the declared kinds and validates
their data with the same schemas as host-side tagging. The kind
descriptions tell the model which output each one represents.

An authored tool named `tag_artifact` takes precedence over the generated
tool.

## List artifacts

`list({ kind?, sessionId? })` returns matching records newest-updated
first. HTTP callers can list records and download content through the
[artifact routes](/docs/reference/http-api.md#list-and-download-artifacts).

## Stream artifact tags

Tagging an artifact with a `sessionId` emits `artifact.tagged` on that
session. Its event data contains `id`, `kind`, `key`, `title`, `data`,
and `source`. See [Stream events](/docs/reference/sessions.md#stream-events) for the
event envelope.

## Related

- [Sessions](/docs/reference/sessions.md)
- [Tools](/docs/reference/tools.md)
- [Evals](/docs/reference/evals.md)
- [HTTP API](/docs/reference/http-api.md)
