Agent Discovery Protocol v1.0
A simple web standard for making APIs discoverable by AI agents. One endpoint. One JSON format. That's the whole spec.
1. Endpoint#
Every service implementing the protocol MUST serve a JSON manifest at:
GET https://{domain}/.well-known/agent- Path:
/.well-known/agent(following RFC 8615) - Method: GET
- Content-Type:
application/json - CORS: Recommended for public APIs
- Cache:
Cache-Control: max-age=3600recommended
2. Manifest Format#
| Field | Type | Required | Description |
|---|---|---|---|
| spec_version | string | Yes | Protocol version. Currently "1.0" |
| name | string | Yes | Human-readable service name |
| description | string | Yes | 10-200 chars. What the service does |
| base_url | string | Yes | Base URL for relative detail_urls |
| auth | object | Yes | Authentication requirements |
| pricing | object | No | Pricing model and plans |
| capabilities | array | Yes | List of capabilities (min 1) |
Capability entry#
| Field | Type | Description |
|---|---|---|
| name | string | snake_case identifier |
| description | string | What this capability does |
| detail_url | string | URL for full details (absolute or relative to base_url) |
{
"spec_version": "1.0",
"name": "MailForge",
"description": "Transactional email API with templates and analytics.",
"base_url": "https://api.mailforge.dev",
"auth": {
"type": "api_key",
"header": "X-Api-Key",
"setup_url": "https://mailforge.dev/dashboard/api-keys"
},
"pricing": {
"type": "freemium",
"plans": [
{ "name": "Free", "price": "$0/mo", "limits": "100 emails/day" },
{ "name": "Pro", "price": "$29/mo", "limits": "10,000 emails/day" }
]
},
"capabilities": [
{
"name": "send_email",
"description": "Send a transactional email with optional template",
"detail_url": "/api/capabilities/send_email"
},
{
"name": "get_analytics",
"description": "Get email delivery analytics and open rates",
"detail_url": "/api/capabilities/get_analytics"
}
]
}3. Auth Object#
| Field | Description |
|---|---|
| type | "none" | "api_key" | "oauth2" |
| header | Header name for api_key (default: "Authorization") |
| prefix | Prefix for api_key (default: "Bearer") |
| setup_url | URL where users can get API keys |
| authorization_url | OAuth2 authorization endpoint |
| token_url | OAuth2 token endpoint |
| scopes | OAuth2 scopes (string array) |
4. Pricing Object#
| Field | Description |
|---|---|
| type | "free" | "freemium" | "paid" |
| plans | Array of { name, price, limits } |
| plans_url | URL to full pricing page |
5. Capability Detail Format#
Each capability's detail_url returns a JSON object with everything an agent needs to call it:
| Field | Type | Description |
|---|---|---|
| name | string | Capability identifier |
| description | string | Detailed description |
| endpoint | string | API endpoint path or full URL |
| method | string | HTTP method (GET, POST, etc.) |
| parameters | array | Parameter definitions with name, type, description, required, example |
| request_example | object | Full example HTTP request |
| response_example | object | Example response with status and body |
| auth_scopes | string[]? | Required OAuth2 scopes |
| rate_limits | object? | requests_per_minute, daily_limit |
6. Discovery Flow#
The protocol uses lazy drill-down. Agents fetch only what they need, when they need it:
1. Agent asks: "I need to send an email"
2. Registry search: GET /api/discover?q=send+email
Returns: service names, domains, matching capability summaries
3. Agent picks a service, fetches manifest: GET https://api.mailforge.dev/.well-known/agent
Returns: full capability list, auth requirements, pricing
4. Agent drills into the capability it needs: GET /api/capabilities/send_email
Returns: endpoint, method, parameters, examples
5. Agent calls the capability with the right parameters
7. Requirements#
- •Manifest MUST be served at
/.well-known/agent - •Response MUST be valid JSON with
Content-Type: application/json - •
spec_versionMUST be "1.0" - •
descriptionMUST be 10-200 characters - •Capability names MUST be snake_case
- •At least one capability MUST be defined
- •Each capability MUST have a
detail_urlthat returns valid JSON - •Capability names MUST be unique within a manifest
- •
base_urlMUST start withhttps://
Full specification with additional examples available on GitHub:
View spec on GitHub →