message

A message is one conversational message: a user prompt, an assistant response, a system or developer instruction delivered as a message, context inserted by the agent software (the harness), a message from another session or another person in a chat, or a stored notice.
Capture state keys: content, displayContent, role. ASR-200 A message MUST contain messageId and content, and MUST contain role unless capture.role is present. ASR-201 role describes the channel, not the writer: system and developer are instruction roles (Codex, for example, delivers harness instructions as developer messages); user and assistant are the conversational roles. Some sources decide a message’s role only when they build each request, differently for each provider (OpenClaw’s injected custom messages). When the stored record has no role, role is absent and capture.role is {"state": "absent"}.

Author

ASR-202 A producer MUST set author: "human" only when the source records that a person wrote the content. When the source does not distinguish, author MUST be absent. ASR-203 A producer MUST NOT use author: "human" for content that the source marks as inserted by the harness, a hook or a tool, even when it arrives under role: "user". When the source marks the boundary between human text and inserted text inside one item, the producer MAY split the text at that boundary into separate parts, each with its exact text and its own author and origin (see Part-level values); otherwise it keeps the text whole. A producer SHOULD keep one native item as one message, so that the native ID is kept.

Origin

origin: "retrieval" and origin: "memory" let search indexes recognize content that was retrieved from earlier history, so it is not counted again as new evidence. A prompt that a schedule, a webhook or another event caused keeps the author and origin the source records for it (often harness and injected). What started the turn is the turn’s trigger (see Turns and triggers).

Part-level values

One native message can mix content of different kinds: Codex tags each part of a user-role item (the person’s text, AGENTS.md, an environment snapshot, hook context). Splitting such an item into several messages would lose its native ID. Instead, a content part can carry its own author, origin and phase.
This record comes from a Codex session. Every part carries its own values, so the message has none. ASR-224 A content part MAY carry author, origin and phase, with the values defined for the message members. A part’s own value applies to that part; the message’s value applies only to the parts that do not carry one. When every part carries its own value, the message member MAY be absent. Readers MUST resolve a part’s effective value this way. ASR-202 and ASR-203 apply to each part’s effective author.

Audience

ASR-204 audience MUST be model, user, both or unknown, and absent means unknown. A producer MUST set model, user or both only when the source indicates who saw the content. It MUST NOT default to both. ASR-205 A stored harness notice MUST be a message with author: "harness", origin: "notice" and audience: "user". Messages with audience: "user" stay on the active path but are not entries in the context view (see Structure).

Status

ASR-206 status MUST be one of the values above or a vendor value. partial means the content is incomplete because generation did not finish or only part was captured; interrupted means the user or harness stopped generation; error means generation failed; withdrawn means queued input that was removed before it was delivered (Claude Code’s queue remove, an OpenClaw pending input that was cancelled). ASR-225 A producer MUST set status: "withdrawn" only when the source records that the input was removed before delivery. A withdrawn message stays on the active path but is not an entry in the context view, and readers MUST NOT present it as received by the model.

Phase

phase separates text that an assistant writes while it works (commentary) from its answer (final), as Codex and OpenClaw record it. The message’s phase is the default for its parts; a part can carry its own (ASR-224), because one response can hold both.

Senders and recipients

from names who sent a message, as an actor reference (see Identity): a participant in a chat, another session, an agent address. It is a separate fact from author (who wrote the words) and origin (how the message entered). recipients names who the message was addressed to; each entry is {actor, kind?}, where kind is primary or additional (open). triggersTurn records whether the source delivered the message so that it starts a turn (Codex trigger_turn).
The first record is in the stream of the example session’s subagent: the parent sent it with a tool call, and the subagent received it as a user-role message. The second comes from a Codex worker thread. Codex addresses agents by path inside one agent tree, so each address carries the tree’s root session as its scope. ASR-226 from, recipients, triggersTurn, conversation, platform, addressed and via MUST come from the source. A producer MUST NOT set author: "human" because from names a person, MUST NOT set from because of author, and MUST NOT invent a recipient or the turn a message started. ASR-228 from and each recipient’s actor MUST be actor references (ASR-076), and each element of derivedFrom MUST be a ref (ASR-062) or a session reference with a # part.

Conversations and platform IDs

In a chat, conversation names the conversation a message belongs to, by an ID from the header’s conversations (see Session records). platform keeps the messaging app’s own IDs: messageIds (one message can arrive or leave as several platform messages) and replyTo (the platform ID of the message it answers). addressed records whether the message was meant for this agent, which matters in a group where the agent also sees messages not meant for it.
This record comes from the OpenClaw session whose header is shown under Participants. The sender is participant p2, whose kind OpenClaw does not know, so author is absent. ASR-227 conversation MUST name a conversation declared in the header or in a declaration with a lower seq.

Derived messages

derivedFrom lists the records a message was rendered from, when the source records them: a handoff summary built from another session’s history, a merge-back of a fork, a summary written for a switch to another provider. Entries are refs to records in this stream, or session references with a # part for records in other sessions. A derived message is new content of this session, not a copy: copies of records use copiedFrom (see Lineage).
This record comes from a T3 Code thread that switched from Codex to Claude Code. T3 Code rendered a summary of three earlier records and sent it to Claude Code as the first prompt. ASR-229 A producer MUST write derivedFrom only when the source records which records the message was rendered from. It MUST NOT infer derivedFrom from similar text.

Content and display content

content is what the model received or produced. displayContent is what the user saw, when the source keeps a different representation: Gemini CLI’s displayContent, Cline’s UI message array, an interface rendering of a tool-heavy turn. An app that wraps a prompt before sending it to the model (T3 Code adds its own instructions around a person’s first prompt) keeps what the person typed. Its stream records that text in displayContent, with content empty and capture.content set to absent unless the app also recorded the wrapped text. ASR-207 When the source holds only a user-facing representation of a message, the producer MUST put it in displayContent, leave content empty, and set capture.content to absent. It MUST NOT copy display text into content unless the source states that the two are the same. ASR-208 When displayContent is present, content is non-empty and the source links the two, displayCorrespondence SHOULD state how. Absent means correspondence is unknown. A validator does not report its absence, because it cannot establish whether the source links the two representations. Any asserted correspondence remains subject to its type and content rules. ASR-209 When the source rewrote stored content after the model saw it (for example by masking a large output), the producer MUST set the capture state of the affected field to masked (see Missing data and revisions).

Content parts

Content parts are the content blocks of MCP revision 2026-07-28, as reused by the Agent Client Protocol (ACP) schema v2.0.0-alpha.9, with the additions and deviations listed below. MCP tool output passes through unchanged. ASR-210 Every content part MUST be an object with a string type. ASR-211 Text MUST be kept exactly as the source stored it: no trimming, reflowing, Unicode normalization or line-ending conversion. Streaming deltas MUST be joined only by direct concatenation, and a final snapshot MUST NOT duplicate text already received as deltas.

text

image and audio

ASR-212 image and audio parts MUST have mimeType and MUST NOT have both data and blob. A part with neither carries no bytes; the record’s capture state for the field says why. resource_link is MCP’s ResourceLink: {type, uri, name, title?, description?, mimeType?, size?, annotations?}. resource is MCP’s EmbeddedResource: {type, resource, annotations?}, where resource is {uri, mimeType?, text} or {uri, mimeType?, blob} with blob as base64, exactly as in MCP. ASR-213 A resource_link MUST have uri and name. A resource MUST have resource.uri and at most one of resource.text, resource.blob (base64, as in MCP) and resource.blobRef (a BlobRef, an ASR addition). URIs in content are data. Readers never fetch them automatically (ASR-562).

reasoning

Visibility values:
  • full: the provider exposed the reasoning text.
  • summary: the provider exposed only a summary.
  • omitted: the provider or harness withheld the text (often leaving an empty text and a signature).
  • encrypted: the reasoning exists only as ciphertext.
  • redacted: the provider redacted it, leaving opaque data.
ASR-214 A producer MUST NOT put text the source marks as a summary in text, or label a summary as visibility: "full". It MUST set visibility when the source states it. Readers MUST NOT present text as full reasoning unless visibility is full. ASR-215 opaque and signature MUST be excluded from text indexing and from metadata exports. Readers MUST NOT render them as text. ASR-216 Visibility and capture state are independent. visibility says what the provider exposed; the record’s capture state says how much of the source’s stored content is included in the record. A full reasoning part can be truncated; an encrypted one can be complete.

refusal

ASR-217 A refusal part MUST have text: the refusal message the model returned through a dedicated refusal channel. Refusals expressed in ordinary text stay text parts.

data

A data part holds structured data the source attached to a message: an IDE selection, an environment snapshot, a terminal excerpt, a page element, review findings. It is an ASR part type.
ASR-230 A data part MUST contain data. A data part in displayContent says what the user saw. It is not evidence that the model received the data, or received it as JSON. When the source keeps structured data but not the text the model received (Claude Code renders attachments into the request at send time), the message holds the data part in content. The message’s capture state describes the structured content it holds, rather than the rendered text that was not kept. ASR-238 Structured source content does not establish the exact rendered input the model received. Readers MUST NOT present a data part as the exact text the model saw. A nonempty content array MUST have a compatible capture state (ASR-506). Data known only as a UI representation MUST be in displayContent (ASR-207).

opaque

An opaque part holds content that the source keeps only in a form that cannot be read: an encrypted message part, encrypted content from another agent. Encrypted reasoning stays a reasoning part with opaque state (see reasoning).
ASR-231 An opaque part MUST contain format and MUST NOT contain both data and blob. ASR-232 Opaque parts MUST be excluded from text indexing and from metadata exports. Readers MUST NOT render them as text.

Derivation

When a source replaced content by a derived form (a transcript of a voice note, a caption, a translation), the derived part can say so with derivation.
Here a voice note was transcribed. The audio part keeps its media type; the record’s capture state says why its bytes are not included. ASR-233 A derivation MUST contain method, and a producer MUST set it only when the source records that the content was derived. from, when present, MUST be the index of another part in the same array.

Unknown parts and deviations

ASR-218 Readers MUST skip content parts whose type they do not recognize, and storage tools MUST preserve them. MCP annotations and _meta on parts MUST be preserved verbatim. Deviations from MCP 2026-07-28 and ACP schema v2.0.0-alpha.9 content blocks:
  1. image and audio accept blob (a BlobRef) instead of data, and may carry neither when the bytes were not captured.
  2. resource.resource accepts blobRef.
  3. reasoning, refusal, data and opaque are ASR part types. ACP carries reasoning as separate agent_thought messages (see Reasoning-only messages).
  4. Any part may carry the ASR members author, origin, phase and derivation.
  5. Tool calls and tool results are records (tool_call, tool_result), never content parts.

Reasoning-only messages

ACP v2 sends reasoning as agent_thought messages with their own messageId, and Codex stores reasoning items with their own IDs. A reasoning-only message is a message whose content is exactly one reasoning part. It keeps the native ID.
This example comes from a Codex session; its empty summary array is preserved literally. ASR-219 A producer MUST keep a reasoning item that has its own native ID as a reasoning-only message with that ID, rather than folding it into an adjacent assistant message. ASR-220 Readers MUST treat a reasoning-only message the same way as a reasoning part inside an assistant message. Visibility, capture, redaction and indexing rules apply identically.

plan

A plan is the agent’s current task list, plan document or goal, as recorded by the source: ACP plan_update, Codex update_plan, a to-do tool, a plan-mode document, a long-running goal with a budget. Each plan record is a complete snapshot. A changed plan is a revision with the same planId.
This example comes from a Codex session, where the plan is set by an update_plan tool call and has no native plan ID. Plan documents and goals:
The first record is a Claude Code plan-mode document, named by the plan file. The second is a Codex goal whose ID is derived from its stable, unique (threadId, createdAt) tuple under the registry rule. The third is a Claude Code task list with entry IDs, owners and dependencies. Capture state key: content. ASR-221 A plan MUST contain planId and planType. When planType is items it MUST contain entries, and each entry MUST contain content and status. When planType is document or goal it MUST contain content or a capture.content state. ASR-222 A plan record MUST be a complete snapshot. A later state of the same plan MUST be a new plan record with the same planId and supersedes naming the previous one. ASR-236 The entryId values in one plan record MUST be unique, and every value in an entry’s blockedBy MUST be the entryId of another entry in the same record. Questions to the user, delegation to other agents and plans are separate record types (input_request, subagent, plan). Consumers find them by record type, not by the kind of the tool call that produced them (see Tools).

delivery

A delivery records what happened to a message the agent sent to a conversation: queued, sent, delivered, held back, or failed. On a messaging app, an assistant message says what the agent wrote; it does not say that anyone received it. A reply can be held back (OpenClaw’s NO_REPLY), cancelled by a hook, or fail on the platform.
These records come from the OpenClaw session under Participants. The first reply was sent to the group. The agent chose not to answer the second message, so its final text was not sent. A change of status is a revision of the delivery record (supersedes). ASR-234 A delivery MUST contain status. ASR-235 A delivery’s message and conversation follow the reference-resolution table. Their targets MUST be a message record and a declared conversation, respectively (ASR-227). ASR-237 A producer MUST write delivery records only from the source’s record of an outbound attempt or its outcome, never from the existence of a message. Readers MUST NOT present a message as delivered unless a delivery for it has status sent or delivered.