| Internet-Draft | AID | September 2026 |
| Nemethi | Expires 6 March 2027 | [Page] |
Agent Identity and Discovery (AID) answers one question: given a domain, where is the agent and which protocol should a client speak? An AID client queries a DNS TXT record at the well-known subdomain _agent.<domain> and learns the service endpoint URI, protocol token, authentication hint, and optional metadata for that agent.¶
This document defines the AID v2 (`aid2`) record format, client discovery algorithm, exact-host lookup rules, endpoint-proof (PKA) handshake using Ed25519 HTTP Message Signatures, security requirements, and IANA registrations for the `_agent` DNS node name and the `agent` service name. The legacy `aid1` record format is retained as a compatibility format for clients migrating from earlier deployments. AID is intentionally small; after discovery, protocol-specific mechanisms such as MCP or A2A handle communication and capability negotiation.¶
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 6 March 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.¶
Applications that need to locate and connect to an agent often rely on out-of-band configuration, centralized directories, or protocol-specific discovery mechanisms. AID defines a single DNS-based bootstrap point that answers one question: given a domain, where is the agent and which protocol should a client speak?¶
AID uses a TXT record at the well-known DNS name _agent.<domain>. The record is small, versioned, and protocol-agnostic. It tells a client where the agent is located, which protocol token applies, what authentication hint to expect, and whether endpoint proof is available.¶
This revision updates the specification from the AID v1.2 record format described in [RFC-NEMETHI-AID-00] to the current AID v2 (`aid2`) wire format: the record uses an unpadded base64url Ed25519 JWK `x` value for the endpoint-proof key and an RFC 7638 JWK thumbprint as the HTTP Message Signature `keyid`, removing the `kid`/`i` rotation alias used by `aid1`. It also defines an optional domain-binding extension to the endpoint-proof handshake that lets an endpoint signal consent to serve as the agent for the queried domain. The legacy `aid1` format remains valid during a compatibility window.¶
This document requests two IANA registrations. The RFC 8552 registration covers the deployed TXT-based discovery label `_agent`, while the RFC 6335 service-name-only registration reserves `agent` for possible future SRV-based discovery under the same naming family. Both registrations apply to the `_agent` label across `aid1` and `aid2`; the record-version field, not the DNS node name, distinguishes wire-format revisions.¶
AID has been deployed since mid-2025 with client and server SDKs across six languages. This document is an individual contribution, submitted for consideration alongside other agent-discovery proposals under discussion in the IETF DAWN effort.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
A provider MUST advertise its agent service by publishing a single TXT record at `_agent.<domain>`. Providers MUST use DNS TXT records for discovery. TXT is the deployed discovery record type because it is widely available across DNS providers and registrars. Future versions of AID may adopt a more structured record type, but the `_agent` label remains stable; see Section 8.¶
The record MUST be a single semicolon-delimited string of `key=value` pairs. Clients SHOULD trim leading and trailing whitespace from keys and values. Clients MUST ignore unknown keys unless the key has a known legacy meaning that this specification explicitly rejects for `aid2`.¶
If a DNS server splits the TXT record into multiple 255-octet character strings, the client MUST concatenate them in order before parsing. Providers SHOULD keep total payload size below 255 bytes when possible.¶
Key comparison is case-insensitive. Clients MUST recognize the single-letter lowercase alias for every defined key. A record MUST NOT include both a full key and its alias. Providers SHOULD emit the short-key form for compact DNS deployment.¶
AID v2 records MUST NOT use `kid` or `i` for endpoint proof. A `v=aid2` record containing `kid` or `i` is invalid.¶
_agent.example.com. 300 IN TXT ( "v=aid2;u=https://api.example.com/mcp;" "p=mcp;a=pat;s=Example AI Tools" )
_agent.example.com. 300 IN TXT ( "v=aid2;p=mcp;u=https://api.example.com/mcp;" "k=JrQLj5P_89iXES9-vFgrIy29clF9CC_oPPsw3c5D0bs;" "a=oauth2_code;s=Secure AI Gateway" )
_agent.example.com. 300 IN TXT ( "v=aid2;p=websocket;u=wss://agent.example.com/session;" "a=oauth2_code;s=Streaming Agent" )
_agent.grafana.com. 300 IN TXT ( "v=aid2;u=docker:grafana/mcp:latest;" "p=local;a=pat;s=Run Grafana agent locally" )
_agent.example.com. 300 IN TXT ( "v=aid1;p=mcp;u=https://api.example.com/mcp;" "k=<legacy-v1-multibase-key>;i=g1" ) _agent.example.com. 300 IN TXT ( "v=aid2;p=mcp;u=https://api.example.com/mcp;" "k=<same-key-as-v2-base64url>" )
Clients that support both versions partition records by version before ambiguity checks. A same-key migration from legacy `aid1` to current `aid2` is not a key rotation when the decoded Ed25519 public key bytes are the same.¶
When an AID client is given a domain, it MUST perform the following steps:¶
Malformed answers do not matter when there is exactly one valid record in the selected version. Returning clients that previously selected `aid2` SHOULD treat an `aid1`-only result as a version downgrade.¶
If no DNS record is found or the DNS lookup fails, the client MAY attempt the `.well-known` fallback on the same exact host; see Appendix B. If both DNS and fallback fail, discovery fails.¶
Client implementations SHOULD use these codes to report specific failure modes.¶
| Code | Name | Meaning |
|---|---|---|
| 1000 | ERR_NO_RECORD | No AID DNS record was found for the domain. |
| 1001 | ERR_INVALID_TXT | A record was found but is malformed, invalid, or ambiguous. |
| 1002 | ERR_UNSUPPORTED_PROTO | The record is valid, but the client does not support the selected protocol. |
| 1003 | ERR_SECURITY | Discovery failed due to a security policy or failed endpoint proof. |
| 1004 | ERR_DNS_LOOKUP_FAILED | The DNS query failed for a network-related reason. |
| 1005 | ERR_FALLBACK_FAILED | The `.well-known` fallback failed or returned invalid data. |
Discovery is exact-host by default. If the application asks for `app.team.example.com`, the canonical AID query name is `_agent.app.team.example.com`.¶
Clients MUST NOT walk up the DNS hierarchy looking for `_agent.team.example.com` or `_agent.example.com`. If an operator wants a child host to inherit a shared record, that inheritance MUST be expressed in DNS for the exact queried name, for example by using a `CNAME` at the child host's `_agent` label.¶
_agent.app.team.example.com. 300 IN CNAME ( _agent.shared.team.example.com. ) _agent.shared.team.example.com. 300 IN TXT ( "v=aid2;p=mcp;u=https://gateway.team.example.com/mcp;" "k=<current-key>" )
The canonical v2 location is the base record `_agent.<domain>`. Providers MAY additionally publish protocol-specific names such as `_agent._mcp.<domain>` or `_agent._a2a.<domain>` for legacy clients, diagnostics, or explicitly configured base-failure probing. Protocol-specific names, when used, always use the underscore form `_agent._<proto>.<domain>`; clients MUST NOT perform a compatibility lookup at `_agent.<proto>.<domain>`.¶
When an application explicitly requests a protocol, v2 clients still query the canonical base name `_agent.<exact-host-user-entered>` first and filter that record for the requested protocol. Protocol-prefixed probing is legacy, diagnostic, or base-failure-only behavior where supported and explicitly configured. Clients MUST NOT query parent hosts implicitly in either lookup form.¶
AID publishes public discovery metadata. The TXT record MUST NOT contain secrets. The protocol depends on DNS integrity, TLS for remote endpoints, and explicit client safeguards for local execution.¶
Clients that support `proto=local` MUST implement the following safeguards:¶
If an initial request to the discovered `uri` returns an HTTP redirect (`301`, `302`, `307`, or `308`) to a different origin, clients SHOULD treat this as a potential security risk. Clients MUST NOT follow such cross-origin redirects automatically. Implementations MAY either terminate with `ERR_SECURITY` or require explicit user confirmation before proceeding. Clients MUST NOT follow redirects during PKA verification or `.well-known` fallback.¶
PKA proves exactly this: the endpoint reached at the discovered URI controls the Ed25519 private key corresponding to the public key currently published in the domain's selected AID record.¶
PKA does not prove: that a user authorized a specific action; that an OAuth token is valid; that a SPIFFE SVID belongs to a trust domain; that an internal policy engine approved a request; that a key change is cryptographically continuous with a previous key; or that the endpoint consents to serve as the agent for the queried domain.¶
Because the response signature binds only the endpoint's own request context, any domain can publish a record containing another operator's endpoint URI and public key, and the endpoint proof still verifies. This unauthorized-association gap does not let the publishing domain impersonate the endpoint, but it falsely implies a relationship between the domain and the endpoint. Clients that need the endpoint's consent to the association use the domain-binding profile in Appendix A.7; v2 clients SHOULD request this by default.¶
AID's security model addresses the following threat landscape.¶
Assumptions:¶
Mitigations provided:¶
Explicitly out of scope:¶
Clients that expose enterprise controls SHOULD provide policy presets and MAY expose the underlying policy knobs directly.¶
| Preset | PKA | DNSSEC | Well-known | Downgrade | Domain binding |
|---|---|---|---|---|---|
| balanced | if-present | prefer | auto | warn | prefer |
| strict | require | require | disable | fail | require |
The underlying policy knobs are:¶
Policy semantics are as follows:¶
When a record is discovered through the `.well-known` fallback (`trustSource=well-known-tls`; see Appendix B), the queried host and the TLS-validated host are the same origin, so an `AID-Domain` binding there is largely redundant with TLS host validation. Clients still send `AID-Domain` and `domain-binding=require` still enforces, but the binding adds little beyond TLS in that path.¶
If discovery succeeds only through `.well-known`, the result cannot satisfy `dnssec=require`.¶
Providers are RECOMMENDED to publish `_agent` TXT records with a TTL between 300 and 900 seconds. Clients MUST respect the received TTL and MUST NOT cache the record longer than that.¶
PKA responses are separate from DNS records. A nonce-bound PKA response MUST include `Cache-Control: no-store`. Clients SHOULD also send `Cache-Control: no-store` on PKA requests.¶
AID v2 core does not define DNS-level cryptographic key rotation. The core record says, for example:¶
_agent.acme.com TXT ( "v=aid2;p=mcp;u=https://agent.acme.com/mcp;" "k=<current-key>" )¶
That means:¶
It does not mean:¶
If the key changes, the key changed. Clients with previous state decide whether to warn, fail, or accept according to local policy (Section 5.3).¶
A shape such as the following is not valid in v2 core:¶
_agent.acme.com. 300 IN TXT ( "v=aid2;p=mcp;u=https://agent.acme.com/mcp;" "k=<old-key>" ) _agent.acme.com. 300 IN TXT ( "v=aid2;p=mcp;u=https://agent.acme.com/mcp;" "k=<new-key>" )¶
It changes the model from a domain resolving to one selected endpoint record with an optional proof key, to a domain resolving to one selected endpoint descriptor with an active key set from which a response `keyid` selects a key. That requires rules for normalized non-key field equivalence, duplicate handling, partial DNS propagation, key-set pinning, downgrade policy, SDK return types, and conformance fixtures. It also does not solve lost-key or compromised-key recovery.¶
If AID later needs managed rotation for pinned clients or provenance profiles, that should be a separate HTTP key-directory profile, likely using JWKS or Web Bot Auth style overlap:¶
{
"keys": [
{
"kty": "OKP",
"crv": "Ed25519",
"kid": "<jwk-thumbprint>",
"x": "<public-key>",
"use": "sig",
"nbf": 1712793600,
"exp": 1715385600
}
]
}
¶
If such a directory chains to DNS `k`, that chaining is the defining property of an AID-anchored key directory. If it does not chain to DNS `k`, it is a normal external key directory outside AID core.¶
AID v2 keeps `_agent.<domain>` as the discovery label for compatibility with existing deployments. The stable DNS label for AID is `_agent`. Record formats may evolve, but the discovery label remains `_agent` across versions, and the record version field identifies the wire-format expectations. This is the main reason the RFC 8552 registration is valuable even if a later AID version uses a different DNS RR type.¶
Label governance beyond the v2 key-format and endpoint-proof updates defined in this document may be addressed by a future working group process.¶
To support interoperability, token registries and community resources are maintained publicly. The auth and protocol registries remain compatible with legacy `aid1` records unless changed through the normal extension process.¶
All authentication tokens are case-sensitive and use lowercase ASCII.¶
All protocol tokens are case-sensitive and use lowercase ASCII.¶
| Token | Meaning | Allowed `uri` scheme(s) |
|---|---|---|
| mcp | Model Context Protocol | https:// |
| a2a | Agent-to-Agent Protocol | https:// |
| openapi | OpenAPI specification document | https:// |
| grpc | gRPC over HTTP/2 or HTTP/3 | https:// |
| graphql | GraphQL over HTTP | https:// |
| websocket | WebSocket transport | wss:// |
| local | The agent runs locally on the client machine | docker:, npx:, pip: |
| zeroconf | mDNS or DNS-SD service discovery | zeroconf:<service_type> |
| ucp | Universal Commerce Protocol | https:// |
This document requests registration in two IANA registries. The registrations serve different purposes. The RFC 8552 request covers AID TXT discovery at `_agent.<domain>`, applicable across the `aid1` and `aid2` record versions defined in this document. The RFC 6335 request reserves the service name `agent` for potential future DNS service discovery usage under `_agent._tcp.<domain>`.¶
IANA is requested to register the following entry in the "Underscored and Globally Scoped DNS Node Names" registry established by [RFC8552].¶
| RR Type | TXT |
| Node Name | _agent |
| Reference | This document |
The `_agent` node name is used exclusively for Agent Identity and Discovery. A single TXT record published at `_agent.<domain>` contains semicolon-delimited key/value pairs that identify an agent endpoint, protocol token, and optional metadata as defined in Section 3 and Section 4.¶
The requested node name is specific to AID and does not reserve the broader concept of agents or agent-related discovery generally. Protocol-specific labels of the form `_agent._<proto>.<domain>` are subordinate names beneath the registered `_agent` node and do not require separate global registration.¶
IANA is requested to register the following service-name-only entry in the "Service Name and Transport Protocol Port Number" registry defined by [RFC6335].¶
| Service Name | agent |
| Transport Protocol(s) | tcp |
| Description | Agent Identity and Discovery (AID): DNS-based discovery of agent service endpoints |
| Port Number | N/A |
| Assignment Notes | No port number is requested. This is a service-name-only registration intended to establish `agent` for possible future SRV-based discovery under `_agent._tcp.<domain>` while preserving the stable `_agent` label. |
| Reference | This document |
When `k` is present, clients MUST verify endpoint proof using HTTP Message Signatures with Ed25519.¶
For v2, `k` MUST be unpadded base64url. Decoding MUST produce exactly 32 octets. Legacy `z...` multibase keys MUST NOT be accepted in `v=aid2`. The corresponding JWK is:¶
{ "kty": "OKP", "crv": "Ed25519", "x": "<k>" }
¶
The expected HTTP Message Signature `keyid` is the RFC 7638 [RFC7638] JWK thumbprint using SHA-256 over this exact UTF-8 JSON serialization, with no extra spaces:¶
{"crv":"Ed25519","kty":"OKP","x":"<k>"}
¶
The SHA-256 digest is encoded as unpadded base64url. Implementations MUST NOT hash the raw public key bytes directly for `keyid`.¶
Validated RFC 9421 [RFC9421] Structured Fields shape:¶
The signature MUST NOT cover HTTP `Date`.¶
The client challenge MUST contain at least 32 bytes of entropy and SHOULD be transported as unpadded base64url in the RFC 9421 `nonce` signature parameter. The verifier MUST compare the received `nonce` exactly to the challenge it sent. Servers are not required to store nonce state in v2 core because the verifier supplies the one-shot nonce and the signed response is not cacheable.¶
`created` and `expires` are mandatory. `expires` MUST be greater than `created`. `expires` minus `created` MUST NOT exceed 300 seconds and SHOULD be 60 seconds or less. Verifiers MAY allow a small clock-skew tolerance when evaluating `created` and `expires`.¶
Signers MUST emit `alg="ed25519"` lowercase. Verifiers MUST compare the semantic algorithm value case-insensitively and MUST reconstruct `@signature-params` from the received Structured Field value.¶
The base v2 PKA response signature covers `"@method";req`, `"@target-uri";req`, `"@authority";req`, and `"@status"`. `@method`, `@target-uri`, and `@authority` are request-derived components and therefore use `;req`. `@status` is response-derived and does not use `;req`. The domain-binding profile in Appendix A.7 extends this base covered set with `"aid-domain";req`; the tag remains `aid-pka-v2`.¶
`@status` signs the status actually returned. PKA does not require status `200`. A signed `401` can still prove endpoint authenticity before an OAuth or auth.md handoff continues.¶
A verifier accepts a v2 PKA response only when:¶
This profile lets an endpoint prove that it consents to serve as the agent for the queried domain, addressing the unauthorized-association gap described in Section 5.1. When `k` is present in an `aid2` record, clients SHOULD request domain binding by default (see Section 4.1). The domain-binding indicator in the discovery result is the expected outcome for well-configured v2 deployments; clients that need a hard enforcement boundary use `domain-binding=require` in enterprise policy (Section 5.3).¶
There is a single RFC 9421 tag for all v2 PKA proofs, `aid-pka-v2`. A proof is domain-bound if and only if its signed covered set includes the `"aid-domain";req` component, positioned strictly between `"@authority";req` and `"@status"`. The covered set is part of `@signature-params`, which is itself signed, so coverage is authenticated and cannot be altered without invalidating the signature. The `tag` identifies the application profile per [RFC9421] Section 2.3; it is the covered set, not a separate tag, that distinguishes an unbound proof from a domain-bound one.¶
A client requesting domain binding sends the queried domain in the `AID-Domain` request header and requests an extended response signature whose covered set adds `"aid-domain";req`:¶
The `AID-Domain` value is the exact host the client queried in Section 4.1 (step 2), normalized to its A-label form per Section 4.1 (step 1), lowercased, and without a trailing dot or port. Signer and verifier MUST use this identical byte value.¶
A server that supports this profile and serves the named domain responds with the Appendix A.3 shape, except that the covered set includes `"aid-domain";req` after `"@authority";req`. The `aid-domain` component is the request header field; its RFC 9421 component identifier is the lowercased field name `aid-domain`, so the signature binds the exact value the client sent.¶
A server that supports this profile but does not serve the named domain MUST NOT produce a signature covering that `AID-Domain` value. It SHOULD respond with status `403` and no `Signature-Input` header. A server that does not support this profile ignores the header and responds with the base Appendix A.3 shape, whose covered set omits `aid-domain`, which remains a valid endpoint proof without domain binding.¶
A response that carries no valid `aid-pka-v2` signature, including a `403` refusal, is a failed endpoint proof under Section 5, so discovery fails whenever the selected record contains `k`. A profile-aware endpoint that refuses an unserved domain therefore causes discovery to fail for that domain, which is the intended outcome.¶
Verifier rules, in addition to Appendix A.6:¶
Domain binding is a statement by the endpoint that it serves the named domain. It does not prove authorization, delegation, or organizational identity.¶
In AID v2, domain binding is optional-but-default: clients SHOULD send `AID-Domain`, and an unbound proof (one whose covered set omits `aid-domain`) remains a valid outcome unless local policy requires binding (`domain-binding=require`; see Section 5.3). A future major version (`aid3`) is expected to make sending `AID-Domain` REQUIRED for clients performing PKA and to make rejecting unbound proofs the baseline. Establishing high adoption while the installed base is small is intended to minimize switching cost at that transition; implementations that already send `AID-Domain` by default require no change at `aid3`.¶
AID remains DNS-first. The `.well-known` fallback is a convenience for environments where publishing DNS TXT records is difficult. It does not change the RFC 8552 scope of `_agent`.¶
DNS-discovered records have `trustSource=dns`. Fallback-discovered records have `trustSource=well-known-tls`. If a policy requires DNSSEC-backed trust, `.well-known` cannot satisfy it. The `.well-known` URI convention itself is described in [RFC8615].¶
This appendix is non-normative. It describes how AID composes with adjacent mechanisms without incorporating them into AID core.¶
AID v2 follows Web Bot Auth where the layers match: Ed25519, RFC 9421 HTTP Message Signatures, RFC 7638 JWK thumbprints, `created`, `expires`, `nonce`, and `tag`.¶
AID does not become Web Bot Auth. Web Bot Auth signs automated client requests to origins. AID PKA proves endpoint control for a DNS-discovered agent endpoint.¶
Operators may reuse key material across AID and Web Bot Auth if their threat model allows it, but this document does not recommend reuse. Reuse shares blast radius between endpoint proof and request-signing.¶
AID may be used by future SPIFFE or WIMSE profiles as a public first-contact anchor.¶
AID v2 core does not define:¶
AID v2 remains compatible with the general idea of compact Ed25519 key material as used by some key-addressed identity designs, but it does not adopt a key-addressed identity model. In such designs, the public key itself is the address and DNS-shaped records are signed directly under that key. AID remains DNS-authority-rooted: the DNS owner publishes the current endpoint and current endpoint-proof key inside a TXT payload at a name derived from the domain, not from the key.¶
Specification and reviewer-facing language should say "DNS-current endpoint/key" and should not imply self-certifying names, key-addressed identity, or cryptographic continuity across key changes.¶
This appendix is non-normative.¶