agent.json Specification
The open capability manifest for the agent internet. agent.json is a machine-readable file that a service publishes to declare what it offers to AI agents — its capabilities, inputs, and payment terms.
1. Purpose
agent.json answers three questions:
- What can agents do here? (intents)
- What inputs do those actions require? (parameters)
- Where should payment go? (payout address, bounty terms, x402)
Just as robots.txt tells search engines how to crawl a site, agent.json tells AI agents exactly how to interact with your service.
- For Providers: Make your service "agent-ready" in 5 minutes and get paid for agent traffic without maintaining a custom agent API.
- For Runtimes: Stop hardcoding brittle web scrapers. Fetch the
agent.jsonand instantly understand capabilities, inputs, and payment terms.
2. Hosting
Serve your manifest at one of these paths (checked in order):
https://yourdomain.com/.well-known/agent.json (preferred)
https://yourdomain.com/agent.json (fallback)• Served over HTTPS
• Content-Type: application/json
• Publicly accessible without authentication
• Valid JSON, no redirects to a different origin
The .well-known path follows RFC 8615 conventions.
3. Integration Tiers
Think of tiers like introducing yourself. First you say your name (Tier 1). Then you explain what you do (Tier 2). Then you show your ID to prove it (Tier 3). Each tier unlocks more trust, which is better for economics and agents across the whole ecosystem.
| Tier | Description | Key Fields |
|---|---|---|
| Tier 1: Listed | Like a business card. Your domain is discoverable by agents. Three required fields. | version, origin, payout_address |
| Tier 2: Capable | Like a menu with prices. Agents can call your API programmatically. Declare endpoints, parameters, and pricing. | intents[], bounty, incentive, price |
| Tier 3: Verified | Like a notarized business license. Prove you own your domain with a cryptographic identity (DID + public key). Optionally register with the OATR for trust discovery. | identity { did, public_key, oatr_issuer_id } |
| Tier 3+: Committed | Verifiable behavioral invariants. Declare latency bounds, data residency, uptime SLAs, and regulatory compliance — optionally signed with Ed25519 for tamper evidence. | commitments { entries[], signature } |
Like a business card. Your domain is discoverable by agents. Three required fields.
Like a menu with prices. Agents can call your API programmatically. Declare endpoints, parameters, and pricing.
Like a notarized business license. Prove you own your domain with a cryptographic identity (DID + public key). Optionally register with the OATR for trust discovery.
Verifiable behavioral invariants. Declare latency bounds, data residency, uptime SLAs, and regulatory compliance — optionally signed with Ed25519 for tamper evidence.
Tier 1 — Minimal
Three fields. Your domain is now discoverable by agent runtimes.
{
"version": "1.0",
"origin": "example.com",
"payout_address": "0x0000000000000000000000000000000000000000"
}Tier 2 — Structured
Declares specific capabilities. Agent runtimes match user requests to your intents using semantic similarity.
{
"version": "1.0",
"origin": "example.com",
"payout_address": "0x0000000000000000000000000000000000000000",
"display_name": "Example Store",
"description": "Online marketplace for electronics and home goods.",
"intents": [
{
"name": "search_products",
"description": "Search the product catalog by keyword, category, or brand. Returns names, prices, ratings, and availability.",
"parameters": {
"query": { "type": "string", "required": true, "description": "Search query" },
"category": { "type": "string", "required": false, "description": "Product category filter" }
}
},
{
"name": "complete_purchase",
"description": "Complete a purchase for items in the user's cart. Requires prior user approval.",
"parameters": {
"cart_id": { "type": "string", "required": true, "description": "Cart identifier" }
},
"bounty": { "type": "cpa", "rate": 12.00, "currency": "USDC" }
}
],
"bounty": { "type": "cpa", "rate": 2.00, "currency": "USDC" },
"incentive": { "type": "cpa", "rate": 0.50, "currency": "USDC" }
}Tier 3 — Verified Identity
Proves you own your domain with a cryptographic identity. A DID (Decentralized Identifier) lets agents verify your API is legitimate — not an impersonator. The simplest method is did:web: if you own example.com, your DID is did:web:example.com.
Note: Tier 3 proves the API provider's identity. The separate question of whether an agent is authorized to act on a user's behalf is solved by the Open Agent Trust Registry, which verifies that agent runtimes are legitimate — like the Certificate Authority system for the agent internet.
{
"version": "1.4",
"origin": "example.com",
"payout_address": "0x...",
"identity": {
"did": "did:web:example.com",
"public_key": "base64url-encoded-public-key",
"oatr_issuer_id": "example-runtime"
},
"intents": [ ... ],
"bounty": { ... }
}Becoming Tier 3: Step by Step
Tier 3 means your API has a provable identity. Instead of just saying "I'm example.com," you can cryptographically prove it. This guide walks you through the process. It takes about 5 minutes.
Step 1: Generate a keypair
Create an Ed25519 keypair. The private key stays secret (you use it to sign things). The public key goes in your agent.json and DID document so others can verify your signatures.
npx @open-agent-trust/cli keygen --issuer-id yourdomain-comReplace yourdomain-com with a slug based on your domain. Use lowercase letters, numbers, and hyphens only. No spaces. For example: acme-api, stripe, my-saas-co.
This outputs two things:
- Private key — saved as a
.private.pemfile. Keep this secret. Never commit it to a repo. To read it:cat yourdomain-com.private.pem. macOS users: do not double-click this file. macOS will try to import it into Keychain Access. Always usecatin the terminal. - Public key — printed to your terminal. This goes in your agent.json and DID document (Steps 2 and 3 below). Safe to share publicly.
When is the private key used? For Tier 3, you only need the public key. The private key is used later if you register as a trusted runtime issuer in the Trust Registry, where your backend would sign JWTs (attestations) to vouch for agents it runs. This is an advanced use case. For now, just keep the private key safe.
Step 2: Add identity to your agent.json
Add the identity block to your existing agent.json. Replace yourdomain.com with your actual domain and paste your public key from Step 1.
"identity": {
"did": "did:web:yourdomain.com",
"public_key": "your-public-key-from-step-1",
"oatr_issuer_id": "your-issuer-id"
}oatr_issuer_id field is optional. If you also register with the Open Agent Trust Registry, adding this field consolidates trust discovery — the OATR CI uses your agent.json for domain verification instead of requiring a separate /.well-known/agent-trust.json file.The did:web method uses your domain as proof of identity. If you control yourdomain.com, you control did:web:yourdomain.com. No registration with a central authority required.
Step 3: Host your DID document
Create a file at /.well-known/did.json on your domain. This is how anyone resolves your DID to find your public key.
{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:web:yourdomain.com",
"verificationMethod": [{
"id": "did:web:yourdomain.com#key-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:yourdomain.com",
"publicKeyMultibase": "z6Mkf5rGMoatrSj1f..."
}]
}Note on key format: The publicKeyMultibase field uses multibase encoding: prefix your public key with z (the multibase identifier for base58btc). For example, if your CLI output is jywIPY2WMGZLlv5Wx9Kp..., the multibase value is zjywIPY2WMGZLlv5Wx9Kp.... The public_key in your agent.json (Step 2) uses the raw value without the z prefix.
After deploying, verify it works by visiting https://yourdomain.com/.well-known/did.json in your browser. You should see the JSON above.
Step 4 (optional): Register with the Trust Registry
If you also operate an agent runtime (a platform that runs agents on behalf of users), you can register as a trusted issuer in the Open Agent Trust Registry. This is separate from Tier 3. Tier 3 proves your API's identity. The Trust Registry proves your runtime is authorized to issue attestations for agents.
Key management
What if I lose my private key?
Generate a new keypair, update your agent.json and did.json, and deploy. The old key is immediately revoked because it is no longer published on your domain. Your domain is the source of truth.
Can I rotate my keys?
Yes. Generate a new keypair, update both files, deploy. The transition is instant because agents resolve your DID document on every verification. There is no propagation delay.
Can I use the same key for Tier 3 and the Trust Registry?
Yes. If the same entity controls both the API and the runtime, one keypair works for both.
What key type should I use?
Ed25519. It is fast, widely supported, and the standard across the agent.json and Trust Registry specs.
4. Field Reference
4.1 Root Object
| Field | Type | Req | Description |
|---|---|---|---|
| version | string | yes | Manifest schema version. "1.0", "1.1", "1.2", "1.3", or "1.4". |
| origin | string | yes | The domain this manifest represents. Must match the domain serving the file. |
| payout_address | string | yes | Wallet address for receiving payments. Currently USDC on Base L2. |
| display_name | string | no | Human-readable service name. Used in dashboards and reporting. |
| description | string | no | Brief description. Used for semantic discovery when intents aren't declared. |
| intents | array | no | Array of Intent objects declaring available capabilities. |
| payments | object | no | Protocol-agnostic payment wrapper. Keys are protocol names (x402, l402, mpp, custom). v1.3+. |
| x402 | object | no | Legacy x402 payment discovery. Deprecated in v1.3 — use payments.x402 instead. |
| bounty | object | no | Default economic terms for all intents (provider → runtime). |
| incentive | object | no | Default suggested incentive for all intents (runtime → provider). |
| identity | object | no | Provider identity metadata for Tier 3 (DID, public_key, oatr_issuer_id). v1.4 adds OATR trust registry integration. |
| commitments | object | no | Behavioral invariants (latency bounds, data residency, SLA). Optional Ed25519 signature for tamper evidence. v1.4+. |
| extensions | object | no | Vendor-specific extension namespaces. Shape: extensions.<vendor>. |
versionstringrequiredManifest schema version. "1.0", "1.1", "1.2", "1.3", or "1.4".
originstringrequiredThe domain this manifest represents. Must match the domain serving the file.
payout_addressstringrequiredWallet address for receiving payments. Currently USDC on Base L2.
display_namestringHuman-readable service name. Used in dashboards and reporting.
descriptionstringBrief description. Used for semantic discovery when intents aren't declared.
intentsarrayArray of Intent objects declaring available capabilities.
paymentsobjectProtocol-agnostic payment wrapper. Keys are protocol names (x402, l402, mpp, custom). v1.3+.
x402objectLegacy x402 payment discovery. Deprecated in v1.3 — use payments.x402 instead.
bountyobjectDefault economic terms for all intents (provider → runtime).
incentiveobjectDefault suggested incentive for all intents (runtime → provider).
identityobjectProvider identity metadata for Tier 3 (DID, public_key, oatr_issuer_id). v1.4 adds OATR trust registry integration.
commitmentsobjectBehavioral invariants (latency bounds, data residency, SLA). Optional Ed25519 signature for tamper evidence. v1.4+.
extensionsobjectVendor-specific extension namespaces. Shape: extensions.<vendor>.
4.2 Intent Object
Each intent represents one capability the service offers to agents.
| Field | Type | Req | Description |
|---|---|---|---|
| name | string | yes | Machine-readable identifier. Must be snake_case, unique within the manifest. |
| description | string | yes | Natural-language description of the capability. Primary field for semantic matching. |
| endpoint | string | no | API endpoint URL. Absolute URL or path relative to origin. |
| method | string | no | HTTP method: "GET", "POST", "PUT", or "DELETE". |
| parameters | object | no | Map of parameter names to Parameter objects. |
| returns | object | no | Description of the response shape (type, properties, description). |
| price | object | no | What the provider charges to access this intent. |
| payments | object | no | Per-intent payment protocol overrides. Same structure as root payments. v1.3+. |
| x402 | object | no | Legacy per-intent x402 overrides. Deprecated in v1.3 — use payments.x402. |
| bounty | object | no | Per-intent bounty override. Takes priority over manifest-level bounty. |
| incentive | object | no | Per-intent incentive override. Takes priority over manifest-level incentive. |
namestringrequiredMachine-readable identifier. Must be snake_case, unique within the manifest.
descriptionstringrequiredNatural-language description of the capability. Primary field for semantic matching.
endpointstringAPI endpoint URL. Absolute URL or path relative to origin.
methodstringHTTP method: "GET", "POST", "PUT", or "DELETE".
parametersobjectMap of parameter names to Parameter objects.
returnsobjectDescription of the response shape (type, properties, description).
priceobjectWhat the provider charges to access this intent.
paymentsobjectPer-intent payment protocol overrides. Same structure as root payments. v1.3+.
x402objectLegacy per-intent x402 overrides. Deprecated in v1.3 — use payments.x402.
bountyobjectPer-intent bounty override. Takes priority over manifest-level bounty.
incentiveobjectPer-intent incentive override. Takes priority over manifest-level incentive.
When endpoint is present, the intent is a direct API intent. When absent, it's a semantic intent — the runtime uses the description for capability matching and executes via web automation.
| Pattern | Example | Use For |
|---|---|---|
| search_* | search_products | Finding and listing items |
| get_* | get_order_status | Retrieving specific data |
| add_* | add_to_cart | Creating or adding |
| update_* | update_profile | Modifying existing data |
| submit_* | submit_application | Form submissions |
| complete_* | complete_purchase | Finalizing transactions |
4.3 Price Object
What the provider charges to access an intent. Different from bounty (provider pays runtime) and incentive (runtime pays provider).
| Field | Type | Req | Description |
|---|---|---|---|
| amount | number | yes | Cost per call in the specified currency. |
| currency | string | yes | "USD" for fiat pricing, "USDC" for on-chain pricing. |
| model | string | no | "per_call" (default), "per_unit", or "flat". |
| unit_param | string | no | For per_unit model: which parameter determines the unit count. |
| free_tier | number | no | Number of free calls before pricing applies. |
| network | string | string[] | no | Settlement network(s) for on-chain currencies. e.g. "base" or ["base", "arbitrum"]. Omit for fiat. |
amountnumberrequiredCost per call in the specified currency.
currencystringrequired"USD" for fiat pricing, "USDC" for on-chain pricing.
modelstring"per_call" (default), "per_unit", or "flat".
unit_paramstringFor per_unit model: which parameter determines the unit count.
free_tiernumberNumber of free calls before pricing applies.
networkstring | string[]Settlement network(s) for on-chain currencies. e.g. "base" or ["base", "arbitrum"]. Omit for fiat.
Example — Paid API:
{
"name": "analyze_document",
"description": "AI-powered document analysis. Extracts key clauses, identifies risks, and generates a summary.",
"endpoint": "/api/v1/analyze",
"method": "POST",
"parameters": {
"document_url": { "type": "string", "required": true, "description": "URL of the document to analyze" },
"analysis_type": { "type": "string", "required": false, "enum": ["summary", "risk", "full"], "default": "full" }
},
"price": {
"amount": 0.50,
"currency": "USDC",
"model": "per_call",
"network": "base"
}
}4.4 Commitmentsv1.4
The commitments block declares behavioral invariants — service-level guarantees that agents and runtimes can use for routing, trust scoring, and enforcement. Commitments can be unsigned (for discovery) or signed with Ed25519 (for tamper-evident enforcement).
| Field | Type | Req | Description |
|---|---|---|---|
| schema_version | string | no | Commitments schema version. Currently "1.0". |
| entries | array | no | Array of commitment entry objects. |
| signature | string | no | Ed25519 signature over JCS-canonicalized (RFC 8785) entries array. Uses the key from identity.public_key. |
schema_versionstringCommitments schema version. Currently "1.0".
entriesarrayArray of commitment entry objects.
signaturestringEd25519 signature over JCS-canonicalized (RFC 8785) entries array. Uses the key from identity.public_key.
Commitment Entry Fields
| Field | Type | Req | Description |
|---|---|---|---|
| type | string | yes | Category of commitment (e.g. "latency_bound", "data_residency", "uptime_sla", "regulatory_compliance"). |
| constraint | string | yes | Human-readable constraint. This is the authoritative summary for automated discovery. |
| verifiable | boolean | no | Whether this commitment can be mechanically verified (e.g. via monitoring). |
| ref | string | no | URL to enforcement-level detail (SLA document, audit evidence, compliance certificate). Discovery systems ignore it; enforcement systems follow it. |
typestringrequiredCategory of commitment (e.g. "latency_bound", "data_residency", "uptime_sla", "regulatory_compliance").
constraintstringrequiredHuman-readable constraint. This is the authoritative summary for automated discovery.
verifiablebooleanWhether this commitment can be mechanically verified (e.g. via monitoring).
refstringURL to enforcement-level detail (SLA document, audit evidence, compliance certificate). Discovery systems ignore it; enforcement systems follow it.
Example — Commitments with Signature:
{
"commitments": {
"schema_version": "1.0",
"entries": [
{
"type": "latency_bound",
"constraint": "p99 < 500ms",
"verifiable": true
},
{
"type": "data_residency",
"constraint": "EU-only processing",
"verifiable": false
},
{
"type": "uptime_sla",
"constraint": "99.9% monthly uptime",
"verifiable": true,
"ref": "https://example.com/sla.json"
},
{
"type": "regulatory_compliance",
"constraint": "SOC 2 Type II certified",
"verifiable": true,
"ref": "https://example.com/compliance/soc2-2026.pdf"
}
],
"signature": "base64url-Ed25519-signature"
}
}constraint). Signed commitments add tamper evidence — the signature is computed over the JCS-canonicalized (RFC 8785) entries array using the Ed25519 key from identity.public_key.5. Payment Discoveryv1.3
The payments wrapper is a protocol-agnostic object where each key represents a payment protocol. Presence of a key means the provider supports that protocol — no supported: true flag needed.
"solana_pay": {} today — no spec change needed. Agents that don't recognize a protocol simply skip it.{
"payments": {
"x402": {
"networks": [
{
"network": "base",
"asset": "USDC",
"contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"facilitator": "https://x402.org/facilitator"
}
]
},
"l402": {
"macaroon_endpoint": "https://api.example.com/l402/macaroon",
"network": "lightning",
"currency": "BTC",
"description": "Pay via Lightning Network"
},
"mpp": {
"provider": "stripe",
"currency": "USD",
"checkout_url": "https://example.com/checkout"
}
}
}5.1 Built-in Protocols
x402On-chainHTTP 402 payment challenges with on-chain settlement (USDC on Base, Arbitrum, etc.). See section 6 for full field reference.
l402LightningLightning Network micropayments via macaroon-based authentication. Sub-second settlement, ideal for high-frequency API calls.
mppTraditionalManaged Payment Provider — Stripe, Square, or other traditional processors. Credit card, ACH, and other fiat rails.
5.2 Intent-Level Payments
Each intent can override root-level payment configuration using the same payments wrapper structure.
{
"name": "analyze_document",
"description": "AI-powered document analysis.",
"payments": {
"x402": {
"direct_price": 0.50,
"ticket_price": 0.40,
"description": "Pay $0.50/analysis directly, or $0.40 with a Session Ticket."
}
}
}6. x402 Field Referencev1.2+
HTTP 402 (Payment Required) is a standard HTTP status code. The x402 protocol builds on this by defining a structured payment challenge and proof mechanism. The x402 object enables agents to discover payment capabilities before making a request.
price, does not prevent other payment mechanisms, and does not make x402 the only supported payment rail. The extensions namespace remains available for other payment rail metadata.6.1 Root-Level x402
Declares that this provider supports x402 payment negotiation. These values serve as defaults for all intents.
| Field | Type | Req | Description |
|---|---|---|---|
| supported | boolean | yes | Whether the provider accepts x402 payment proofs. |
| network | string | no | Settlement network in single-network mode. e.g. "base". |
| asset | string | no | Payment asset. e.g. "USDC", "ETH". |
| contract | string | no | Token contract address for ERC-20 assets. |
| facilitator | string | no | URL of the x402 facilitator service. |
| recipient | string | no | Recipient address. Defaults to payout_address. |
| networks | array | no | Multi-network config. When present, flat fields are ignored. |
supportedbooleanrequiredWhether the provider accepts x402 payment proofs.
networkstringSettlement network in single-network mode. e.g. "base".
assetstringPayment asset. e.g. "USDC", "ETH".
contractstringToken contract address for ERC-20 assets.
facilitatorstringURL of the x402 facilitator service.
recipientstringRecipient address. Defaults to payout_address.
networksarrayMulti-network config. When present, flat fields are ignored.
Single-network (flat):
{
"x402": {
"supported": true,
"network": "base",
"asset": "USDC",
"contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"facilitator": "https://x402.org/facilitator"
}
}Multi-network:
{
"x402": {
"supported": true,
"networks": [
{
"network": "base",
"asset": "USDC",
"contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"facilitator": "https://x402.org/facilitator"
},
{
"network": "arbitrum",
"asset": "USDC",
"contract": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"facilitator": "https://x402.org/facilitator"
}
]
}
}If networks is present, it takes priority and flat fields (network, asset, etc.) are ignored.
6.2 Intent-Level x402 Override
Per-intent x402 metadata. Overrides or extends the root-level x402 configuration for that specific intent.
| Field | Type | Req | Description |
|---|---|---|---|
| supported | boolean | no | Override the root-level supported flag for this intent. |
| direct_price | number | no | Price per request when paying directly via x402. |
| ticket_price | number | no | Discounted price when using a prepaid session ticket. |
| description | string | no | Human-readable explanation of x402 pricing for this intent. |
| network_pricing | array | no | Per-network price overrides when costs differ across chains. |
supportedbooleanOverride the root-level supported flag for this intent.
direct_pricenumberPrice per request when paying directly via x402.
ticket_pricenumberDiscounted price when using a prepaid session ticket.
descriptionstringHuman-readable explanation of x402 pricing for this intent.
network_pricingarrayPer-network price overrides when costs differ across chains.
Example:
{
"x402": {
"direct_price": 0.50,
"ticket_price": 0.40,
"description": "Pay $0.50/request directly via x402, or $0.40 with a Session Ticket."
}
}Resolution order: network_pricing[matching_network] → intent-level direct_price/ticket_price → price.amount
6.3 Full v1.4 Example — Payments, Identity & Commitments
{
"version": "1.4",
"origin": "api.example.com",
"payout_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
"display_name": "Example Intelligence API",
"description": "AI-powered document analysis API with multi-protocol payments.",
"identity": {
"did": "did:web:api.example.com",
"public_key": "base64url-encoded-Ed25519-public-key",
"oatr_issuer_id": "example-intelligence"
},
"payments": {
"x402": {
"networks": [
{
"network": "base",
"asset": "USDC",
"contract": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"facilitator": "https://x402.org/facilitator"
},
{
"network": "arbitrum",
"asset": "USDC",
"contract": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"facilitator": "https://x402.org/facilitator"
}
]
},
"mpp": {
"provider": "stripe",
"currency": "USD",
"checkout_url": "https://api.example.com/checkout"
}
},
"commitments": {
"schema_version": "1.0",
"entries": [
{
"type": "latency_bound",
"constraint": "p99 < 500ms",
"verifiable": true
},
{
"type": "data_residency",
"constraint": "EU-only processing",
"verifiable": false
},
{
"type": "uptime_sla",
"constraint": "99.9% monthly uptime",
"verifiable": true,
"ref": "https://api.example.com/sla.json"
}
],
"signature": "base64url-Ed25519-signature-over-JCS-canonicalized-entries"
},
"intents": [
{
"name": "analyze_document",
"description": "AI-powered document analysis. Extracts key clauses, identifies risks, and generates a summary.",
"endpoint": "/api/v1/analyze",
"method": "POST",
"parameters": {
"document_url": { "type": "string", "required": true }
},
"price": {
"amount": 0.50,
"currency": "USDC",
"model": "per_call",
"network": ["base", "arbitrum"]
},
"payments": {
"x402": {
"direct_price": 0.50,
"ticket_price": 0.40,
"description": "Pay $0.50/analysis directly via x402, or $0.40 with a Session Ticket."
}
}
}
],
"bounty": { "type": "cpa", "rate": 0.25, "currency": "USDC" }
}7. Economic Flows
| Price | Bounty | Incentive | |
|---|---|---|---|
| Direction | User → Provider | Provider → Runtime | Runtime → Provider |
| Purpose | Gating access / buying goods | Advertising / routing acquisition | Performance / fulfillment reward |
| Required | Yes (blocks access) | No (provider's choice) | No (runtime's choice) |
| Declared via | price | bounty | incentive |
All three can coexist in the same manifest. A service can receive user payments for API calls (price), offer a routing bounty to agents who bring traffic (bounty), and request a performance payment from the runtime (incentive).
Payment Rail Support
- x402 (HTTP 402) — On-chain micropayments via payment challenges. Declared in
payments.x402. - L402 (Lightning) — Lightning Network micropayments via macaroon auth. Declared in
payments.l402. - MPP (Managed) — Traditional processors (Stripe, Square). Declared in
payments.mpp. - Direct transfer — Agents send payment directly to
payout_address. - Custom protocols — Any protocol via custom keys in
payments. Spec doesn't need to change.
8. Versioning
The version field uses "MAJOR.MINOR" format.
- Major changes (1.0 → 2.0) indicate breaking changes.
- Minor changes (1.0 → 1.1) indicate backward-compatible additions.
v1.0 — Core manifest with intents, parameters, bounty, incentive, identity.
v1.1 — Adds price.network field and the x402 object for payment discovery.
v1.2 — Extends multi-network support with x402.networks array for multi-chain settlement.
v1.3 — Introduces the payments wrapper for protocol-agnostic payment discovery. Built-in support for x402, L402, and MPP. Top-level x402 deprecated in favor of payments.x402.
v1.4 — Adds identity.oatr_issuer_id for OATR trust registry integration and the commitments block for behavioral invariants with optional Ed25519 signatures. Consolidates trust discovery from 4 files to 2.
All v1.0 manifests remain valid. Runtimes should process all v1.x fields and additionally parse payments, identity, and commitments if present. Legacy top-level x402 is still accepted for backward compatibility.
9. Security Considerations
- Origin verification is mandatory. Runtimes must reject manifests where the origin doesn't match the serving domain.
- HTTPS is mandatory. Runtimes must not fetch manifests over HTTP.
- Intent descriptions are untrusted input. Runtimes should not execute them as code or use them where injection is possible.
- Endpoint URLs must be same-origin. A manifest at
example.comshould not declare endpoints atevil.com. - API secrets never appear in the manifest. The manifest is public. All secrets live server-side.
- Manifests can change. Providers can modify at any time. Runtimes should re-fetch periodically and handle changes gracefully.
This specification is released under the MIT License. Anyone can implement, extend, or build upon it without restriction. View on GitHub →