Agent Session Protocol

Content Blocks

The content taxonomy and opaque-payload passthrough

Block types

ContentBlock =
  | { type: "text"; text }
  | { type: "thinking"; text; signature? }   // resume-critical
  | { type: "tool-call"; toolCallId; name; arguments }
  | { type: "tool-result"; toolCallId; toolResultId; content; isError }
  | { type: "image"; mimeType; data?; uri?; alt? }
  | { type: "reference"; uri; title?; mediaType? }
  | { type: "error"; message; code?; detail? }
  | { type: "unknown"; nativeType; value }   // opaque-payload container

Opaque passthrough

Agent ecosystems contain bytes that cannot be parsed but must round-trip verbatim:

  • Claude's thinking signature (required by the Anthropic API on resume)
  • Codex's reasoning encrypted_content (server-side verification chain)

ASP carries them in a typed unknown block — never normalized away. The rule is strict: any canonical→native→canonical re-encoding path must leave unknown blocks idempotent (no double-wrapping), or the nativeType is clobbered and the payload lost.

Tool results

Tool-result content is authoritative on the tool entity's result, not on the message blocks — harnesses disagree on the block shape (pi uses [text], Codex uses [tool-result]), so exporters must read from the tool entity.

Full detail: asp/spec/content-blocks.md.

On this page