AGDX
The portable data and agent contract underneath Laser SDK.
AGDX (Agent Data Exchange Protocol) defines records and behavior for Laser SDK. It covers streaming, managed data, and agent coordination on a durable log. The SDK records model provenance. It does not call models.
AGDX assumes a durable partitioned log with offsets. Laser SDK implements it on Apache Iggy. AGDX defines portable data and behavior. Iggy provides transport, retention, and consumer groups.
Rust, Python, and TypeScript use VSR (Viewstamped Replication Revisited). VSR handles transport and replication below AGDX. It does not change AGDX envelopes, headers, command codes, or fixtures. Classic Iggy transport is unsupported.
This page covers the architecture and application rules. The full specification and its docs/agdx.md source define exact fields, limits, codes, and byte layout.
One contract, five layers
| Layer | Owns | Can be used alone |
|---|---|---|
| Substrate | Durable partitions, offsets, retention, consumer groups, pull-based reads | Laser SDK ships Apache Iggy |
| Wire | Portable types, named-field CBOR, dictionaries, limits, capability shapes, fixtures | Yes, by an independent port |
| Platform | Publish and consume, projections and query, key-value, forks, graph | Yes, with no agent concepts |
| Fabric | Agent envelopes, reliable consumers, coordination, context, memory, governance | Yes, with no public edge protocol |
| Edges | A2A, MCP, and AG-UI mappings | Only when an external client needs that contract |
The log remains the source of truth. Projections, query indexes, working state, graph data, run status, and agent registries are derived views or recorded conventions, not independent stores synchronized by application glue.
Envelope anatomy
Every typed agent record carries one named-field CBOR AgentEnvelope. The Apache Iggy binding keeps only the information needed before decoding out of band.
Each field has one authoritative location. An agent record stamps agdx.ct, agdx.av, gen_ai.conversation.id, and optional agdx.to outside the envelope.
The envelope owns source, cause, correlation, deadlines, idempotency, operation details, and body. Generic records may use the wider provenance header set.
command {
kind: command
record: 01J...
conversation: 01J... # partition key and trace identity
source: planner # a claim unless verified
target: summarizer
correlation: 01J... # request and reply pairing
operation: summarize
body: <bytes> # decoded using agdx.ct
signature: <optional>
}| Field family | Fields | Purpose |
|---|---|---|
| Identity and routing | kind, record, conversation, source, target | What this is, who claims to have sent it, where it belongs |
| Causality | cause, cause_at, correlation | Parent record, optional native log position, request and reply pairing |
| Chunk lifecycle | channel, sequence, last, finish_reason | Ordered streaming and deterministic reassembly |
| Execution | operation, tool, task_state, deadline_micros, idempotency_key | What is happening and which safety constraints apply |
| Content | body, content type header | Opaque payload bytes and their codec |
| Accounting and policy | usage, metadata | Advisory token usage and pinned policy or routing context |
| Evolution and integrity | must_understand, signature | Strict feature handling and optional verified authorship |
Machine ids are 128-bit values displayed as 26-character Crockford base32 strings. In the CBOR envelope they are fixed 16-byte big-endian byte strings. cause is the portable parent identity. cause_at is an optional Apache Iggy log-position locator for efficient local navigation.
Legal message shapes
The kind determines which fields are required or invalid. The wire validator, SDK constructors, and receivers all enforce the same matrix.
| Kind | Required core | Meaning |
|---|---|---|
command | record, conversation, source, correlation, body | Requests a reply or an effect. A fire-and-forget command is invalid |
response | record, conversation, source, correlation, body | Answers the command carrying the same correlation |
event | record, conversation, source, body | Announces something and expects no reply |
chunk | conversation, source, correlation, channel, sequence, body | Carries one ordered part of chat, reasoning, or tool_args |
status | record, conversation, source, operation | Carries task, card, progress, quarantine, or unquarantine state |
error | record, conversation, source, correlation, body | Terminates a request, and optionally a chunk channel, with a typed error |
status with operation task also requires a correlation and task state. A chunk requires its purpose on sequence 0, forbids the purpose on later chunks, and carries usage only on the terminal chunk. Construct envelopes through the typed SDK verbs instead of assembling raw maps.
Command and stream lifecycle
A chunk stream is grouped by channel and ordered by sequence inside one conversation partition. Reassembly starts at zero and drops duplicate sequences. A gap ends the stream. Only the first terminal is accepted.
Offsets provide resume state. Reader-local gap and abandoned outcomes are never written back to the raw log.
Produce the same command in every SDK
const conversation = ConversationId.new()
const correlation = CorrelationId.parse(
conversation.toString()
)
const record = await laser
.agdx(
AgentTopic.Commands,
AgentId.new("planner"),
conversation
)
.command(correlation, utf8("summarize incident 42"))
.withOperation("summarize")
.send()let conversation = ConversationId::new();
let correlation =
CorrelationId::from_u128(conversation.as_u128());
let record = laser
.agdx(
AgentTopic::Commands,
"planner".parse()?,
WireConversationId::from(conversation),
)
.command(
correlation,
b"summarize incident 42".to_vec(),
)
.with_operation("summarize")
.send()
.await?;conversation = ls.new_conversation_id()
correlation = ls.new_correlation_id()
record = await laser.agdx(
ls.Topics.COMMANDS,
"planner",
conversation,
).command(
correlation,
b"summarize incident 42",
operation="summarize",
)All three calls publish the same logical command envelope and return its minted record id. The worker replies with respond using the same correlation, or opens a chunk stream when it needs incremental output.
Delivery, ordering, and replay
- At least once: handlers commit their consumer offset only after successful processing. A crash before the commit causes replay.
- Ordered per conversation: agent records use the conversation id as the partition key. Independent conversations can run across partitions in parallel.
- Exactly once is application behavior: use an idempotency key and a durable processed-key store around the business effect. It is not a wire delivery mode.
- Acknowledgement is an offset commit: AGDX adds no ack, nack, visibility timeout, priority, or broker-managed retry protocol.
- Dead lettering is explicit: the runtime publishes a capsule containing the original encoded envelope, source position, reason, attempt count, and optional detail.
- Large bodies use claim-check:
BodyRefnames external bytes and pins their size and SHA-256 digest, so a consumer verifies what it retrieves.
Trust boundary
Agent-written fields are claims until verified. Routing does not grant access.
| Signal | Safe interpretation |
|---|---|
source, target, usage, cost, policy metadata | Advisory on a shared unsigned topic |
| Verified envelope signature | Proves the enrolled principal signed the canonical envelope |
| Signature context | Also binds the out-of-band content type and agent version |
| Write-exclusive Iggy topic with ACLs | Establishes authorship through topology |
| Server-stamped user on managed commands | Trusted input to capability RBAC |
| Fence token checked by the state store | Rejects a stale lease holder before an effect |
target narrows routing but does not grant access. Token usage and cost are advisory accounting. A privileged control fact such as quarantine requires a valid operator signature.
Delegated work carries on_behalf_of inside signed envelope metadata. Authorization intersects the agent's grants with the user's grants.
More than agent messages
AGDX defines three data surfaces over one authenticated connection.
| Surface | Operations | Source of truth |
|---|---|---|
| Streaming | publish, consume, typed envelopes, replay, batching | Apache Iggy log |
| Materialized views | projections, schemas, query, change feed, graph traversal | Deterministic views derived from log records |
| Working state | key-value, compare-and-swap, fenced writes, leases, copy-on-write forks | Ordered mutations recorded through the platform |
Memory is a facade over those primitives, not a separate wire command family. remember publishes a typed memory record, recall reads the best available view, graph relationships use the graph surface, and context scopes apply the conversation lens consistently.
Capability negotiation
At connection time the SDK probes hello. The reply advertises the managed plane, per-surface operation versions, feature bits, materialization backends, and the deployment's resolved AGDX topic topology.
- An unavailable surface returns a typed
Unsupportederror. - A mismatched operation version fails locally before the request is sent.
- Additive behavior that could be silently ignored, such as stronger query consistency, is refused unless explicitly advertised.
- Subfeatures default off. A server must never advertise a guarantee it cannot honor.
- Standalone VSR-enabled Apache Iggy serves streaming and the log-backed agent fabric. Managed commands require an advertised capability. Laser Stack supplies those capabilities through
laser-plane.
This makes capability discovery part of correctness, not a marketing feature list. Applications can branch on laser.capabilities() without probing through failures or manually supplying a capability set.
Interop is an edge mapping
External agent protocols do not replace AGDX inside the system. A bridge translates at the boundary, while internal agents and services continue to read and append durable records.
The runtime path stays compact: external client, edge adapter, AGDX command or event, internal agent, AGDX reply or stream, then edge response mapping. The durable log remains between every internal producer and consumer.
| External contract | AGDX mapping |
|---|---|
| A2A message and task lifecycle | Command on a fresh task conversation, then response, error, and task-status records |
MCP tools/call | Command carrying the tool name and correlated response or error |
| AG-UI chat, reasoning, and tool calls | Chunk streams rendered as frontend events |
| AG-UI shared state | state_snapshot and RFC 6902 state_delta events |
| Human approval | Ordinary command and response through request_input and respond_input |
Map shared semantics into envelope fields. Keep protocol-specific data byte-identical in the body. Every bridge appends its id to bridge_hops and rejects messages that already contain it. This prevents translation loops. See Interop for the bridge APIs.
Encoding and conformance
Independent ports interoperate by preserving a small set of strict invariants:
- Every wire payload uses named-field CBOR through one encoder.
- A payload is exactly one CBOR item. Trailing bytes, corrupt known fields, and wrong known types fail decoding.
- Unknown fields are ignored for additive evolution. Unknown dictionary codes remain representable instead of failing the whole record.
- Optional fields are omitted, not encoded as empty placeholders.
- Envelope ids are 16-byte big-endian values. The duplicate Apache Iggy
Uint128routing header uses Iggy's little-endian typed representation. - The per-kind validity matrix is checked before publish and after decode.
- Positive fixtures pin accepted bytes. Negative fixtures pin rejected shapes. Decode, validate, and re-encode must remain byte-identical.
The runtime-free laser-wire crate owns the contract and golden fixtures. All clients use the same envelope rules and scenarios.
Transport, cryptography, clocks, and ID generation remain outside this crate.
Status
AGDX is pre-1.0. The built core and VSR Iggy binding define the current contract. Roadmap sections are proposals. Breaking wire changes require an operation-version decision and fixture updates in every SDK.
Related
Laser Stack
Run the VSR binding and managed plane locally
Fabric
Reliable agent execution over AGDX
Interop
A2A, MCP, and AG-UI edge mappings
Governance
RBAC, effect policy, and durable approvals
State
Key-value state, CAS, locks, and forks
Views
Projections, schemas, and query
Graph
Knowledge graph and traversal