Every interaction on the web reduces to four operations: read structured data, write validated state changes, receive notifications about changes, and discover what's available. The Capabilities Manifest is the fourth operation — a single YAML file that tells an AI agent everything it needs to interact with a domain safely and correctly.
This document specifies version 0.1 of the format.
Location
The manifest lives at /.well-known/capabilities.yaml at the root of every participating domain, following RFC 8615 (Well-Known URIs). An agent arriving at an unfamiliar domain fetches this file first.
Content type: application/yaml or text/yaml. UTF-8 encoding.
Structure
The manifest has seven top-level sections. Two are required. Five are optional.
manifest (required)
Metadata about this file.
manifest:
spec: "0.1" # Spec version
updated: "2026-03-26T00:00:00Z" # Last modified (ISO 8601)
canonical: "https://perardua.dev/specs/capabilities" - spec — version of this specification the file conforms to.
- updated — when the manifest was last modified. Agents use this for cache invalidation alongside standard HTTP ETag/Last-Modified headers.
- canonical — URL of this specification for reference.
domain (required)
Identity of the service. Not marketing copy — honest, structured, machine-parseable.
domain:
name: "Service Name"
url: "https://example.com"
description: "What this service does. One paragraph."
contact: "api@example.com"
tos: "/terms"
privacy: "/privacy" - name — human-readable service name.
- url — canonical domain URL.
- description — what this service does, who it's for. Honest. An agent uses this to decide whether to explore further.
- contact — email for integration or API questions.
- tos — path or URL to terms of service.
- privacy — path or URL to privacy policy.
auth (optional)
Authentication methods this domain supports. Each method gets an id that endpoints reference. Omit entirely if everything is public.
auth:
- id: public
type: none
- id: github
type: oauth2
provider: github
authorize_url: "https://github.com/login/oauth/authorize"
scopes: ["read:user"]
- id: bearer
type: bearer
description: "JWT obtained via OAuth flow"
- id: api_key
type: api_key
header: "X-API-Key"
- id: signet
type: signet
proofs:
required: [identity]
optional: [age, jurisdiction, payment_authorization] Supported types: none, oauth2, bearer, api_key, signet. The agent uses the type to determine how to authenticate. OAuth flow mechanics are handled by the agent, not specified in the manifest.
read (optional)
Data the agent can query. Each entry is one endpoint. Read endpoints return data without changing state.
read:
- id: catalog
path: /api/products
description: "Product catalog with attributes and pricing"
auth: public
params:
- name: q
type: string
required: false
description: "Search query"
- name: category
type: string
required: false
enum: [books, prints]
- name: page
type: integer
required: false
default: 1
- name: per_page
type: integer
required: false
default: 20
max: 100
response:
format: application/json
schema: /api/products/schema.json
cache:
ttl: 3600
signal: stable
pagination:
style: cursor
default_size: 20
max_size: 100
rate_limit:
requests: 100
window: 60s
# Streaming read — a read that doesn't end
- id: feed
path: /api/feed
description: "Real-time content stream"
auth: bearer
response:
format: text/event-stream
stream:
enabled: true
heartbeat_interval: 30s
replayable: true
reconnect_after: 3s
cache:
signal: volatile Field reference:
- id — unique identifier within this manifest.
- path — URL path. May include
{param}placeholders for path parameters. - description — what this endpoint returns.
- auth — references an
auth.id. Usepublicor omit for unauthenticated. - params — query or path parameters with type, description, and constraints.
- response.format — MIME type.
application/json,text/html,application/pdf,text/event-stream,application/x-ndjson, etc. - response.schema — optional URL to JSON Schema describing the response.
- stream — optional. Declares this as a streaming read.
heartbeat_intervalsets expected keepalive frequency.replayableindicates Last-Event-ID reconnection support.reconnect_aftersuggests retry delay. - cache.ttl — seconds. 0 means do not cache.
- cache.signal —
stable(changes infrequently),volatile(changes often, always re-fetch),immutable(never changes). - pagination — optional.
cursororoffsetstyle. - rate_limit — optional. Requests per time window.
A stream is a read that doesn't end. The agent opens the connection, consumes data as it arrives, and closes when done. This covers social feeds, real-time tracking, live content, and any continuous data source. No new primitive is needed — streaming is reading.
HTML pages are valid read endpoints. A static content site declares its pages as read endpoints with format: text/html. The agent parses HTML the same way it parses JSON — by reading and reasoning.
write (optional)
State changes the agent can request. Each entry is one endpoint that modifies data in the world.
write:
- id: create_order
path: /api/orders
method: POST
description: "Place a product order"
auth: bearer
request:
format: application/json
schema: /api/orders/request.json
response:
format: application/json
schema: /api/orders/response.json
idempotent: true
idempotency_key: X-Idempotency-Key
side_effects:
- "Creates pending order"
- "Initiates payment capture"
- "Sends confirmation to notification feed"
payment:
provider: stripe
flow: redirect
currency: usd Field reference:
- method — HTTP method:
POST,PUT,PATCH, orDELETE. - request — content type and optional schema for the request body.
- idempotent — whether retrying is safe.
- idempotency_key — header name for idempotency token, if applicable.
- side_effects — human-readable list of what changes in the world. The agent should present these to its user before executing.
- payment — optional. Declares payment flow.
provideridentifies the processor.flowisredirect(agent sends user to payment page) orinline(payment handled in-band).
notify (optional)
Feeds the agent can poll for updates. Atom format only (RFC 4287).
notify:
- id: updates
path: /feed/atom.xml
format: atom
description: "New publications, order status changes"
auth: public
poll_hint: 3600s
categories:
- new_publication
- order_status - format —
atomonly in v0.1. - poll_hint — suggested minimum polling interval. The agent controls its own schedule.
- categories — event types present in this feed. Agent can filter.
The agent owns the polling relationship. The domain provides the feed. Nothing in between needs to exist. This is a deliberate architectural choice: push mechanisms give the domain control over when to interrupt the user. Polling gives the agent control.
health (optional)
Service availability check. Omit for static sites — if the manifest loads, the site is up.
health:
path: /api/health
format: application/json errors (optional)
How the domain reports errors. Omit for static sites.
errors:
format: application/problem+json Recommended: RFC 9457 Problem Details for HTTP APIs. Also acceptable: application/json with a consistent error shape.
constraints (optional)
Rules the domain enforces. These are informational — the domain declares what it enforces so agents can reason about access, limits, and requirements before acting.
constraints:
- id: metered_access
type: access
description: "5 free articles per month, then subscription required"
applies_to: [articles]
details: /api/access/status
version: "2026-03-26"
- id: transaction_limit
type: financial
description: "Maximum single transaction: $10,000"
applies_to: [checkout]
- id: age_gate
type: content
description: "Adult content requires age verification"
requires_proof: age
applies_to: [adult_content]
- id: data_sharing
type: privacy
description: "Anonymized usage data shared with analytics partners"
opt_out: /api/privacy/preferences - type — controlled vocabulary:
access,financial,content,privacy,commerce,rate_limit. - applies_to — list of read or write endpoint ids this constraint affects.
- details — optional. Path to a read endpoint that returns the current computed state of this constraint (e.g., how many free articles remain, what the cancellation fee is for a specific booking). Static description in the manifest, dynamic details via API.
- requires_proof — optional. Signet proof type required to satisfy this constraint.
- opt_out — optional. Path to an endpoint for opting out of this constraint.
- version — optional. Change detection for constraint updates.
Constraints are domain-informational only in v0.1. Agent-enforced constraints (advertising contracts, signed packages, token compensation) are deferred — they require attestation protocols and payment infrastructure that don't yet exist.
Design Principles
The manifest works for the web as it exists. HTML pages are valid read endpoints. A static site with no API and no database can publish a capabilities manifest. The spec doesn't require a JSON API to be useful.
The agent controls the relationship. The agent decides when to poll, what to cache, and how to present data to its user. The domain declares what's available. The domain does not push, interrupt, or control the agent's behavior.
Side effects are declared, not hidden. Every write endpoint lists what it changes in the world. An agent that reads "Initiates payment capture" knows to ask its user before proceeding. Undeclared side effects are a breach of the manifest's contract.
Auth is per-endpoint, not per-domain. A domain may expose some data publicly and gate other data behind authentication. Each endpoint declares its own requirement.
Cache signals are honest. stable means the data changes infrequently and caching is safe. volatile means always re-fetch. immutable means it will never change. Dishonest cache signals degrade agent trust in the domain.
What's Excluded
The following are deliberately omitted from v0.1:
- WebSocket / bidirectional streams — SSE streaming reads are supported (agent opens connection, consumes data). Bidirectional protocols where the domain pushes unsolicited data are excluded. The agent controls the connection.
- GraphQL — REST endpoints are sufficient. Agents compose multiple calls trivially.
- Webhooks — the agent polls or streams. The domain doesn't push to agent infrastructure.
- Agent-enforced constraints — advertising contracts, signed compliance packages, token compensation. Deferred to v0.2 — requires attestation protocols and payment rails.
- Token economy — future spec version. Requires its own treatment.
- Multi-step transaction flows — these are a UI artifact. An agent submits all required data in one write. The domain validates and executes atomically.
- Faceted search / filter UIs — agents query with parameters, not filter checkboxes. Hierarchical data is navigated via API endpoints, not UI affordances.
- API versioning — each endpoint's path is its version.
- Batch operations — a write endpoint that accepts an array. No special primitive.
- File upload — a write endpoint with
multipart/form-data. No special primitive.
Reference Implementations
The following domains publish capabilities manifests conforming to this specification:
- perardua.dev — static content site (research portfolio)
- cageandmirror.com — commerce site (book publisher with Stripe checkout)
- centaur.tools — community platform (tool registry with OAuth, search, forum)
- signet.tools — product documentation site
- kindex.tools — product documentation site
- exemplar.tools — product documentation site
These span the three primary web archetypes: static content, community platform, and commerce. Together they demonstrate that the format works for the web as it exists today.
Relationship to Existing Standards
- robots.txt told crawlers what not to touch. The manifest tells agents everything — what to touch, how, and under what rules.
- OpenAPI / Swagger describes APIs for developers building integrations. The manifest describes domains for agents acting autonomously. OpenAPI is for humans writing code. The manifest is for machines making decisions.
- Schema.org / JSON-LD adds structured metadata to HTML pages. The manifest declares operational capabilities — not just what data exists, but what actions are available and what they cost.
- Atom (RFC 4287) is the notification format. The manifest declares where feeds live. Atom provides the feed content.
- RFC 8615 governs the
/.well-known/URI prefix. The manifest follows this convention.
Version 0.1 · March 2026 · Jeremy McEntire · jmc@cageandmirror.com
The credential layer referenced in this specification is Signet. The persistent agent context layer is Kindex.