A public registry of action types that AI agents take on a user's behalf, and the service-specific variants of each action.
Agents, orchestrators, signing, and execution sit downstream of this; the registry only describes what the actions are and how they vary by service.
<authority>.<sector>.<domain>.<object>.<action>.v<N>
org.intentschema for the public catalog; com.<vendor> or com.<org> for private.communication and productivity, but the list is open: new sectors are added by PR when a real intent needs one. Private namespaces (com.<org>.*, x.<org>.*) MAY use any sector.v1, v2, etc. Immutable once published; breaking changes mint a new version.Segments MUST be lowercase ASCII; objects MUST be singular nouns; verbs MUST be present tense.
Every published file is served at two URL shapes; implementations choose.
https://intentschema.org/intents/communication/email/message/send/v1.jsonhttps://intentschema.org/intents/communication/email/message/send/@sha256:<hex>/v1.jsonHash = sha256(JCS(file)) (RFC 8785 canonicalization). The hash-pinned URL returns the matching bytes or 404; it MUST NOT redirect on mismatch. @sha256-<base64> accepted as an SRI-style alias.
Use bare URLs for documentation and browsing. Use hash-pinned URLs in signed payloads, approval surfaces, and any context where schema substitution must be impossible.
The registry root also publishes /index.json — a machine-readable catalog of every intent, profile, and common schema with its bare URL, hash-pinned URL, and current sha256. Consumers fetch this once to enumerate the catalog instead of crawling.
{
"$id": "https://intentschema.org/intents/communication/email/message/send/v1.json",
"fqdn": "org.intentschema.communication.email.message.send.v1",
"title": "Send email message",
"description": "Sends an email message to one or more recipients.",
"payload": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "...": "..." },
"result": { "type": "object", "...": "..." },
"examples": [
{ "name": "basic send", "value": { "...": "..." } }
]
}
Target — every payload declares a target identifying where the action happens. Shared shape at common/target/v1.json:
{ "system": "gmail", "external_id": "msg_abc123", "etag": "W/\"xyz\"" }
system is a lowercase provider id; external_id is required for update/delete/reply intents and omitted for create-in-default-container; etag is an optional optimistic-concurrency token.
Attachments and blobs — carried by reference (common/blob-ref/v1.json). Required: url and sha256. Executors verify the hash before passing bytes to the provider.
Idempotency — mutating intents MAY include idempotency_key (opaque string, typically ULID or UUIDv7). Executors use it to deduplicate retries against the provider.
Update semantics — an update-style intent picks either full object replace or an RFC 6902 JSON patch array, declared in the payload schema. Merge patch is not used.
Result schema — every intent MAY declare a result block (JSON Schema) describing what the executor returns on success.
Read verbs (list, read, get) — three verbs for fetching data, each with a distinct role:
list — enumerate a collection with optional filter. Returns { items: [...], next_cursor?, estimated_total? }. Accepts target (system only), object.query/object.filter, object.limit, object.cursor. No idempotency_key.read — fetch a single piece of content you consume (a message body, a note, a thread, a draft). Returns the full content. Requires target.external_id. No idempotency_key. Use read when the object has textual content a human would literally read.get — fetch a single structured record you look up (channel metadata, event details, contact card, task record). Returns { external_id, object, etag? }. Requires target.external_id. No idempotency_key. Use get when the object is a data record, not a piece of content.The send/read pairing is natural for messaging (you send a message, you read a message). The create/get pairing is natural for records (you create an event, you get an event).
availability.set mode — under productivity.calendar.availability.set, the object.mode field selects which availability concept is being set (working_hours, focus, ooo). Avoids exploding into separate intents per mode.
Examples — each intent SHOULD include an inline examples array. Each entry has name and value; value MUST validate against the intent's payload. CI validates every entry.
Provider-specific fields — provider-specific request and response fields live at the payload top level under a key matching target.system. A Gmail payload targeting system: "gmail" carries its extras under a gmail object; a Microsoft Graph payload under ms_graph; a Google Calendar payload under google_calendar. Profiles narrow what goes in that key. There is no separate extensions slot.
Payload reuse — where a mature vocabulary exists, reuse it: JMAP for email, jCal for calendar, jCard for contacts, FHIR for health, ISO 20022 for payments.
A profile pins one core intent and narrows its payload for a specific service.
{
"$id": "https://intentschema.org/profiles/com.google.gmail/communication.email.message.send.v1.json",
"id": "org.intentschema.communication.email.message.send.v1@com.google.gmail.v1",
"pins": "https://intentschema.org/intents/communication/email/message/send/v1.json",
"title": "Gmail email send profile",
"description": "Gmail-specific constraints and extensions.",
"constraints": { "...": "JSON Schema differential applied on top of the core" }
}
Rules:
result block that extends the core's result. The effective result schema is core.result AND profile.result (composed via allOf). Use this to document provider-specific response fields. Place additions under a top-level key matching target.system (e.g., gmail: { historyId, labelIds }).api block mapping the intent to the provider's concrete API call: { method, path, scopes, docs }. For JMAP providers, jmap_method replaces method+path. This gives executors the exact endpoint to call.v2, profile maintainers decide whether to publish a v2 profile; the v1 profile stays valid for v1 consumers.vN is immutable in its normative content (payload, result, constraints). Editorial fields (title, description) may be clarified.vN+1 alongside vN. The old version remains served indefinitely.replaced_by URL pointing at its successor.Deliberately out of scope for the first cut. Listed so contributors don't over-engineer the core.
readOnlyHint, destructiveHint, idempotentHint, openWorldHint), AWS IAM access levels, Kubernetes RBAC verbs./.well-known/intents). An RFC 8615 document where a deployment advertises which profiles it accepts (hash-pinned), required OAuth scopes, endpoints, and any tightened-further policy.