Skip to content

Governance over AG-UI

The protocols in this stack are transport-agnostic governance extensions. They already bind to A2A (agent↔agent, via capabilities.extensions[]) and MCP (agent↔tools, via _meta). AG-UI is a third transport on a different axis: agent↔human. It is where a person plugs into a run — and several of these protocols have a moment that belongs to the principal (approve this, I can’t perceive that, this outcome was bad). This page specifies how that same governance object travels over AG-UI.

AG-UI is orthogonal to the stack, not another protocol in it. A plain AG-UI app needs no governance, and the governance protocols run perfectly well with no human edge. The binding is a one-way bridge: when a protocol reaches a decision that requires a person, it projects onto AG-UI’s interrupt mechanism to get the human in the loop, then resumes.

The visualization below is one human-facing task with all governance carried over a single AG-UI run. Events on the agent↔agent axis are blue; the agent↔human (AG-UI) events are amber; the gates are the points where the run pauses for a person. Click any gate for its wire JSON, or step through.

A governance object has one canonical wire type and one canonical URI. This binding only says how that same object travels over AG-UI, exactly as the A2A and MCP bindings say how it travels there. Four mechanisms carry it:

  • Identity by URI. Every governance payload, Custom event, and interrupt is keyed by the protocol’s canonical extension URI, carried in metadata.governance.uri. A governance-aware client routes on it; a generic AG-UI client ignores it and still works.
  • Interrupts for human-in-the-loop. A decision that belongs to the principal is a RUN_FINISHED interruptconfirmation for a yes/no (consent), input_required for structured input (a capacity-check response, a satisfaction rating). The run resumes on the same threadId.
  • State and Activity for posture. Resume-required context (an accessibility envelope, a policy document) is published as a STATE_SNAPSHOT before the interrupt; surfaced-but-not-gating records (an attestation) ride as Activity or Custom events.
  • MetaEvent for volunteered feedback. Feedback the human offers unprompted (a thumbs-up, a rating) maps to the relevant record without a blocking gate.

A conforming AG-UI governance binding holds these:

  • B-1 — URI identity. Payloads and interrupts are keyed by the canonical protocol URI; resolution rejects an interrupt that is not its own.
  • B-2 — Non-breaking. Unknown governance events and interrupt reasons are ignored by a generic client; the run still completes.
  • B-3 — Typed resume, denials in payload. A resolved interrupt’s payload validates against its responseSchema and deserializes to the protocol’s wire type. A denial is encoded in that type (decision: "rejected", refused: true) — never as a bare AG-UI cancelled, which means abandoned.
  • B-4 — No fabricated input. A human decision must originate from a real resume or MetaEvent; the binding never invents one.
  • B-5 — State before interrupt. Any state a resume depends on is emitted before the interrupt that needs it.
  • B-6 — Idempotent resume. Each governance side effect is applied at most once per interruptId.

The fit is graded, and it falls out along the human-decision axis. Where a principal has a real decision, the binding is strong; where governance is purely between agents, AG-UI is at most an observability surface.

ProtocolFitWhat rides AG-UI
Anumati / ACAP (consent)StrongPolicy in STATE_SNAPSHOT; consent decision as a confirmation/tool_call interrupt → ConsentRecord; per-action AdherenceEvents as Custom; an ambiguous claim escalates to an interrupt.
Sauvidya / PACE (accessibility)StrongCapability envelope as STATE_SNAPSHOT; an active consent-capacity challenge as an input_required interrupt → ActiveChallenge.
Phala (welfare)StrongPrincipalSatisfactionModel as state; satisfaction as an input_required interrupt or a volunteered MetaEventSatisfactionRecord.
Pramana (verification)ModerateEach output’s ClaimAttestation as an inspectable Activity event. Surface, don’t gate.
Abhyasa (delivery)ModerateAG-UI is one more custody binding; a principal-visible escalation renders as a confirmation interrupt acknowledged by a CustodyAck.
Pratyahara / NERVE, Yathartha (integrity)Observability onlyBehavioral integrity is agent-to-agent; the human is not in the trust loop. Posture may surface to an operator dashboard via StateSnapshot. No governance gate — the omission is deliberate.

That a uniform fit would be a smell is the point: forcing a human channel onto machine-to-machine integrity checks would be a misfit. The unevenness is the design working as intended.

This spec governs what a human-in-the-loop message means and how it travels — not how it looks. Rendering is a separate, complementary layer. A2UI (Google, open-sourced December 2025) is a declarative format for agent-generated interfaces: the agent sends a blueprint of trusted, pre-approved components and the client renders them with its own native widgets. A2UI rides the same AG-UI transport, so the very interrupts this spec defines — a consent gate, a capacity challenge, a satisfaction prompt — can be rendered as a rich native form via A2UI instead of a plain message + responseSchema, with Sauvidya / PACE choosing the modality and styling appropriate to the principal.

The boundary is deliberate: A2UI decides presentation only — never the typed payload, the canonical URI identity, or the governance decision. It sits at the far end of the pipe:

governance object → carried over AG-UI → rendered via A2UI

So the loop closes without A2UI entering the governance stack: it is a rendering target the bindings can feed, not a protocol they compose with.

An AG-UI governance binding conforms if it keys payloads and interrupts by the canonical URI (B-1), ignores unknown governance events and reasons (B-2), validates resolved-interrupt payloads and deserializes them to the protocol wire type with denials encoded there (B-3), never fabricates human input (B-4), emits resume-required state before the interrupt (B-5), and applies each governance side effect at most once per interruptId (B-6).

Reference bindings exist for the three strong-fit protocols and the testbed: