Intercom

In plain words: Agent-to-Agent Line sessions

Partial 6 min read 5 glossary terms 4 connected pages
The short version written for the Snayu team

How to ask another independent agent (a peer) to perform a public task over the Agent-to-Agent Line (A2A/Intercom), using a lab script with signed identities, strict policy limits and durable task records.

Why read it: Read this before working on A2A features or running the Intercom lab session.
  1. 1The peer's reply is foreign data; it can never authorise a local tool, action or another task.
  2. 2Operator and workload identities are separate; peers must be enrolled explicitly with their public key.
  3. 3Policies have no wildcards; empty selectors deny. Database migration 0022 adds seven Intercom tables.

Partial Bounded outbound public-text sessions exist; private context and incoming A2A server do not.

Words on this page, decoded click one for its card

Long-term MemoryPlug-in AreaAgent-to-Agent Line
Where it sits in LychD

Agent-to-Agent Line Intercom / A2A

Lets your assistant ask another independent assistant for help. Replies are treated as foreign data.

It's like: Calling another company's helpdesk: useful answers, but they cannot authorise anything in your office.

Click a dot to open that part's card.

The original text Underlined words open their plain-English card.

IntercomAgent-to-Agent Line asks another sovereign agent to perform a public task. The receiving peer owns its models, tools and execution. Its reply is attributed foreign data; it cannot authorize a local tool, game action or another task.

State of Work owns delivery. The bounded outbound-public-text@1 profile provides an explicit operator session. The separate native-public-peer@1 profile adds an explicit RunJob Record/GraphStep Map lab below. Private ContextBriefing Pack, voice input and automatic fallback remain separate work. Neither session starts a Minecraft client, model or incoming A2AAgent-to-Agent Line server.

Prepare the two identities

Prepare operator identity and workload identity separately. The installation's dedicated local-access credential authenticates the operator; a configured Ed25519 signing key identifies the local workload. Trusted host configuration must also enroll the remote peer's immutable identity and public verification key. Reachability, a TLS certificate, or an advertised Agent Card cannot perform that enrollment.

The peer must implement this profile's required signing extension. An unsigned stock A2AAgent-to-Agent Line SDK route is useful for baseline protocol testing, but cannot satisfy the protected session. The qualification used the official SDK's real dispatcher and task store with explicitly test-only signing middleware; the middleware is not an upstream SDK feature.

Apply the normal database migration gate before using the session. Revision 0022 adds the seven IntercomAgent-to-Agent Line custody tables. It refuses downgrade while any retains a row, including unused capacity. The session itself has no migration or reset command.

Keep database credentials and signing-key bytes with their trusted host secret owners. Supply LYCHD_INTERCOM_DATABASE_URL and an absolute LYCHD_INTERCOM_SIGNING_KEY_FILE in the process environment. Put only public configuration in the file passed below:

uv run --locked python scripts/intercom_lab.py --config /absolute/public-config.json

The file contains workload_id, signing_key_id and policy. The policy is the exact PeerPolicy.record() shape: generation, explicit actions, purposes, categories, task_schemas, peers, endpoints, four limits, and bounded declaration_seconds, task_seconds, network_seconds. Each limit, keyed by host, purpose, peer or task, supplies uses, application_bytes, network_bytes. Empty selectors deny; there are no wildcards. The eight independent actions are enroll, classify_public, submit, poll, cancel, read, rotate, revoke.

Capacity survives changes to configuration labels, task ids, and credentials. Changed ceilings refuse rather than resetting it. A new policy generation immediately invalidates old live authority; before a later startup activates the new generation, trusted host composition must establish the matching durable policy. The session supplies no policy-update command.

Author, submit and read

Each input line is one JSON object. enroll takes peer_id, purpose, task_schema, optional category (default public-task), a key record, and an endpoint object with address, hostname, port, path, ca_file. The numeric address and explicit CA file are mandatory. The key supplies key_id, public_key_pem, issuer (peer UUID), protocol: "rfc9421-ed25519@1", audience (workload UUID), assurance: "operator-enrolled", and timezone-aware valid_from and expires_at. The service independently pins its actual workload key binding; changing that key on restart cannot silently reuse the enrollment.

After enrollment, target-bearing commands use the exact HTTPS URI, including its configured port, as endpoint. They also carry peer_id, purpose, task_schema and optional category. For example, with identities and selectors already admitted in public configuration:

{"operation":"declare-public","peer_id":"00000000-0000-0000-0000-000000000002","purpose":"public-summary","task_schema":"public-text@1","endpoint":"https://peer.example:443/a2a/jsonrpc","source":{"text":"Summarize this public task description.","public_assertion":true}}

This dedicated field is an attributed human assertion of authored, public text. It is not PII detection or proof that text was never pasted. Known restricted influence, unknown lineage, local-only data and other source kinds refuse. Chat, microphone input, model output, files and private ContextBriefing Pack do not enter this producer automatically.

declare-public returns a declaration_id whose exact live declaration belongs to this startup. Use it once:

{"operation":"submit","declaration_id":"the-returned-declaration-uuid"}

Submit returns status and the local task_id. poll, cancel and read carry that task_id plus the same exact target selectors. Submit and poll return status only. Use the separate read action to consume a retained result. The result remains authenticated-foreign-data.

Every physical operation is separately charged before contact: one use, its complete application request size and a conservative 512 KiB network allowance. Actual accepted network bytes are recorded separately and do not refund the reservation. Stable scopes are the host, exact purpose, peer identity and peer-plus-schema task family.

Uncertainty, cancellation and restart

An uncertain intent commit, claim commit, send acknowledgement or response authentication returns {"error":"unknown","task_id":"..."}. Retain that identity and inspect it under fresh read authority. A truly uncommitted task can be absent. Never automatically declare or submit a new task to replace an unknown one: the peer may already be executing it.

A known foreign task id permits a fresh, authorized poll. An unknown id cannot be invented or discovered by silently resending. Restart restores neither declarations nor live transmission claims; it can explicitly reconcile known tasks with fresh authentication and current policy.

Cancellation first closes local result adoption, then asks the peer to cancel. Read its local disposition separately from the authenticated foreign observation. An acknowledgement establishes neither rollback nor process containment. If a task already reached an admitted terminal, it remains readable under current authority and refuses late cancellation.

rotate takes the exact target and a new remote key record; the old key version is retired before the persistence wait. revoke fences local handoffs before awaiting durable revocation. An uncertain authority mutation remains fenced. No session command deletes history, refunds capacity, fetches artifacts, streams, discovers endpoints or selects another peer, provider or language.

This profile has one control process and event loop. Cross-process revocation, hostile same-UID containment, general remote IAM and private-input anonymization are outside its delivered boundary.

Native public peer Run

Apply revision 0023 through the normal migration gate. It binds a peer task to its exact RunJob Record, station, request, pinned PatternWorkflow and actual Step/occurrence. It refuses inconsistent legacy wait owners and refuses downgrade while native task, RunJob Record, closure or reauthorization evidence remains. The existing 0022 retention rule still applies to all seven IntercomAgent-to-Agent Line tables.

Use the same dedicated operator credential, workload key and exact public configuration:

uv run --locked python scripts/intercom_native_lab.py --config /absolute/public-config.json

Native policy additionally selects admit, adopt, resume and inspect. These are independent actions; they do not grant submit, poll or read. Existing enrollment commands remain available. This lab uses the actual RunEngine, GraphStep Map, worker function and PostgreSQL checkpoints with an explicit process-owned delivery queue. It supplies no SAQ broker, capability or hardware transition.

submit-public-run takes the existing public source and exact target selectors plus a stable request_id UUID. Supply an existing session_id when retrying that same admission; omitting it creates a new session. The RunJob Record prepares one immutable task without contact, checkpoints it and parks as awaiting_peer. Reusing a request with changed text or target refuses.

tick takes run_id, performs at most one submit or poll, and executes any admitted successor. Repeat it explicitly while the task is pending. A correlated terminal can resume the GraphStep Map once; the reply remains foreign data. status exposes local status, task identity and binding selectors. A completed reply additionally requires current independent read authority. cancel-run closes local adoption and awaits local exchange retirement; visible remote uncertainty is retained. Commands are serial and network operations have their configured finite deadline. An already settled unknown, expiry or remote noncompletion returns an explicit outcome with local status; the next operator command remains usable. Other worker and authority failures are not converted into a successful settlement.

After restart, the lab restores durable evidence but needs fresh authentication and live peer permission. Call reauthorize-run with run_id, the returned task_id and binding_digest, and the exact actions selected from submit, poll, read, adopt, and resume. An unclaimed first submit also needs reaffirm_public_source: true.

Reauthorization preserves the original task, body, and expiry. It cannot refresh the request or replace an uncertain submit. If a claimed task lacks a foreign identity, reconcile its local exchange before following the explicit unknown failure route.

The lab has no incoming peer, automatic relay loop, private-input producer, voice command path or Blockworld effect. Its process restart and local cancellation checks do not prove remote process containment, broker recovery or cross-process revocation.