Skip to content

Authority Negotiation, Ontology Federation, the A2A gateway and AuthZEN

Phase 7 of the Authority Control Plane is about two agents that do not share an owner. A partner's agent and yours need to work together without either side handing the other a bearer token, without either side trusting the other's logs, and without a translation layer that quietly widens what was agreed. Four pieces make that work, all over the same authority model.

Authority Negotiation

Two agents that need to work together do not exchange tokens. The responder's workspace computes the intersection of

Input Where it comes from
the requester's authority the warrant it presents (verified offline, issued by its own workspace), or what it holds if it is local, or the federation cap if it is external with no warrant
the responder's boundary the objects in force for the responder: access profile, roles, active mission, grants, budgets
both intents each side's explicit mission narrows its own families; both objectives are recorded
both Charters pinned by hash; the responder's rules run at every action under the warrant
the federation contract the link's allowed families and scopes when the parties are in different organisations
the resource constraints the families, bounds, budgets and resources the request asks for

The result is proposed as a xybern-negotiation-v1 body, signed by the responder's issuer key (INV-007, an accountable issuer), with an Assurance block both sides attest to: purpose (both objectives), authority (hashes of both inputs and the intersection), liability domain (who is accountable for the instruction, who for the execution and the decisions) and downstream delegation (allowed or not, depth). A proposal that overlaps nothing is refused before anything is signed.

The requester countersigns. A requester in another workspace on the same host signs with its own key through its own API key; an external requester supplies a signature with its public key over the same payload. Only a countersigned negotiation issues the Session Warrant: an ordinary xybern-warrant-v1 token held by the responder, narrowed to the intersection, bound to the responder's mission, and carrying the negotiation id in its signed body. At the choke point the warrant is valid only while the negotiation is active, so either party revoking the negotiation revokes the warrant everywhere at once.

Every execution attested under a Session Warrant leaves one mutual execution receipt, sealed in both Provenance Vaults with the same negotiation id, decision id and attestation id, so neither side depends on the other's records.

POST /v1/enforce/negotiations                 {requester: {agent_id, workspace_id | org, warrant?}, responder_agent_id, purpose, requested?, ttl_seconds?, downstream_delegation?}
GET  /v1/enforce/negotiations                 both roles, with intersection, assurance and receipts
POST /v1/enforce/negotiations/<id>/countersign   by the requester's workspace key, or with {signature: {algorithm, key_id, value, public_key_pem}}
POST /v1/enforce/negotiations/<id>/revoke     by either party

SDK: negotiate, negotiations, negotiation, countersign, revoke_negotiation.

Ontology Federation

A partner names things differently. An ontology bridge is a signed, versioned map from the partner's vocabulary to yours, per kind (capability or resource), under constraints:

{"partner": "Acme Logistics", "kind": "capability", "mappings": [
  {"from": "purchase_order.create", "to": ["create_purchase_order"], "constraints": {"argument_bounds": {"create_purchase_order": {"amount": {"max": 50000}}}}},
  {"from": "erp.read.*", "to": ["read_erp_*"]}]}

Translation never widens. A partner term with no mapping is dropped and reported; every constraint on a mapping is folded into the translated authority with the same narrowing the warrants use. A new version retires the previous one and records its hash. A negotiation with an external requester translates the requester's authority through the active bridges before intersecting. The federation profile is the bundle a partner needs to work with you: the link's caps, the active bridges, your issuer record and published keys.

GET  /v1/enforce/bridges                      POST /v1/enforce/bridges (approvals scope)
POST /v1/enforce/bridges/<id>/retire          POST /v1/enforce/bridges/translate {partner, kind, terms | authority}
GET  /v1/enforce/federation/profile?partner=

The A2A gateway

Agent Cards are generated from passports, so what a partner discovers about your agent is what its passport says: name, provider, skills from its authorised families, the passport link, the trust state, the Charter hash, the mission, and how to authenticate (negotiate first, then the Session Warrant). A card is public at /a2a/<passport_id>/agent.json.

Inbound tasks (tasks/send, plain or JSON-RPC) arrive through negotiation. A task without an active negotiation is answered input-required with the proposal to countersign. A task under an active negotiation is authorised at the choke point with the Session Warrant and the requester as source, and comes back as an A2A Task: completed on allow, input-required on escalate, failed on block, canceled on terminate, with the decision id and the receipt link in its metadata.

Outbound tasks from your agent are authorised locally first; the envelope carries the Session Warrant in X-Xybern-Warrant and a stamp over the message in X-Xybern-Stamp, so the partner can verify both offline.

GET  /v1/enforce/a2a/cards[?agent_id=]        POST /v1/enforce/a2a/tasks       GET /v1/enforce/a2a/tasks
POST /v1/enforce/a2a/outbound                 {negotiation_id, text, partner_url?, action?, dry_run?}

The Connect group in the dashboard has an Agent to agent view: cards with their public links, negotiations with their intersections, signatures and receipts (countersign and revoke), bridges (sign and retire) and tasks.

AuthZEN

Any enforcement point that speaks the OpenID AuthZEN access evaluation API can ask Xybern directly. The subject is the principal, the action the capability, the resource the resource, the properties the arguments and the context the session, all mapped onto the Authority Slice. A real evaluation is a real decision, recorded and receipted; context.dry_run answers through pre-flight and records nothing.

POST /api/v1/access/evaluation
{"subject": {"type": "agent", "id": "buyer-1"}, "action": {"name": "create_purchase_order", "properties": {"amount": 42000}},
 "resource": {"type": "supplier_db", "id": "acme", "properties": {"class": "CONFIDENTIAL"}}, "context": {}}
→ {"decision": true, "context": {"decision": "allow", "decision_id": "…", "receipt": "/api/v1/enforce/decisions/…/receipt"}}

POST /api/v1/access/evaluations               batch, top-level fields are defaults
GET  /.well-known/authzen-configuration

The wire decision is a boolean as the standard requires; the Xybern decision (allow, escalate, block, terminate), the outcome, the rules that fired and the receipt travel in context.