| Internet-Draft | Selo Architecture | October 2026 |
| Hamlett | Expires 4 May 2027 | [Page] |
Connecting one organization's systems to another's usually requires a connector built for that pair of systems, whether written by hand, bought from a connector catalog, or packaged as a tool server for an AI model. Connectors scale with the number of pairs, carry long-lived shared credentials, and have no verifiable link to the legal entities involved or to the terms under which access was granted.¶
This document describes that problem and an architecture, called Selo, that aims to reduce the need for such connectors. Agents owned by verified legal entities verify each other, negotiate a typed access agreement that both parties sign, and then execute it through a standard runtime and a gateway in front of each entity's existing API, using credentials bound to the agreement. Each entity maintains its own tested, signed mapping between its system and shared capability profiles. Selo uses existing APIs; it does not replace them.¶
The document states requirements and an architecture to inform discussion of whether, and where, such work belongs in the IETF. It does not specify a protocol.¶
This note is to be removed before publishing as an RFC.¶
This is an individual submission. Discussion is invited on the dispatch@ietf.org mailing list, and at a side meeting at IETF 127 on Monday 16 November 2026, 17:30-19:00 (US Pacific time), in room Continental 7.¶
The author has a pending patent application relating to this document. An IPR disclosure will be filed in accordance with BCP 79.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 4 May 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Most business software exposes an API. Accounting, enterprise resource planning (ERP), commerce, banking, payroll and logistics systems all let authorized callers read and write their records. What is missing is not the API but the connection between two organizations' APIs: something has to decide who may call what, under which terms, translate between two data models, hold the credentials, and keep working as both sides change.¶
Today that is a connector, built for a pair of platforms, configured for a pair of organizations, and operated by one of them or by a third party. Tool servers that expose a platform's API to an AI model, such as Model Context Protocol [MCP] servers, are a newer form of connector. AI agents make it plausible for software to read an API description and propose how two systems should exchange data. They do not, on their own, make that safe: an agent that can be steered by text from a counterparty cannot be trusted to grant access or sign commitments.¶
Selo is an architecture in which:¶
Much of this architecture profiles existing work or belongs outside the IETF. The parts that appear to need new, interoperable definitions, and that the author proposes for discussion, are:¶
Section 6.5 suggests venues for the remaining pieces.¶
Selo aims to reduce the need for manually built connectors and per-platform tool servers. Every operation is still performed by an entity's existing platform API. Selo does not move money; payments are executed by existing payment systems. Searching for counterparties is a marketplace function and is out of scope.¶
Issuer accreditation, verification procedures (for example know-your-business checks and their renewal), the trust list, assurance-tier definitions, approval workflows and user interfaces, and compliance-framework identifiers are expected to be governed by one or more external trust frameworks. This document defines only the hooks the protocol needs from them: an assurance level in the entity certificate, verifiable claims in an entity credential, and references to approvals and role credentials in agreements.¶
This version covers organizations only. Individuals as parties raise distinct privacy questions (Section 9) and are left for future work.¶
These requirements are stated as outcomes a solution needs to achieve, not as normative protocol requirements.¶
Entity A Entity B
+---------------------+ +---------------------+
| Agent (may use a |<-- control -->| Agent (may use a |
| model) | plane | model) |
| | typed proposals | | | typed proposals |
| v | | v |
| Policy checker | | Policy checker |
| (isolated, no model;| | (isolated, no model;|
| key + mandate) | | key + mandate) |
| | signs | | | signs |
| v | | v |
| Runtime + gateway |<--- data --->| Runtime + gateway |
| (pinned mapping, | plane | (pinned mapping, |
| owner credentials) | | owner credentials) |
| v | | v |
| Platform API | | Platform API |
+---------------------+ +---------------------+
Supporting services: issuers and trust list; public issuance log
(certificates, keys, revocations; never relationships); registries
(capability profiles, typed terms, algorithm suites)
Negotiation happens when an agreement is formed or changed, not per call; individual transactions flow through the data plane under the agreement. The agent is owned by the entity that uses the platform, not by the platform's vendor. A vendor or integration service may run components as an operator for its customers, who remain the owners.¶
An issuer verifies an entity and signs its entity certificate, a restricted certificate-authority certificate [RFC5280] with a path-length constraint of zero and name constraints limiting it to the entity's own namespace and its verified domains. The entity certificate carries the legal identifier, an assurance level and those domains. The entity key is held in protected hardware or a cloud key service and is used rarely, to certify the entity's other keys and to sign mandates and role credentials. Facts beyond the certificate (officers, verification dates, screening status, attestations) can be carried in a selective-disclosure credential such as an SD-JWT VC [RFC9901] [I-D.ietf-oauth-sd-jwt-vc] and revealed one claim at a time.¶
Keys are separated by role, each certified by the entity certificate:¶
An entity commits in advance to its next entity key by publishing a digest of it, and rotation is accepted only to the committed key, so a thief of the current key cannot take over the identity. Every certificate issued, key change and revocation is submitted to a public append-only log modeled on Certificate Transparency [RFC9162] or to a SCITT transparency service [RFC9943]; monitors alert an entity to issuance under its legal identifier. The log never records relationships or agreements. Revocation status is published promptly, for example in status lists [I-D.ietf-oauth-status-list].¶
The trust framework (Section 1.2) defines assurance levels. One level is expected to require verification by two independent issuers, so that no single issuer can create it (R3).¶
An entity publishes a discovery document at /.well-known/selo [RFC8615] on a domain listed in its entity certificate, optionally with a DNS record (for example SVCB [RFC9460]) or a DAWN mechanism [DAWN-CHARTER]. The document contains only the entity identifier, agent addresses, certificate chains, supported versions and algorithm suites, and is signed by a key certified by the entity certificate. A relying party checks that the domain it fetched from is one of the certified domains. An entity can also send a counterparty a signed invitation naming it by legal identifier.¶
Before revealing anything beyond the discovery document, each agent checks the other's certificate chain to an issuer on its trust list, revocation status, log inclusion, any operator authorization, and the assurance level its owner requires. Only then is a catalog exchanged, tailored to the requester.¶
A requester becomes approved for a category by invitation, by a typed access request approved by a person holding a covering role credential, or automatically under a deterministic rule in the provider's signed mandate (for example "verified existing customers may use Customer categories"). Per category, the provider sets whether an invitation alone suffices. Categories a requester is not approved for are omitted from its catalog, and a request naming one receives a response indistinguishable from one naming a nonexistent category, because the existence of sensitive endpoints is itself sensitive. Approval interfaces are expected to help approvers notice lookalike identities; how they do so is left to implementations and trust frameworks.¶
The owner gives each agent a signed mandate containing access limits per sensitivity label, commercial limits, the most generous terms the agent may offer, and requirements to obtain from counterparties. The agent's model negotiates and composes typed proposals. Each proposal crosses an isolation boundary to the policy checker, which contains no model and evaluates each typed field against the mandate by fixed rules. Values the mandate does not cover default to refusal or escalation, never approval.¶
Agent (model) --typed proposal--> | isolation | --> Policy checker
|
+------------------------+----------------------+
| | |
within mandate outside, escalatable not permitted
| | |
sign, with a approver with covering refuse
within-mandate role credential;
reference counterparty gets
"pending"; no answer by
deadline = declined
Every decision is recorded in a signed decision log. The counterparty learns only that a commitment was within mandate (or approved by a named, entitled person), through a within-mandate reference that identifies the mandate version and decision and binds to the mandate without revealing it; the mandate is disclosed only in an audit or dispute (R9). A provider also needs to avoid committing, across all its agreements, more platform capacity (such as request rates) than its platform account supports; how it does so is an implementation matter.¶
Messages are transport independent and follow the steps of contract formation:¶
A plain-HTTPS binding is required. Each message is a signed object, so its signature is independent of the binding; optional bindings carry the same objects over agent-to-agent protocols such as A2A [A2A] or agentproto protocols.¶
All fields are typed. Every inbound message is validated against its schema by deterministic code before any content reaches a model, and non-conforming messages are rejected. Free text is confined to one optional field marked untrusted, shown to people and either withheld from the model or given only to a quarantined model with no tools or keys.¶
Each message includes the digest of the preceding message in the session, forming a hash chain, plus a timestamp and nonce. The protocol version and algorithm suite are selected by a fixed rule (for example, the responder's most preferred entry in the intersection) from the signed hello messages, which are part of the chain, so stripping options from one hello is detected.¶
START --hello/hello--> VERIFIED --catalog--> CATALOG CATALOG --access-request--> ACCESS_PENDING ACCESS_PENDING --approved--> CATALOG (category now visible) ACCESS_PENDING --denied or timeout--> CLOSED CATALOG --offer--> NEGOTIATING (one live offer; each expires) NEGOTIATING --escalation--> PENDING_APPROVAL PENDING_APPROVAL --approved--> NEGOTIATING PENDING_APPROVAL --declined or timeout--> CLOSED NEGOTIATING --accept (digest of offer)--> ACCEPTED ACCEPTED --sign/sign (each via its checker)--> SIGNED SIGNED --> TESTING (agreement lifecycle) Any state: reject, withdraw, expiry, error, failed check --> CLOSED
An accept names the digest of the exact offer accepted, and the agreement is derived from that offer by a fixed rule. Nothing is binding, and no runtime loads an agreement, until both signatures verify. Offer expiries and approval deadlines are carried as typed values in the messages.¶
An access agreement is a JSON object canonicalized with [RFC8785]. Each party signs the canonical bytes with a detached signature (JWS [RFC7515] or COSE [RFC9052]) made with its checker signing key; each signature carries, as a signed attribute, that party's within-mandate reference and any approval references. The signatures are therefore not part of the body they sign. The body contains:¶
A human-readable rendering is produced from the canonical data by fixed, versioned rules, not by a model, so any party can regenerate it. The contracting parties are the entities, not their agents: replacing an agent does not affect agreements. Changing any term, endpoint or party requires a new signed version that includes the previous version's digest. Annex entries, such as test confirmations, suspensions and mapping-update notices, are appended to the agreement record without a new version, and the parties periodically countersign the latest annex digest.¶
SIGNED --> TESTING --both confirm--> ACTIVE
TESTING --fail or timeout--> CLOSED
ACTIVE --suspend--> SUSPENDED (some endpoints or all)
SUSPENDED --cause fixed, re-test passes--> ACTIVE
ACTIVE --renegotiate--> new version signed and tested
--> new version ACTIVE, old version SUPERSEDED
ACTIVE or SUSPENDED --terminate--> TERMINATED
After both signatures, the agreement enters TESTING. The provider issues test-scoped credentials that its gateway honors only against a test data source, such as a platform sandbox, a validate-only mode or synthetic records. The runtimes exchange sample records through every endpoint and mapping and validate them against the profile schema and invariants. Each runtime signs a test-confirm annex entry listing endpoints exercised and digests of the profile-format sample records and of its own mappings. Only when both confirmations are recorded does the agreement become ACTIVE and production credentials exist.¶
Runtimes refuse to operate outside the signed agreement. A failure affecting some endpoints, such as mapping output that violates the profile or an expired attestation, suspends only those endpoints; an endpoint resumes after the cause is fixed and its test passes again, without renegotiation. A platform API change usually requires only that the affected owner update its own mapping (Section 5.10). Disputes are resolved by the parties, using the signed records.¶
On activation, the provider issues the consumer short-lived OAuth access tokens identifying the agreement and version and bound, by a confirmation claim using DPoP [RFC9449] or mutual TLS [RFC8705], to the consumer runtime key named in the agreement. Tokens are refreshed at a token endpoint that checks agreement status. The provider's platform credentials stay in a vault used only by its gateway.¶
On every call, the gateway validates the token and proof of possession; checks that the agreement version is ACTIVE (or TESTING for a test token), that the endpoint is not suspended and that neither party is revoked; checks the endpoint and operation against the interface; removes fields outside the agreement; enforces rate, volume and time limits; executes the owner's pinned mapping and calls the platform API; and appends an entry to a signed, hash-chained private log of call metadata (not record contents). These logs make terms that cannot be enforced technically, such as purpose restrictions, demonstrable. Models may be used at run time for monitoring only.¶
An active agreement can also be exposed to the consumer's own AI assistant as tools, for example an MCP [MCP] server generated from the agreement's interface, limited to operations within the agreement.¶
Capability profiles build on existing business-document standards such as UBL [UBL], ISO 20022 [ISO20022] and XBRL Global Ledger [XBRL-GL]. Operations no profile covers are described as custom endpoints in OpenAPI [OPENAPI], with a field mapping confirmed by both parties in negotiation.¶
Each entity translates once, between its own platform as configured and each profile it uses. Its mapping is written in a sandboxed, deterministic language (for example JSONata [JSONATA] with no network, file, clock or random access, bounded execution and exact decimal arithmetic for money); passes the profile's conformance tests against the owner's platform; has its money-bearing fields confirmed by a person; and is signed and pinned by digest, so the bytes executed are the bytes tested. This document places no requirement on how a mapping is produced. There is no shared adapter library, so a defective mapping affects only its owner's agreements. When an owner changes its own mapping, it re-tests and re-signs it and records a signed mapping-update notice in the agreement record; the affected endpoints are re-tested, and no new agreement version is needed.¶
Payment details are a protected part of the commercial terms. A change needs a new agreement version approved by a person holding a finance role (an agent's mandate alone never suffices); direct notice to the paying side's people at notification endpoints in the agreement, by a path that bypasses both agents; a waiting period (for example 72 hours) during which the previous details remain in effect and either side can cancel; and confirmation by a person on the paying side before the first payment to the new details. Selo moves no money; payment approval rules can be agreement terms consumed by existing payment systems.¶
No compliance framework is built into the protocol. Attestations can be presented as credentials; requirements can be typed terms that a mandate attaches to a sensitivity label; if a required attestation lapses, only the dependent endpoints are suspended. The signed transcripts, agreement records, decision logs and call logs are verifiable offline, and implementations may offer them as evidence for audits.¶
Most building blocks of Selo already exist or are being developed elsewhere. This section summarizes the closest work.¶
One could assemble a vLEI role chain, a mandate draft, a RAR or GNAP grant, DPoP, a SCITT log and sector-style consent. The author believes four properties are still missing:¶
If the community agrees the problem is worth pursuing, one possible split is: the agreement object and negotiation messages as new work (venue to be determined through DISPATCH, possibly agentproto); agreement-bound tokens as an OAuth profile; mandate representation coordinated with WIMSE; discovery through DAWN; issuance logging through SCITT; and issuer accreditation, trust lists, capability profiles and conformance tests in an external trust framework.¶
Verified identifiers solve attribution but do not on their own prevent abuse: identities can be cheap, legitimate identities are compromised, and model-based agents read the other side's input. The main threats considered so far, with the architectural response:¶
Operators and gateways concentrate many owners' platform credentials and are high-value targets. Discovery, status and log services are targets for denial of service.¶
The following issues are known and not yet resolved by this architecture:¶
Following the threat categories of [RFC6973]:¶
Individuals as parties are out of scope for this version. Publishing their certificates in an append-only public log would conflict with erasure rights, so a design for individuals would need a different approach. An operator hosting agents for several owners should keep each owner's offers, limits and terms isolated.¶
This document has no IANA actions. A protocol specification developed from it would be expected to register the well-known URI suffix "selo" [RFC8615] and to establish registries for message types, typed access terms and algorithm suites.¶
These objects are illustrative only; field names and values are examples, not proposed formats. Identifiers use an "example:" prefix, and some digests are elided.¶
The body below is canonicalized and signed by each party with a detached signature; the signatures and within-mandate references are not part of it.¶
{"format":"1.0","agreement_id":"agr-5f2e","version":1,
"prev_version":null,
"parties":{
"provider":{"entity":"example:ent:acme-supply",
"agent":"example:agent:acme-supply:a1",
"runtime_key_jkt":"5d1c..."},
"consumer":{"entity":"example:ent:ledgerly",
"agent":"example:agent:ledgerly:k2",
"runtime_key_jkt":
"0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I"}},
"interface":[{"id":"e1","category":"finance.ledger",
"profile":"gl-transactions/1.2","op":"read",
"caller":"consumer","direction":"pull",
"format":"application/json"}],
"access":{"requests_per_minute":30,"max_records_per_day":20000,
"retention_days":365,
"purposes":["bookkeeping","tax-preparation"],
"ai_training":false,"data_location":"US",
"termination_notice_days":30},
"commercial":null,
"legal":{"uri":"https://terms.example.org/data-access/2.0",
"digest":"sha256:c0ff...",
"choices":{"governing_law":"US-DE",
"liability_cap":{"amount":"50000.00",
"currency":"USD"}}},
"accept_digest":"sha256:ab12...",
"render_template":"sha256:7d00..."}
¶
Issued at 2026-11-12T17:30:00Z, after both test confirmations were recorded at 17:20:00Z; valid for one hour.¶
{"iss":"https://gw.acme-supply.example",
"sub":"example:ent:ledgerly",
"aud":"https://gw.acme-supply.example/p/gl",
"agreement":"agr-5f2e","agreement_version":1,
"agreement_digest":"sha256:9b44...","scope":"e1:read",
"cnf":{"jkt":"0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I"},
"iat":1794504600,"exp":1794508200,"jti":"t-71c2"}
¶
The author thanks the authors of the work cited in Section 6, on which this document builds.¶