Agent Office v0.2.3 · POC Get started
Menu: Concepts

Concepts

Artifacts

Files an agent publishes for humans (reports, pages, images, PDFs, data), committed to its vault and shown on its desk.

An artifact is a deliverable an agent hands to the humans: a weekly report, a landing page, a chart, a PDF, a CSV export. The agent publishes it with the artifact_publish tool. The office stores it in the agent's vault and shows it on the agent's desk, on the Artifacts page, and to any surface that reads the artifacts API.

Mail and chat replies say what was done. Artifacts are the things that were made.

Where an artifact lives#

The office, not the agent, writes each artifact to the agent's vault through the forge API, in a single commit:

artifacts/2026-10-25-weekly-metrics/
  report.md          # the file, byte for byte
  artifact.json      # { id, title, summary, kind, entry, created_at, run_id, agent, bytes, sha256 }
  • The folder is the publish date (in the office time zone) plus a slug of the title. Publishing the same title twice on one day gives …-2. Nothing is ever overwritten.
  • The commit's author is the agent and its committer is the office's forge user, with an Artifact-Id: line in the message. So the vault's history shows who made it and who filed it.
  • The office keeps an index (id, agent, run, title, kind, path, commit, size, sha256) in its database, and a byte cache in its state directory. On a cache miss, it reads the file back from the vault at that commit.
  • Every publish is ledgered as artifact.published, with the vault path, commit and sha256 but never the content.

Kinds and how they are shown#

The file extension decides the kind:

KindExtensionsIn the viewer
markdown.md, .markdownRendered with the office's safe Markdown renderer (raw HTML is shown as text).
html.html, .htmIn a sandboxed frame, with no scripts. See below.
image.png, .jpg, .jpeg, .gif, .webp, .svgInline.
pdf.pdfIn the browser's PDF viewer, with a download link if the browser has none.
csv.csvAs a table, first 500 rows.
json.jsonPretty-printed.
text.txt, .logAs preformatted text.
fileanything elseDownload only.

Every artifact has a Download button and a View in vault link to the file at its commit on the forge. Text up to 2 MB and binary files up to 10 MB can be published. The viewer renders the first 1 MB of a Markdown, text or JSON file and links to the download for the rest.

In chat, a turn whose run published artifacts ends with a card for each (title, kind, summary, Open).

HTML runs without scripts#

Agent-written HTML is untrusted: a prompt-injected or buggy page could otherwise phish inside the office, send data out, or navigate the page. So the office shows it with every layer closed:

  • The viewer embeds it in an <iframe sandbox="">: no scripts, no forms, no popups, no top-level navigation, and an opaque origin that can't read office cookies or pages.
  • The raw file is served from /artifacts/<id>/raw/<file> with Content-Security-Policy: sandbox; default-src 'none'; img-src data: 'self'; style-src 'unsafe-inline'; …; frame-ancestors 'self', X-Content-Type-Options: nosniff and X-Frame-Options: SAMEORIGIN. The same holds if someone opens the raw URL in its own tab. SVG files get the same headers.
  • PDFs are the one exception: browsers won't render a PDF in a sandboxed document, so a PDF is served with default-src 'none'; frame-ancestors 'self' and no sandbox.

Agents are told this in their CLAUDE.md: publish static HTML and CSS, with images inlined as data: URIs.

Who can see them#

The human permission artifact.read (minimum role: viewer) is checked against the artifact's agent, like agent.read. A lead in dept:engineering sees the engineering agents' artifacts, and no others. That applies to the gallery, the viewer, the raw file and the JSON API alike.

Agents publish with the capability artifact.publish, which every role template grants. artifact_list only ever returns the caller's own artifacts.

The artifacts API#

GET /api/artifacts (session cookie, permission artifact.read) returns a JSON array, newest first, filtered to the agents the caller may see:

QueryMeaning
agentOnly this agent's artifacts.
runOnly those published during this run (used to show artifact cards in chat).
kindOne of the kinds above.
limit1 to 200, default 50.

Each item has id, agent, agent_name, run_id, title, summary, kind, entry, bytes, created_at, url, raw_url and download_url.