Skip to main content

The problem artifacts solve

An agent produces something big — a query result, a log dump, a scraped table — and then needs three rows out of it, twice, four turns later. Pasting the whole thing back into the prompt burns the context window and the budget on every turn that follows. An artifact is that blob stored once, addressed by id, and readable by query: filter, sort, search, project, paginate. The rows come back; the other 39,997 never enter the prompt. Artifacts are scoped to the key that uploaded them. The tenant scope is always taken from your authenticated key and can never be set from the request body.

Endpoints

Upload

201 Created
Identical content uploaded twice is deduplicated: the second call returns 200 with "deduped": true and the same reference. Re-uploading in a retry loop costs nothing.
Provenance defaults to { "method": "unknown", "lossless": false } — the honest default for content an agent produced. Only assert "lossless": true when the artifact really is an exact projection of its source; downstream consumers are entitled to trust it.

Query

The body is the query. Every field is optional — an empty body reads from the top. Operators for filter[].op: eq, ne, lt, lte, gt, gte, contains, in, exists.
Request
Response
totalMatched counts the rows that matched before offset/limit, and truncated tells you whether your window dropped any — together they are how a client knows to page rather than guessing from rows.length. Unstructured content (plain text, a log with no parseable rows) comes back as text instead of rows, with "structured": false. Use range to slice it.

Inspect

Returns { "reference": { ... }, "descriptor": { ... } } — size, shape, summary, and provenance. Deliberately never the raw bytes: the whole point of an artifact is that the big thing stays out of the context window, so the read path is query, not get.

Delete

Returns { "deleted": true, "artifactId": "art_..." }, or 404 if it does not exist for your key.

Errors

Same flat shape as Agent Runs{ "error": { "type", "message" } } with invalid_request (400), unauthorized (401), not_found (404), method_not_allowed (405), and not_implemented (501) when the store is not enabled on the deployment you are calling.

From the CLI