Agent Message Envelope
File: /agents-api/inc/AI/AgentMessageEnvelope.php
The canonical agent message shape is a JSON-friendly typed envelope. Runtime
code, chat storage, and transcript storage should store and return envelopes.
Provider-specific role/content/metadata arrays are a projection used at the
request-runtime boundary, not the internal contract.
Envelope Shape
[
'schema' => 'agents-api.message',
'version' => 1,
'type' => 'text',
'role' => 'assistant',
'content' => 'Message text or provider-neutral content blocks',
'payload' => [], // Type-specific JSON-serializable payload.
'metadata' => [], // Extension metadata; must stay JSON-serializable.
// Optional fields preserved when present:
'id' => 'stable-message-id',
'created_at' => '2026-04-28 12:00:00',
'updated_at' => '2026-04-28 12:00:00',
]Supported type values:
texttool_calltool_resultinput_requiredapproval_requiredfinal_resulterrordeltamultimodal_part
Use payload for type-specific fields that the agent runtime understands, such
as tool names, tool parameters, turn numbers, and tool result data. Use
metadata for extension/provider details that should be preserved but are not
part of the type contract.
Compatibility
AgentMessageEnvelope::normalize() accepts existing role/content/metadata rows
and versioned envelopes. It also accepts the short-lived data envelope key from
the initial envelope draft as a read-time compatibility input and rewrites it to
payload.
New writes should store canonical envelopes. Current provider requests use
AgentMessageEnvelope::to_provider_message() / to_provider_messages() to
project envelopes into Data Machine’s role/content/metadata provider-message
shape. That projection folds the envelope type and payload into provider
metadata.
Type Payload
Legacy tool-call messages:
[
'role' => 'assistant',
'content' => 'AI ACTION (Turn 1): Executing Wiki Upsert',
'metadata' => [
'type' => 'tool_call',
'tool_name' => 'wiki_upsert',
'parameters' => [ 'title' => 'Example' ],
'turn' => 1,
],
]normalize to:
[
'schema' => 'agents-api.message',
'version' => 1,
'type' => 'tool_call',
'role' => 'assistant',
'content' => 'AI ACTION (Turn 1): Executing Wiki Upsert',
'payload' => [
'tool_name' => 'wiki_upsert',
'parameters' => [ 'title' => 'Example' ],
'turn' => 1,
],
'metadata' => [
'type' => 'tool_call',
'tool_name' => 'wiki_upsert',
'parameters' => [ 'title' => 'Example' ],
'turn' => 1,
],
]For new adapters, prefer putting type-specific fields in payload and
adapter-specific details in metadata. Data Machine projects payload back into
provider metadata only when calling a provider boundary that still expects that
shape.
Adapter Guidance
Runtime adapters using agents_api_conversation_runner may return messages in
either legacy or envelope shape. AgentConversationResult::normalize() normalizes
every returned message to the canonical envelope before callers store or render
the result.
Conversation store adapters should normalize host messages to this envelope at their boundary and return envelopes to Data Machine’s chat abilities and UI. Adapters that wrap a host-specific DTO should keep that DTO at the host boundary, not inside Data Machine storage.