Domain contract — 8 items
Eight items. Declare them all and the agent is generated.
1. Commands — what I can do
Section titled “1. Commands — what I can do”Every state-changing operation must be a typed contract.
id: inventory.stock.receiveoperation_type: COMMANDrisk_level: R2idempotency: required # ⚠ MANDATORYconcurrency: optimisticinput: { type: object, ... }output: { type: object, ... }| Field | Why |
|---|---|
idempotency: required |
⛔ Without it, a retry creates a duplicate |
risk_level |
The approval flow derives from it |
concurrency |
So the agent does not write over stale data |
2. Queries — what I can see
Section titled “2. Queries — what I can see”Four types are mandatory. Missing one and the agent cannot work.
| Type | Example | What the agent uses it for |
|---|---|---|
| Summary | inventory.daily_summary |
“What’s the overall state?” |
| Anomaly | inventory.low_stock |
“What’s wrong?” |
| Search | inventory.item.search |
Finding a specific record |
| Detail | inventory.stock.get |
One record in full |
3. ⚡ Verification — the right to say “done”
Section titled “3. ⚡ Verification — the right to say “done””The most important item. Every COMMAND declares which query proves it.
id: inventory.stock.receiveverification: operation: inventory.stock.get business_key: id expect: { field: resource.state, equals: open }⚠ Adding this item after the domain is built means reviewing every contract. Written upfront it is three lines per command.
4. Permissions — what I may not do
Section titled “4. Permissions — what I may not do”permissions: required: [inventory.stock.receive]Cannot be empty. Permissions are enforced on the server, not in the UI — otherwise the agent walks around the rule.
5. summary_for_ai — so it can plan
Section titled “5. summary_for_ai — so it can plan”summary_for_ai: > Records a stock receipt. FIRST use `inventory.item.search` to confirm the item card exists. An `ITEM_NOT_FOUND` error means the item is not in the catalogue — create it first.Three things: what it does · what to call first · what the main error means.
⚠ This is not a prompt — it is API documentation for the agent. Without it the agent calls operations in the wrong order.
6. Canonical resource and state
Section titled “6. Canonical resource and state”Every resource your domain returns is mapped to the canonical shape:
{ "resource": { "id": "mov_01hq...", "type": "stock_movement", "state": "open", "source_state": "AWAITING_CHECK", "updated_at": "...", "version": "3" }, "attributes": { "warehouse_code": "WH-1", "qty": "12" }}Canonical state |
Meaning |
|---|---|
open |
exists and active |
closed |
completed |
cancelled |
cancelled |
pending |
being processed |
failed |
failed |
unknown |
⚠ could not be mapped |
⚠ Hard rule: a Domain Pack may only depend on resource.*.
attributes.* is specific to your domain and agent semantics never bind
to it.
7. Typed errors
Section titled “7. Typed errors”errors: - ITEM_NOT_FOUND - STOCK_INSUFFICIENT - PERIOD_CLOSED - VALIDATION_FAILED⛔ A free-text error is one the agent cannot understand, so it cannot choose the next step. Every error must be a code and must be declared in the contract.
⚠ An error a handler returns but the contract does not declare fails CI.
8. A _label beside every ID
Section titled “8. A _label beside every ID”{ "warehouse_id": "wh_01hq...", "warehouse_label": "Central warehouse", "item_id": "itm_01hq...", "item_label": "Canon EOS R6 (body)", "actor_id": "actor_01hq...", "actor_label": "Aziz Karimov"}| Missing | Consequence |
|---|---|
No _label |
The agent invents the ID on the next call |
| No ID | The agent gives the user an unusable answer |
Both are required.
Checking
Section titled “Checking”davirix app checkIt names the missing item precisely and assigns a level: A0–A4.
- Readiness levels
- The verification block — in depth