{"slug":"oip-vs-a2a","title":"OIP vs A2A: asking vs proving","body":"Two protocols keep getting mentioned in the same breath because both have \"agent\" in the pitch. They do not compete. A2A is a wire protocol for conversations **between** agents that do not trust each other's internals. OIP is an execution and accountability substrate **inside** one build. Confusing them costs you real architecture time, so here is the honest comparison, spec detail included.\n\n## What A2A actually is\n\nAgent2Agent (A2A) is the protocol Google announced in April 2025 and donated to the Linux Foundation in June 2025, with 100+ vendors signed on. It standardizes how one agent asks another opaque agent to do work:\n\n- **Discovery — Agent Cards.** An agent publishes a JSON card (canonically at `/.well-known/agent.json`) declaring its identity, endpoint, version, skills (named capabilities with descriptions and example prompts), supported input/output modes, and auth requirements. A client agent reads the card and decides whether to engage. The card is a promise, not a proof — nothing in A2A verifies that a skill does what it claims.\n- **Transport.** JSON-RPC 2.0 over HTTPS. Core methods: `tasks/send` (one-shot), `tasks/sendSubscribe` (with Server-Sent Events streaming), `tasks/get`, `tasks/cancel`, plus push notifications to a client webhook for long-running work.\n- **Unit of work — the Task.** Every exchange creates a Task with a lifecycle: `submitted → working → input-required → completed | failed | canceled`. Tasks carry **Messages** (role user/agent) composed of **Parts** — TextPart, FilePart, DataPart (structured JSON) — and produce **Artifacts**, also made of Parts.\n- **Opacity by design.** Agents never share memory, tools, or internal reasoning. You send a message; you get status transitions and artifacts. What happened inside is invisible, on purpose — that is what lets Salesforce talk to SAP without either exposing internals.\n- **Enterprise auth.** The card declares auth schemes aligned with OpenAPI conventions — OAuth2, OIDC, API keys, mTLS. Identity is handled at the HTTP layer, not inside the payload.\n\nWhat A2A deliberately leaves out: any record of what an invocation cost, any receipt you can audit later, any way to verify a claim in the card, any repair semantics when a task silently produced garbage. The task history lives with whichever server ran it, in whatever form it likes.\n\n## What OIP actually is\n\nThe Object Invocation Protocol is this build's substrate. Its unit is not a conversation — it is the **work object**: a directory row (`fn`, `http`, `agent`, or `flow`) whose contract is its docstring (`WHAT / WHEN_TO_USE / ARGS / EX`) and whose behavior is invokable by anyone holding the right capability:\n\n- **Discovery.** `GET /api/dispatch?registry=1` returns every invokable object with its self-description; `?ask=<question>` answers \"how do I do X\" with the exact call. The registry is generated from the same rows that execute — it cannot drift from reality the way a hand-written card can.\n- **Invocation.** `POST /api/dispatch {key, body, actor}` — or GET `?invoke=KEY&body=…` for callers that can only open URLs. One envelope for every object type.\n- **The invariant loop.** resolve → validate → execute → **ledger** → respond with `data + _self + yield`. Every invocation writes full request and response to an append-only ledger (D1, overflowing to R2), stamped with actor and trace.\n- **Receipts.** Every response carries `links.receipt` → `GET /api/dispatch?receipt=inv_ID` returns the complete request, response, cost, and lineage of that exact invocation. This is the part A2A does not have at all: a third party can audit what happened without trusting the agent's memory.\n- **Lineage verbs.** `{replay: \"inv_ID\"}` re-executes a past invocation from its recorded input. `{key, body, repairs: \"inv_ID\"}` links a corrective invocation to the failure it fixes, in both directions (`repairs` / `repaired_by`). Failure is a first-class, queryable object.\n- **Yield accounting.** Every invocation records tokens in/out, cost in USD, and a material/waste flag. The build can tell you what a capability costs and which objects burn money without producing anything.\n- **Capability tokens.** Share tokens scoped to read / act / a single row / N uses — a capability, in the object-capability sense, not a session. A model holding a one-shot row token can fire exactly that object exactly once, and the ledger records it did.\n\nWhat OIP deliberately leaves out: multi-party federation. It is single-build by design — one directory, one ledger, one owner. There is no standard body behind it, no SSE task streaming, no cross-org identity story. It does not need one to do its job, which is making one build's every action provable.\n\n## The actual difference, side by side\n\n- **Unit** — A2A: a Task with a conversation lifecycle. OIP: an invocation with a receipt.\n- **Peer model** — A2A: opaque agents across organizations. OIP: objects inside one build.\n- **Discovery** — A2A: an Agent Card, which is a claim. OIP: a registry generated from the same rows that execute, which is live fact.\n- **Evidence** — A2A: task state only, held by whichever server ran it. OIP: an append-only ledger with full request/response and a receipt per invocation.\n- **Failure** — A2A: a `failed` state, then nothing. OIP: `repairs`/`repaired_by` lineage plus replay from recorded input.\n- **Cost** — A2A: out of scope. OIP: tokens and USD and a material/waste flag on every invocation.\n- **Trust** — A2A: auth at the door (OAuth2/mTLS), then faith. OIP: auth at the door, then proof after every call.\n- **Streaming** — A2A: SSE and push notifications. OIP: none — request/response plus async rows.\n- **Governance** — A2A: a Linux Foundation standard with 100+ vendors. OIP: one build's law.\n\nThe compressed version: **A2A standardizes asking. OIP standardizes proving.** A2A tells you how to hand work to a stranger; OIP tells you exactly what happened to every piece of work you ran, forever, with the receipt to show a judge.\n\n## Where they compose instead of compete\n\nIf this build ever needed to accept work from outside agents, the layering is obvious and non-conflicting:\n\n1. **A2A at the door.** Publish an Agent Card whose skills are OIP objects. `skills[].name` maps 1:1 to directory row keys; the card's examples come from each row's `EX:` line. The card stops being a promise and becomes a projection of the live registry.\n2. **OIP under the floor.** Every incoming A2A Task becomes an OIP invocation. The Task's `completed` artifact carries `links.receipt` as a DataPart — so the *external* caller gets what A2A never gives them: an audit trail. A failed Task maps to a ledgered failure that `repairs` can later link to.\n3. **Cost surfaces upward.** A2A has no cost semantics; an OIP-backed A2A server can put yield (`tokens`, `cost_usd`, `material`) in artifact metadata, which matters the moment two orgs bill each other for agent work.\n\nThat composition — A2A as the diplomatic protocol, OIP as the court record — is strictly stronger than either alone, and neither spec has to bend to do it.\n\n## The honest weaknesses, both directions\n\n- A2A's card is unverified marketing until the first task returns; its \"trust\" story ends at authentication. Interop demos have outnumbered production cross-vendor deployments so far, and the spec is young enough that task semantics still shift between versions.\n- OIP is one build's law, not a standard: no second implementation, no federation, and its opacity trade-off is inverted — everything is visible, which is correct for an owner auditing his own system and wrong for two competitors sharing a wire.\n- Neither protocol makes an agent good. A2A will faithfully transport a bad answer with a valid lifecycle; OIP will faithfully ledger a wasteful invocation with a perfect receipt. Quality is a layer above both — which is exactly why this build routes model output through review gates before anything is published.\n\n## The rule of thumb\n\nReaching across organizations to an agent you do not control: A2A. Running work inside a system where every action must be provable later: OIP. Building something serious: A2A at the boundary, OIP-grade receipts underneath — because \"the agent said it finished\" is a status, and a status is not evidence.\n","register":"oip_protocol","tags":["oip","object-invocation-protocol","protocol-specification","machine-native-json","dynamic"],"style":{"accent":"#16324f","measure":860},"claims":[{"id":"oip-c1","tier":"system","text":"The OIP article layer is generated from live directory rows, so it documents the objects that actually run the reference implementation.","who_claims":"system/oip_articles","source_ids":["oip-s3","oip-s4"]},{"id":"oip-c2","tier":"system","text":"The OIP operating path is caller to directory object to dispatch runner to invocation ledger to receipt.","who_claims":"system/oip_articles","source_ids":["oip-s1"]},{"id":"oip-c3","tier":"system","text":"Every executable capability in the reference implementation is reachable as an OIP object with a human article, a machine document, invocation history, and receipt path.","who_claims":"system/oip_articles","source_ids":["oip-s2","oip-s3"]},{"id":"oip-c4","tier":"system","text":"Tap & Go is the copy primitive: one drop carries credential, protocol, tree, search, execute, and receipt instructions without a separate token-map-bundle assembly step.","who_claims":"system/oip_articles","source_ids":["oip-s2"]},{"id":"oip-c5","tier":"system","text":"OIP receipts are the proof object for actions: they record request, response, actor, links, replay, repair, and lineage.","who_claims":"system/oip_articles","source_ids":["oip-s2","oip-s5"]}],"sources":[{"id":"oip-s1","type":"protocol","title":"BUILD_SPEC object invocation path","url":"https://miscsubjects.com/api/file/docs/BUILD_SPEC.md","summary":"Defines directory rows, dispatch, ledger, and the escalation path for changing the build.","quote":"Run anything: POST https://miscsubjects.com/api/dispatch {key, body}","claim_ids":["oip-c2"],"link_status":"ok","hash":"oipbuildspec0001"},{"id":"oip-s2","type":"protocol","title":"Object Invocation Protocol spec","url":"https://miscsubjects.com/api/file/docs/OIP.md","summary":"Defines OIP surfaces, invariant loop, receipt/replay/repair, and invocation envelopes.","quote":"identify, explain, invoke, ledger, yield","claim_ids":["oip-c3","oip-c4","oip-c5"],"link_status":"ok","hash":"oipspec00000002"},{"id":"oip-s3","type":"protocol","title":"Live OIP capability tree","url":"https://miscsubjects.com/api/dispatch?map=1&format=markdown","summary":"Public recursive capability tree.","quote":"root > shelf > system article > capability article > receipt","claim_ids":["oip-c1","oip-c3"],"link_status":"ok","hash":"oipmap0000000002"},{"id":"oip-s4","type":"protocol","title":"Directory row documentation","url":"https://miscsubjects.com/api/dispatch?key=OIP_TREE&format=markdown","summary":"Capability articles are generated from live rows.","quote":"Machine Contract","claim_ids":["oip-c1"],"link_status":"ok","hash":"oiprow0000000003"},{"id":"oip-s5","type":"protocol","title":"Invocation ledger","url":"https://miscsubjects.com/api/invocations","summary":"Append-only invocation records and receipt links.","quote":"invocations","claim_ids":["oip-c5"],"link_status":"ok","hash":"oipinvocations0005"}],"prov":{"model":"system/oip_articles","action":"generate"}}