aid-discovery (Python)
Official Python implementation of the Agent Identity & Discovery (AID) specification.
AID enables you to discover AI agents by domain name using DNS TXT records. Type a domain, get the agent's endpoint and protocol - that's it.
Built by the team at agentcommunity.org.
- Website: aid.agentcommunity.org
- Docs: aid.agentcommunity.org
- GitHub: github.com/agentcommunity/agent-identity-discovery
Installation
pip install aid-discovery
Quick Start
from aid_py import discover, AidError
try:
# discover() returns a (record, ttl) tuple.
# record is a dict (TypedDict); access fields by key.
record, ttl = discover("supabase.agentcommunity.org")
print(f"Protocol: {record['proto']}") # "mcp"
print(f"URI: {record['uri']}") # "https://api.supabase.com/mcp"
print(f"Description: {record.get('desc')}") # "Supabase MCP" (optional)
print(f"TTL: {ttl} seconds")
# PKA domain-binding result (True only when an Ed25519 handshake
# cryptographically bound endpoint control to the queried domain):
if record.get("domain_bound"):
print("Endpoint control is bound to this domain")
except AidError as e:
print(f"Discovery failed: {e}")
API Reference
discover(domain: str, *, protocol: str | None = None, timeout: float = 5.0, well_known_fallback: bool = True, well_known_timeout: float = 2.0) -> (dict, int)
Discovers an agent by looking up the _agent TXT record for the exact host you pass in. The resolver does not implicitly retry parent hosts.
Parameters:
domain(str): The domain name to discoverprotocol(str, optional): Filter for the requested protocol after querying_agent.<domain>first. Protocol-specific_agent._<proto>.<domain>probing is legacy, diagnostic, or base-failure-only behavior where explicitly supported and configured.timeout(float): DNS timeout in seconds (default 5.0)well_known_fallback(bool): If true, falls back tohttps://<domain>/.well-known/agentonERR_NO_RECORDorERR_DNS_LOOKUP_FAILED(default True)well_known_timeout(float): Timeout for the.well-knownHTTP fetch (default 2.0)
Returns:
-
(record, ttl)tuple, where:record(dict): the parsed and validated AID record. Access fields by key (e.g.record["proto"],record["uri"]). See Data Types →AidRecordfor the available keys.ttl(int): DNS TTL in seconds.
Unpack it directly:
record, ttl = discover(domain).
Raises:
AidError: If discovery fails for any reason
parse(txt: str) -> AidRecord
Parses and validates a raw TXT record string.
Parameters:
txt(str): Raw TXT record content (e.g., "v=aid2;u=https://...;p=mcp")
Returns:
AidRecord: Parsed and validated record (adict/TypedDict; access fields by key)
Raises:
AidError: If parsing or validation fails
Data Types
AidRecord
A parsed AID record. At runtime this is a plain dict (a TypedDict), so access fields by key (record["proto"]), not by attribute. Optional fields may be absent — use record.get("desc"). Keys:
v(str): Protocol version ("aid2";"aid1"is supported for legacy compatibility)uri(str): Agent endpoint URIproto(str): Protocol identifier (e.g.,"mcp","openapi")auth(str, optional): Authentication methoddesc(str, optional): Human-readable descriptiondocs(str, optional): Absolutehttps://documentation URLdep(str, optional): ISO 8601 UTC deprecation timestamppka(str, optional): Public key for attestation (base64url)kid(str, optional): Key id (aid1only)domain_bound(bool, optional): Set bydiscover()after a PKA handshake.Truewhen endpoint control was cryptographically bound to the queried domain. Not a TXT-record field — records returned byparse()do not include it.
AidError
Exception raised when discovery or parsing fails:
code(int): Numeric error codemessage(str): Human-readable error message
Error Codes
| Code | Symbol | Description |
|---|---|---|
| 1000 | ERR_NO_RECORD |
No _agent TXT record found |
| 1001 | ERR_INVALID_TXT |
Record found but malformed |
| 1002 | ERR_UNSUPPORTED_PROTO |
Protocol not supported |
| 1003 | ERR_SECURITY |
Security policy violation |
| 1004 | ERR_DNS_LOOKUP_FAILED |
DNS query failed |
| 1005 | ERR_FALLBACK_FAILED |
.well-known fallback failed |
Advanced Usage
Custom Error Handling
from aid_py import discover, AidError
try:
record, ttl = discover("example.com")
# Use record["proto"], record["uri"], ...
except AidError as e:
if e.code == 1000: # ERR_NO_RECORD
print("No agent found for this domain")
elif e.code == 1001: # ERR_INVALID_TXT
print("Found a record but it's malformed")
else:
print(f"Other error: {e}")
Parsing Raw Records
from aid_py import parse, AidError
txt_record = "v=aid2;u=https://api.example.com/agent;p=mcp;s=Example Agent"
try:
record = parse(txt_record)
print(f"Parsed: {record['proto']} agent at {record['uri']}")
except AidError as e:
print(f"Invalid record: {e}")
aid2 Notes (PKA + Fallback)
-
PKA handshake: For
aid2, when a record includesk(pka), the client performs an Ed25519 HTTP Message Signatures handshake to verify endpoint control. The HTTP signaturekeyidis derived from theaid2key.kid(i) is legacyaid1compatibility only, not a v2 requirement. This requires an Ed25519 verification backend. Install one of:pip install aid-discovery[pka](installscryptography)- Or add
cryptography>=42orPyNaCl>=1.5to your environment (the verifier prefersPyNaClif present and otherwise falls back tocryptography) If no backend is available, discovery raisesERR_SECURITYwhen PKA is present.
-
Domain binding: For
aid2PKA, discovery sendsAID-Domainby default. A domain-bound proof still uses the singleaid-pka-v2tag and is indicated by signed coverage of"aid-domain";req; discovery stores the outcome inrecord["domain_bound"]. An unbound proof is accepted unless the caller enforcesdomain-binding=requirein tooling. -
.well-knownfallback: On DNS issues (ERR_NO_RECORDorERR_DNS_LOOKUP_FAILED), the client may fetchhttps://<domain>/.well-known/agent(TLS-anchored). Disable withwell_known_fallback=False.
Redirect Security
Client implementations do not automatically follow cross‑origin redirects from the discovered URI. If an initial request returns a redirect to a different origin (hostname or port), treat it as a potential security risk and either raise an error or require explicit confirmation.
More on PKA
See the documentation “Quick Start → PKA handshake expectations” for header coverage, algorithm requirements, timestamps, and key format.
Development
This package is part of the AID monorepo. To run tests:
# From the monorepo root
pnpm test
# Or run Python tests directly
cd packages/aid-py
python -m pytest tests/
License
MIT - see LICENSE for details.
Metadata
Release files for aid-discovery 2.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aid_discovery-2.1.1.tar.gz | 30.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aid_discovery-2.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 52.2 kB
Release files / aid_discovery-2.1.1.tar.gz
| Download URL | aid_discovery-2.1.1.tar.gz |
|---|---|
| Size | 30.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
99fa1d0f1adf0256eb1926a844ffcaaa19fcc58d1982ec3bc9d1f8463735eb01
|
|
BLAKE2b-256 checksum How to use checksums |
91eec4459063ff1298a53a7cc585d376e4047d62c7fa9c8136f621b7c4e6fdb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.
Transparency logRelease files / aid_discovery-2.1.1-py3-none-any.whl
| Download URL | aid_discovery-2.1.1-py3-none-any.whl |
|---|---|
| Size | 22.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
37d7fc3d06ffccada160b16de763d3f8d8ef3e1db6a18670b779fb1fbe7bb4f9
|
|
BLAKE2b-256 checksum How to use checksums |
7a7473d5ed2dc3e51239f9147a4a760e6f58132ff21d55935fe77ff548fab7ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.
Transparency log