Two questions have to be answered before anything is configured: does this host speak the protocol, and how does a person prove who they are to it. This document specifies both. The key words are to be interpreted as described in BCP 14.
1. The service document
A platform MUST serve a service document at
GET {origin}/.well-known/agent-setup
The response MUST be application/json and MUST be retrievable without
credentials. Discovery that requires a session cannot be used to find out how to
obtain a session, and a client has to be able to tell "this host does not speak the
protocol" apart from "you are not signed in" before it opens a browser window.
A platform MAY additionally advertise the document from an existing well-known index of its own, keyed by the rel URI below. The well-known path is the interoperable form; an index entry is a convenience for platforms that already have one.
Fields
| Field | Meaning | |
|---|---|---|
v |
MUST | Integer document version. 1 for this specification. |
platform.name |
MUST | Human-readable name, shown to the person before they sign in. |
platform.documentation |
SHOULD | A page a person can read to find out what this platform is. |
profiles |
MUST | Absolute URL of the profiles document. |
authorization |
MUST | Absolute URL of the protected-resource metadata (§3). |
tools |
SHOULD | Bindings this platform publishes profiles for, by binding id. |
loopback_redirect_uris |
SHOULD | Redirect URIs registered for loopback clients (§4). |
publishes_provider |
MAY | true if profiles may carry a provider block. |
A platform MUST NOT require the profiles URL to live on the same origin as the
service document; a client MUST treat it as opaque and follow it as given.
Example
{
"v": 1,
"platform": {
"name": "Example Platform",
"documentation": "https://platform.example/docs"
},
"tools": ["codex"],
"profiles": "https://platform.example/asp/v1/profiles",
"authorization": "https://platform.example/.well-known/oauth-protected-resource",
"loopback_redirect_uris": ["http://localhost:51789"],
"publishes_provider": true
}
2. The rel URI
The protocol is identified by the URI
https://agentsetupprotocol.com/rel/agent-setup/v1
This string is an identifier, not an address. A client MUST compare it byte-for-byte and MUST NOT dereference it to decide whether a platform conforms. A self-hosted platform on a private network still keys its entry with exactly this value; a platform that mints its own variant is not interoperable, because a client matching on the string will not recognise it.
The version segment changes only on a breaking change to the document set. See the versioning policy.
3. Authorization
The authorization URL MUST point at protected-resource metadata as defined by
RFC 9728. From there a client follows the authorization-server metadata (RFC 8414)
to the endpoints it needs. The protocol defines no endpoints of its own and no
token format: it points at the platform's existing identity provider and gets out of
the way.
A client MUST use the authorization code flow with PKCE (S256). A client MUST NOT ask a person to paste a token, and a platform MUST NOT offer pasting as its primary path.
A client that cannot open a browser on the machine it runs on SHOULD fall back to the device authorization grant (RFC 8628) where the platform offers it.
Tokens
A platform MUST validate the audience of any token it accepts for the profiles document. A token minted for a different resource of the same issuer MUST be rejected. This is stated because the failure is silent: without an audience check, any token from the same issuer reads any person's profiles, and nothing in an access log distinguishes that from ordinary use.
A client MUST NOT write an access token into a configuration file. Where a token or key must reach a tool, it travels in an environment variable, and the configuration file names the variable rather than carrying its value.
4. Loopback redirect URIs
A platform SHOULD publish loopback_redirect_uris listing the redirect URIs it has
registered for loopback clients, each with an explicit host and port.
The reason is a failure with no useful diagnosis. http://localhost:{port} and
http://127.0.0.1:{port} are different strings to an authorization server even
though they resolve to the same socket. A client that guesses the wrong one is
refused at the redirect with a generic error, after the person has already signed in
and consented, and nothing in the message says which half was wrong.
A client MUST use a URI from this list when one is published. When none is published, a client MUST NOT assume a particular host, port or range; it SHOULD try a registered-client flow or report that the platform has not published enough to connect. Any port a particular implementation happens to use is a property of that implementation and is NOT part of this specification.
5. Wire format
Every field name in every document defined by this specification is snake_case. A
platform serving camelCase is not conforming.
A client SHOULD nevertheless accept camelCase as an alias on read, and SHOULD warn
rather than fail. The rule exists so that platforms converge; being strict on read
would only move the breakage onto the person.
6. Forward compatibility
| Condition | Required behaviour |
|---|---|
| An unknown field | The client MUST ignore it. It MUST NOT fail a run because of one. |
v greater than the client knows |
The client SHOULD read the fields it recognises, warn, and continue. |
v lower than the client knows |
The client MUST read it as that older version. |
| A missing MUST field | The client MUST report the document as malformed and MUST NOT guess a value. |
A tools entry the client has no binding for |
The client MUST ignore that entry, not the document. |
These rules bind in one direction only: a platform that publishes a field no client reads yet loses nothing, which is what makes the document set extensible without a coordinated release.