SDK tutorial · 9 of 10

Capture and read artifacts

Artifacts are durable generated values with metadata and content addressing. They let the model and product refer to a result without copying a large document through every tool response and turn.

Customization depth

Level 4 · Durable generated results

Hosting depth

Local files or injected artifact repository

Documentation status

Supported SDK boundary

Assumptions

  • An MCP server may generate source, HTML, JSON, documents, or other large text values.
  • The product needs to inspect or reuse generated content after the producing turn.
  • Artifact metadata and content remain protected by the product's conversation authorization.
Heddle owns
  • Create artifact IDs and metadata, track current artifact pointers, and expose artifact tools to the agent.
  • Automatically capture configured large MCP result fields and replace mirrors with compact references.
  • Read and list artifacts through the engine's resolved repository and root.
Your product owns
  • Choose which outputs should become artifacts and how authorized users download or apply them.
  • Provide retention, encryption, content validation, and storage compatible with Heddle's current synchronous artifact port, or return a product-owned remote reference.
  • Project safe metadata instead of exposing internal content keys or filesystem paths.

Start with automatic MCP result capture

For an MCP extension that returns generated text, HTML, JSON, or document bodies:

TypeScript
const prepared = await prepareMcpHostExtension({
  id: 'document-operations',
  workspaceRoot,
  stateRoot,
  serverId: 'documents',
  server,
  resultArtifacts: true,
})

Automatic capture traverses the MCP result, saves sufficiently large strings, infers common kinds, and replaces duplicate text/structured mirrors with the same compact artifact reference. It handles the common MCP shape where a text field repeats serialized structured content.

Start with the boolean option. Tune it only after observing real output:

TypeScript
resultArtifacts: {
  auto: {
    minChars: 1200,
    domain: 'document',
    maxPreviewChars: 800,
  },
}

Path hints and manual rules are advanced overrides for stable server-specific result shapes. Avoid coupling a first integration to guessed nested paths.

Read artifacts from the engine boundary

TypeScript
const artifacts = engine.artifacts.list({ sessionId })
const readResult = engine.artifacts.read(artifactId)

if (readResult) {
  console.log(readResult.artifact)
  console.log(readResult.content)
}

Use engine.artifacts rather than constructing another ArtifactService against stateRoot/artifacts. A host extension or injected repository can change the resolved location.

Understand turn-result artifact scope

result.artifacts is the artifact list currently associated with the session. It is not limited to newly created artifacts from that turn. Use artifact IDs, timestamps, domains, kinds, or your own product record to distinguish new and previously accumulated outputs.

result.toolResults remains scoped to completed tool calls from the current turn.

Compact replacement shape

When automatic capture replaces a large value, the tool result contains metadata equivalent to:

TypeScript
{
  artifact,
  contentPath,
  preview,
  omittedCharacters,
}

The full content remains available through Heddle's artifact reader/tool path. The preview helps the model understand the value without reloading it in full.

Native tool behavior

resultArtifacts is MCP host-extension capture; it does not automatically convert arbitrary native-tool output. For a native tool backed by your own asynchronous document store, save the value there and return a compact authorized reference:

TypeScript
execute: async (input) => {
  const document = await productDocuments.create(input)
  return {
    ok: true,
    output: { documentId: document.id, preview: document.preview },
  }
}

If the value must become a Heddle artifact, use the synchronous engine.artifacts.saveText(...) host boundary deliberately and account for the storage constraint explained in Use your own storage.

Production considerations

  • authorize every artifact read using the owning product conversation or record;
  • validate generated content before applying it to a user-visible product object;
  • set retention and deletion policy for both metadata and content;
  • keep repository content keys and local paths out of public response schemas.

Canonical sources