Commands — io.best.agents.commands
Commands are intents to change a domain service. They are sent to the service by any caller — a Process Manager, an AI agent, a UI, or another service. The service validates, queues, and processes them asynchronously.
Normative reference: SPEC.md — Commands. Canonical schema: commands.json; envelope: cloudEvent.json.
POST /commandsis a behaviour endpoint, not a resource collection. Sending a command is not creating a "command resource" — it is expressing an intent./commandsis a single entry point for every operation the service accepts; what happens is determined entirely by the envelopetype, not the HTTP verb or the URL. In REST you manipulate resources; in BEST you invoke named operations and observe the facts they produce.
Commands ride the CloudEvents 1.0 envelope — see SPEC.md — Wire Format for the field table and examples.
HTTP API
| Method | Path | Description |
|---|---|---|
| GET | /commands |
Catalogue of all available command types and their schema URIs |
| POST | /commands |
Send a command (CloudEvent). Validates, queues, returns 201 |
| GET | /commands/{schema}/{version} |
JSON Schema document for one command type and version |
The catalogue (GET /commands)
Each entry: schema (kebab-case name, the {schema} path segment — distinct from the PascalCase envelope type), version, dataschema (resolvable URI, the exact value to put on the command envelope), optional description, optional workflows (recipe cross-links), optional impact (high-impact annotation — see below).
{
"commands": [
{
"schema": "propose-counter",
"version": "1.0",
"dataschema": "https://api.example.com/commands/propose-counter/1.0",
"description": "Propose a counter-offer in a contract negotiation"
}
]
}
Individual command types are domain data, not capabilities — they never appear as manifest capability entries.
Ingestion (POST /commands)
- Validate required envelope attributes.
- Look up the schema in the server's own catalogue — the inbound
dataschemais a selector, not a location; servers MUST NOT fetch a caller-supplied URI (SSRF — see Security). - Validate
dataagainst that schema. Schema selection, authorisation, and dispatch MUST key on the same identifier. - Valid → durably queue, return
201with{ "id": ..., "correlationId": ... }. Invalid →400.
The envelope id is the idempotency key: duplicates are rejected within a retention window; same id with a different payload → 409. type is the routing key; source must never be the sole routing key. 201 (durably recorded, processing will happen) is the target; use 202 only when the implementation cannot durably enqueue before responding.
Correlation
The correlationid envelope attribute (a CloudEvents extension, lowercase on the wire) ties a command to everything it causes. The caller may set it; when omitted, the server adopts the command's id. The 201 response echoes the effective value as correlationId, every resulting event must carry it, and follow-up commands in the same process should propagate it. Retrieve results with GET /events?correlationId=... (history) and GET /events/stream?correlationId=... (push). See Design Decisions — Command Result Retrieval.
Schema documents (GET /commands/{schema}/{version})
Returns the raw JSON Schema for one command version — the canonical target of the catalogue's dataschema URI. 404 for unknown name or version.
The document may declare produces: an array of PascalCase event types the command can raise, e.g. ["CounterProposed", "NegotiationFailed"]. Failure outcomes are ordinary events in that list; the naming convention (*Failed) is service-defined. Silent failures are handled client-side via timeout — services should document expected processing times and always publish a failure event rather than silently dropping a command.
When the service publishes workflows, the document should also carry the operation's workflows cross-link array — the same ids the catalogue entry carries (see Workflows — Discoverability).
High-impact annotations (impact)
A command that moves money, destroys data, or cannot be undone may carry an impact annotation — on its catalogue entry and, identically, as a top-level member of its schema document:
"impact": {
"categories": ["financial"],
"confirmation": "required",
"warning": "Places a real order on your broker account. Capital is at risk."
}
categories names the kind of impact (financial, destructive, irreversible, compliance — open vocabulary; unknown values are treated as high-impact). confirmation: "required" means a consumer acting on behalf of a human must not submit the command without explicit, per-submission confirmation from that human; "recommended" allows proceeding under a durable prior authorization. warning is text the consumer should surface, substantially intact, before asking.
The annotation is the discovery half of the high-impact controls in Security: it tells well-behaved consumers what to do, and never replaces the server-side control — a server cannot rely on clients honoring it. Normative reference: SPEC.md — Impact Annotations.