26. A2A
In plain words: Design rule 26: Agent-to-agent calls
Defines the Agent-to-Agent Line (Intercom): how one independent LychD install asks another for bounded work, sending requests and results, never weights, credentials or internal state. The receiver decides how to do the work.
- 1Exchange intents, not tensors: only bounded values or artifact references cross the wire.
- 2Delay makes it durable delegation with an inbox and outbox, never a remote function call.
- 3The first outbound profile is signed public text only over A2A JSON-RPC; peer trust is never self-enrolled.
Partial State of Work: a narrow outbound A2A profile works; the full Intercom described here is still Designed.
Words on this page, decoded click one for its card
Context
A sovereign node can request bounded labor from another sovereign node. Their identity, memory, tools, hardware, and policy remain separate; delay makes the exchange durable delegation, never a remote function call.
Status
IntercomAgent-to-Agent Line is Designed. The transport-neutral envelope, verification, policy, replay, lifecycle, terminal-adoption, and durable inbox/outbox contracts below are accepted law, not delivered source. State owns delivery. The common contract is transport-neutral; the bounded outbound profile below selects and must test its own external revision.
Decision
IntercomAgent-to-Agent Line will carry versioned asynchronous labor inside VesselEngine Room using existing LychD identity, persistence, GraphStep Map, dispatch, and workers. The exchange sends intents, not tensors: bounded values or immutable ArtifactRefs go in; typed values, refs, or explicit non-completion come back. The receiver decides whether and how to work on its own iron. No weights, KV cache, Python object, provider client, live toolset, local SigilID Badge, capability grant, GraphStep Map state, or infrastructure command crosses the wire, and no additional control plane is introduced.
An ordinary peer request names an authorized public task schema. The receiver maps that task to its own exact ScrollWorkflow Version and local resolution; the sender neither selects nor learns that decomposition. A portable ScrollWorkflow Version or teaching bundle may cross only as a separately typed, inert artifact. It is not the receiver's GraphStep Map and cannot force local admission, binding, acquisition, or execution.
A public task schema may carry ordered content-language preferences, original-language facts, and a declared finish boundary such as still, motion, or packaged result. Canonical task, SpellStep, ScrollWorkflow Version, field, status, and artifact identities remain untranslated; peers may localize their own labels without changing signed bytes. Unsupported language, translation policy, or finish depth is an explicit incompatibility or refusal, never permission to substitute a language, engine, model, or smaller result. Different typed values create another task or InvocationJob Request; a changed score remains another ScrollWorkflow Version revision.
Use IntercomAgent-to-Agent Line when the receiver is a sovereign task owner, not as a decorative wrapper around a
model request. If the sender selects provider/model and needs one inference operation, the road is
a PortalCloud Model. If an operator-controlled foreign runtime receives a bounded workspace and tool loop,
the road is a delegated AgentJob. A2AAgent-to-Agent Line must not proxy a human subscription, provider credential,
local tool inventory, or hidden fallback chain. The sender binds an A2ATarget containing the
enrolled peer, task schema, adapter, and endpoint in a fresh exact egress decision; the receiver's
private model and decomposition remain its own affair.
Peer identity
A peer is cryptographically verifiable network principal, neither Persona nor local SigilID Badge, with trust record, keys, and authorization. Public discovery is an untrusted advertisement of exact protocol/profile versions, endpoints, authentication methods, public task schemas, public Spell-contract references, content limits, and deliberately coarse price or availability. A claim means only that the peer advertises it; it proves neither local binding, present availability, authority, nor admission. An authenticated extended card or query may reveal peer-specific contracts, ceilings, bounded availability, quote eligibility, or teaching policy.
Discovery never enumerates Personas, SigilsID Badges, grants, installed private ScrollsWorkflow Versions or learned SpellsSteps, local implementation revisions, GraphStep Map state, tool/model inventory, backend topology, Tether coordinates, live queues, artifact bearer URLs, invoices, or payment proofs. A public key repeated inside an unauthenticated card cannot enroll its own trust.
The first interoperability candidate is the
A2A 1.0 Agent Card at
/.well-known/agent-card.json, plus a versioned LychD extension for exact task and public
Spell-contract metadata. Intentionally public known SpellsSteps appear through the card's skill and
extension vocabulary; private catalogue truth does not. The adapter owns document version,
extension URI, authentication, canonicalization, and conformance fixtures; Core does not invent a
parallel /.well-known/lychd-* path. Until that adapter is selected and tested, this is protocol
design rather than a shipped discovery claim.
Tether and Veil are transport and ingress layers, not alternative trust models. A conservative first route is Veil-compiled HTTP exposed only through Tether, then WardSecurity Desk authentication and policy, then IntercomAgent-to-Agent Line envelope verification and replay fencing. Public Veil exposure is a later profile.
The Reach deployment profiles are outbound A2AAgent-to-Agent Line clients by default. In home-only and edge/home, only the authoritative home egress service may call a peer; the VPS edge cannot. In standalone VPS, its local authoritative egress service calls the peer. Invoking one enrolled, authenticated, task-authorized peer requires a fresh exact egress decision, but no published Agent Card, callback, Tether, or public Veil. The first receipt pins polling and disables streaming and push. A later callback-only route may update only an existing outbound task; accepting new foreign work is a separate A2AAgent-to-Agent Line server profile with WardSecurity Desk, durable IntercomAgent-to-Agent Line inbox/outbox, Workers, and its own result path. Incoming peer work can never invoke Reach's Discord delivery.
Outbound public-text JSON-RPC profile
The first construction profile, outbound-public-text@1, binds
A2A v1.0.1, commit
3303592588e388e62e0f69f701af531d2f4e3991, JSON-RPC with A2A-Version: 1.0.
Its required extension URI is
https://github.com/hexanomicon/lychd/blob/main/docs/adr/26-a2a.md#peer-task-jsonrpc-1.
That URI identifies this versioned contract; availability or a self-advertised key never enrolls
trust. The upstream extension rules
permit required message-signing extensions. RFC 9421 Ed25519 is this profile's explicit requirement,
not a standard mandatory A2AAgent-to-Agent Line authentication scheme or an invented HTTP Authorization scheme.
An authenticated local operator separately authorized to classify a source may author one bounded public-text task through the dedicated declaration path. This is an attributed assertion, not PII detection or proof that text was never pasted. Known restricted influence, prohibited categories, unknown lineage and local-only constraints refuse. Ordinary chat, ASR, model output, private ContextBriefing Pack and serialized classification shapes inherit no declaration. This first transport profile uses an explicit operator-operation identity, never a fabricated RunJob Record, Cut or peer wait. The native binding below adds a genuine RunJob Record owner; private-input transformation remains a separate acceptance gate.
Only SendMessage, GetTask and CancelTask are admitted. Submit uses one user text part,
returnImmediately=true, historyLength=0, the exact configured public task schema and
acceptedOutputModes=["text/plain"]. Polls also request zero history. The receiver assigns
the foreign task id; a direct Message result is incompatible with this durable-task profile.
No task listing, follow-up turn, raw/URL part, artifact fetch, push, streaming, discovery or
automatic version, endpoint, credential, provider or language fallback is admitted. Typed
inline text results remain quarantined foreign data and confer no tool or game authority.
The semantic request body is sealed once. Every physical attempt prepares fresh signature timestamps, nonce and attempt identity over its exact UTF-8 body digest and HTTP context, then seals the complete HTTP representation before a fresh egress decision. This is not portable JCS: verification hashes actual body bytes before parsing. Request coverage includes method, complete target URI, content type/digest, protocol/extension, workload sender, recipient, task schema, local task and physical attempt. The signed response binds status, body digest, those expected roles and identities, and the exact pending request URI, content digest and nonce. One signature, the exact component/parameter sets, bounded freshness and matching current enrolled key are mandatory. Duplicate or ambiguous critical headers, unknown profile fields and content encoding refuse; no request-component feature unsupported by the installed verifier may be assumed.
The profile bounds the complete application request to 64 KiB, body to 48 KiB, headers to 8 KiB and 32 fields; response body to 64 KiB, inline artifacts/parts to eight each, and foreign ids to 128 visible ASCII characters. Signature validity is at most 30 seconds, with no future-created or expired signature admitted. Each task has an independently bounded lifetime and each network operation one absolute deadline no longer than 30 seconds. HTTPS uses an explicitly configured trust root, hostname, numeric peer address, port and exact path, without DNS, redirects, ambient proxies or implicit contact retry. The actual numeric peer is verified after connection.
Base A2AAgent-to-Agent Line makes SendMessage deduplication optional and supplies no guaranteed message-id lookup. This profile never resends an uncertain submit or invents a foreign task id. A lost send reply retains unknown remote execution. A known foreign task id permits a fresh authorized poll; uncertainty in a read poll cannot authorize another submit. Cancellation acknowledgement is an authenticated observation of foreign state, not proof of rollback or process containment. Local expiry, revocation and closed adoption remain distinct from the peer's terminal state.
Acceptance requires the callable production submit/poll/result path, durable task/outbox and
transmission custody, real installed cryptography, current WardSecurity Desk authority, complete-wire gating,
and an independent endpoint implementation. The official Python SDK 1.2.3, commit
44b2f761a99123370237afe6c828f4cd2a50c402, is a conformance candidate in a separate locked test
environment; its unsigned route alone proves neither this extension nor durable peer behavior.
Identity helpers, a dormant registry or recorder-to-HTTP substitution do not pass this gate.
Envelope
Every message names protocol/schema versions; sender and recipient; message/task/idempotency ids;
issued/expiry times; nonce/replay fence; task type; bounded content/refs; and authentication over
adapter-pinned canonical bytes. LychD portable artifacts follow
Workflow serialization; an A2AAgent-to-Agent Line adapter must separately pin
its envelope profile and signature input. context_id only correlates: continuation additionally
needs same peer, compatible schema, explicit authorization, and unexpired task relation. Unknown
field/version, identity/signature mismatch, expiry, and same id with changed content fail closed.
Authentication, revocation, and authorization are rechecked at replay, queue, start, resume, effect, result egress, and adoption boundaries appropriate to the task. Returning an old idempotent result cannot treat a now-revoked peer as presently authorized.
Durable task protocol
Admission writes one local peer-task record before work:
RECEIVED → ADMITTED → QUEUED → RUNNING → terminal
SUCCEEDED, REFUSED, FAILED, EXPIRED, REVOKED, CANCELLED, and LOST are distinct terminals. Transport is at-least-once, so inbox admission, claim, adoption, and outbox delivery are idempotent; repeat same envelope returns same identity, changed-content reuse is a security fault. Every physical redelivery retains that exact envelope and external/idempotency identity but obtains a fresh byte-time EgressDecision and consumes its bounded disclosure use; it is not a new semantic peer task or Privacy CutPrivacy Filter. Polling, callback, and stream may return results, but none is sole truth. Callback needs exact egress policy and peer revalidation; silence means neither refusal nor success.
Graph and Long Sleep
Outbound labor occupies one opaque station. The InvocationJob Request can enter Durable StasisPause only after the request and outbox intent commit. It then releases local leases and waits for authenticated, correlated terminal adoption. Its checkpoint retains the peer-task id and local continuation, never foreign state. Expiry, revocation, and loss follow declared PatternWorkflow routes; an unknown remote effect cannot be silently repeated.
Native public peer station
native-public-peer@1 extends the public-text profile through the existing serial GraphStep Map, RunJob Record
ledger, delivery relay and durable checkpoint owner. It adds a distinct PeerTaskNode and
AWAITING_PEER, not an AgentJob or another orchestrator. A dedicated authenticated admission
pins the actual RunJob Record, PatternWorkflow digest, station, stable caller request identity, original public
source, exact target and lifetime. That source is still an explicit operator assertion; a RunJob Record,
SigilID Badge, voice transcript or retained declaration shape cannot classify it public.
Prepare one immutable task and outbox without contact, checkpoint that exact task, then atomically park its RunJob Record and settle the claimed delivery. Only the committed exact peer wait permits the relay's first send. Same semantic occurrence returns the same task, body and original expiry; changed reuse refuses. A committed or uncertain submit claim is permanent, including when zero accepted bytes are known. No foreign id means unknown remote execution, never another submit. Known foreign ids permit independently authorized bounded polls. Network work holds no RunJob Record lock or local capability lease and does not keep the GraphStep Map worker resident.
The single current wait owner survives re-admission and claim. Canonical task/terminal custody, exact RunJob Record/source/PatternWorkflow ownership and current live authority jointly permit one owner-specific resume CAS and one successor delivery. Caller-supplied terminal dictionaries cannot authorize that transition. The first resumable checkpoint must bind the same peer station and task before any node executes. Only a matching created checkpoint plus committed preparation can recover the pre-park crash window; missing, running, error or ambiguous cursors never authorize replay.
Live RunJob Record permission belongs to the process-owned peer service and actual current operator marker; it is neither returned nor persisted. Restart creates no live permission. An explicit fresh authenticated reauthorization rereads the immutable RunJob Record/task/source/target relation under current policy. First activation of a provably unsent task additionally requires a fresh public assertion over its exact original source. This never redeclares the task, changes its expiry or rearms a claimed, closed, revoked or expired occurrence. Standalone operator reconciliation cannot itself resume a GraphStep Map. Current RunJob Record and claim fences apply at each physical handoff, adoption, resume and station re-entry; historical admission alone grants none of those actions.
Local cancellation closes adoption for every task bound to the RunJob Record, including preparation before
park, and proves retirement of all locally owned exchanges before local terminal commitment.
It requires no foreign id or usable remote credential. CANCELLED ends the local InvocationJob Request and
its effect/adoption authority; it claims neither rollback nor containment of a sovereign peer.
Retain visible, attributed remote outcome uncertainty independently of checkpoint cleanup.
Remote CancelTask/GetTask is separately authorized, bounded reconciliation; an acknowledgement
is not containment proof. Late authenticated replies may retain correlated remote observations
but cannot reopen adoption or enqueue a continuation. Local AgentJob and process containment
requirements are unchanged.
This is accepted construction law. Delivery requires a coordinated real RunJob Record/GraphStep Map, PostgreSQL checkpoint/task/delivery, production authenticated transport and independent endpoint passage, including actual local-process restart with fresh authentication, one resume, unknown-submit non-repetition, cancellation races and independently observed local exchange retirement.
Incoming work is an ordinary local admitted run under peer authority. DispatcherTraffic Controller and OrchestratorStage Manager may use their local powers; peer receives no internal handles.
remote is an origin, trust, and authority qualifier—not a fourth service class. A peer may request
foreground, deadline-windowed, or spare-capacity treatment, but receiver policy maps or clamps that
request under peer identity, quotas, local priority, and resource truth. The remote provenance
remains attached whichever tempo is selected.
Missing Spells and teaching
The receiving policy handles an unknown or incompatible SpellStep explicitly:
| Policy | Result |
|---|---|
| Refuse | Return a bounded incompatibility result naming only the safe public requirement. |
| Request teaching | Ask for an attributed teaching bundle under exact peer, task, size, content, license, and expiry policy. |
| Trusted exact contract | Continue only when the local catalogue admits that exact public SpellStep contract and an exact local implementation binding. |
A receiver-owned policy configuration selects among these outcomes by exact peer, task/content class, and SpellStep identity. A sender may ask to teach, but its request cannot select the policy, authorize acquisition, or widen the accepted material.
A teaching bundle is a separately identified, size-bounded, content-addressed manifest over quarantined foreign material, never a live node, package, tool, or registry write. It may contain a public contract, examples, implementation or artifact references, provenance, license duties, and claimed evidence. Assimilation may turn it into a local candidate; SpellweaverWorkflow Engine validates any contract or ScrollWorkflow Version candidate while the appropriate Extension, Packaging, Security, Evolution, and effect owners retain implementation and activation authority. The original peer task remains refused or otherwise terminal. A successful lesson permits only a new envelope and new InvocationJob Request, so teaching cannot rewrite an in-flight ScrollWorkflow Version or inherit its authority.
Paid work and paid teaching are distinct purchased resources with distinct quote and idempotency identities. Toll may quote only after task or teaching eligibility; settlement neither authenticates the peer nor admits work, teaching, publication, or activation.
Sovereignty wall
| Boundary | Question |
|---|---|
| Identity | Known, authenticated, current, unrevoked peer? |
| Task | This task and content class authorized? |
| Resources | Local capacity at priority/deadline? |
| Tools | Exact task toolset? |
| Artifacts | Read, retain, return each blob? |
| Egress | Result and callback may leave? |
| Economics | Quote/bounty expressly admitted? |
Security egress law keeps source-manifest and influence-label digests plus opaque restricted lineage references in durable evidence, never raw subjects or source spans, and requires an exact peer/callback decision per attempt. Trust never declassifies. MagusYou, the Operator work may outrank peer labor only with peer-visible paused, revoked, or failed settlement; killing work without a result is forbidden. Resource revocation never widens tool/data authority.
Legion and Necropolis
Legion delegates to owned nodes. Enrollment may narrow shared administration, but the Node Agent retains identity, fencing, revocation, and application authorization, with no Master SigilID Badge or raw host command. Necropolis relates sovereign peers whose foreign GraphStep Map, memory, models, and priors remain private. Both exchange bounded labor without thereby assimilating the other body.
HTTP is first candidate; Nostr/relays remain candidates behind same envelope/inbox/outbox law. NAT, encryption, and relay signatures require adapter proof. Legion extends one MagusYou, the Operator over owned iron; Necropolis begins at ownership's edge.
Consequences
Accepted
- Sovereign execution and local policy survive durable at-least-once exchange.
- Standard compatibility remains possible without library capture.
Cost
- Identity, replay protection, persistence, callbacks, schemas, and reconciliation are security work.
- Indeterminate outcomes are irreducible until independent interoperability proves the contract.
Acceptance gates
There is no envelope or ledger implementation, route, peer registry, discovery, cryptographic implementation, authenticated durable inbox/outbox, callback handler, transport adapter, RunJob Record bridge, or inter-node receipt.
IntercomAgent-to-Agent Line needs pinned hostile-envelope fixtures; rotation/revocation/expiry/replay proof; durable inbox/outbox restart recovery; idempotent admission/adoption; SSRF-safe callback/artifact policy; GraphStep Map park/cancel/timeout/re-entry; peer-visible preemption; and one independent endpoint. An adapter that supports SpellStep compatibility or teaching additionally needs downgrade, unknown- revision, false-claim, oversized-bundle, provenance/license, quarantine, and no-live-mutation proof.