agent-protocol ยท diff

git:20260821.91f709d to git:20260827.c3abe5f

13 added, 58 removed. Audit A to A.

---
name: agent-protocol
description: Use when producing any agent response
---
# Agent Protocol
- Every agent turn writes one contract -- what it was asked, what it found, what it changed, how it ended
- -- during the turn, not composed at the close. The eleven principles run that arc, ground to close.
+ Every agent turn writes one contract -- what it was asked, what it found, what it changed, how it ended -- during the turn, not composed at the close. The eleven principles run that arc, ground to close.
## 1. Your contract is the delivery; your final message is only the signal that the turn ended
- The gate validates only your persisted contract: one found unfinalized -- or no row at all -- rejects the
- close however complete your message reads (`_resolve_subagent_stop_gate_full`). The message carries no copy.
+ The gate validates only your persisted contract: one found unfinalized -- or no row at all -- rejects the close however complete your message reads (`_resolve_subagent_stop_gate_full`). The message carries no copy.
## 2. You were born with a contract -- adopt it, do not create another
- `# Your Contract` names it on a fresh dispatch, a `# Contract Draft (resumed)` block on a resumed one;
- your first `gaia contract set/add/fill --draft-id <contract_id>` adopts that draft, and every later
- call carries `--draft-id` too -- omitted, the CLI targets the most recently touched draft, which is
- not necessarily yours. Copy `agent_id` verbatim into `agent_status.agent_id`. `AGENT_ID_FORMAT` checks
- the identifier's shape, never its ownership, so a stray `gaia contract init` mints a rival identity
- the gate accepts while your real contract is reaped unfinalized; a bare `init` fits exactly one turn,
- the one that arrived with no contract block at all.
+ `# Your Contract` names it on a fresh dispatch, a `# Contract Draft (resumed)` block on a resumed one; your first `gaia contract set/add/fill --draft-id <contract_id>` adopts that draft, and every later call carries `--draft-id` too -- omitted, the CLI targets the most recently touched draft, which is not necessarily yours. Copy `agent_id` verbatim into `agent_status.agent_id`. `AGENT_ID_FORMAT` checks the identifier's shape, never its ownership, so a stray `gaia contract init` mints a rival identity the gate accepts while your real contract is reaped unfinalized; a bare `init` fits exactly one turn, the one that arrived with no contract block at all.
## 3. Ground yourself before acting
- Ask what already governs this, in precedence: injected context -> memory, queryable past the sample
- you were sent -> the code, which outranks any description of it -> the skills -> outside. A skill the
- code refutes is outranked by it AND is itself a finding: name the skill and the contradicting symbol
- in `open_gaps`, or the drift outlives your turn to be rediscovered by the next agent that trusts it.
- A goal often
- carries a COORDINATE -- a contract id, a memory slug, a brief name -- and `read-map.md`, beside this
- file, is the verb that opens it. Announce no tool sequence and claim no reach in advance.
+ Ask what already governs this, in precedence: injected context -> memory, queryable past the sample you were sent -> the code, which outranks any description of it -> the skills -> outside. A skill the code refutes is outranked by it AND is itself a finding: name the skill and the contradicting symbol in `open_gaps`, or the drift outlives your turn to be rediscovered by the next agent that trusts it. A goal often carries a COORDINATE -- a contract id, a memory slug, a brief name -- and `read-map.md`, beside this file, is the verb that opens it. Announce no tool sequence and claim no reach in advance.
## 4. Local and reversible work just happens; what goes out into the world is asked once
- Commits, files and branches need no signature; pushes, PRs, applies and every other exit into the
- world go into one ordered COMMAND_SET under a single signature, written out exactly in advance --
- `security-tiers` owns what may be grouped. A failed COMMAND_SET is terminal/frozen, remainder and all.
+ Commits, files and branches need no signature; pushes, PRs, applies and every other exit into the world go into one ordered COMMAND_SET under a single signature, written out exactly in advance -- `security-tiers` owns what may be grouped. A failed COMMAND_SET is terminal/frozen, remainder and all.
## 5. The record is written in flight, at the cadence of what would hurt to lose
- If the turn is cut, only what you already wrote exists; everything else survives in the transcript as
- narrative and dies as evidence. Write a finding the instant re-deriving it would cost more than
- recording it, and be resumable before any step whose outcome you cannot predict -- a record composed
- at the close is a second telling, made under the pressure that ends the turn, and it drops fields.
- Seven lists carry it: `fill` each ONCE (it refuses to discard), `add` extends, `set` replaces, as the
- evidence arrives, never in one pass at the close: `files_checked`, `patterns_checked`, `commands_run`,
- `key_outputs`, `verbatim_outputs`, `open_gaps`, and `cross_layer_impacts` -- what your change reached
- outside the file you were sent to, which no other field records for you. `patterns_checked` is written
- the moment you SEARCH, not at the close, and above all when the search returns NOTHING: the file you
- opened comes back in `files_checked` and the command you ran comes back in `commands_run`, but a `grep`
- that matched zero lines is held by no other field -- unwritten as it happens, the negative it proves is gone.
+ If the turn is cut, only what you already wrote exists; everything else survives in the transcript as narrative and dies as evidence. Write a finding the instant re-deriving it would cost more than recording it, and be resumable before any step whose outcome you cannot predict -- a record composed at the close is a second telling, made under the pressure that ends the turn, and it drops fields. Seven lists carry it: `fill` each ONCE (it refuses to discard), `add` extends, `set` replaces, as the evidence arrives, never in one pass at the close: `files_checked`, `patterns_checked`, `commands_run`, `key_outputs`, `verbatim_outputs`, `open_gaps`, and `cross_layer_impacts` -- what your change reached outside the file you were sent to, which no other field records for you. `patterns_checked` is written the moment you SEARCH, not at the close, and above all when the search returns NOTHING: the file you opened comes back in `files_checked` and the command you ran comes back in `commands_run`, but a `grep` that matched zero lines is held by no other field -- unwritten as it happens, the negative it proves is gone.
- `report_prose` sits beside these seven lists, never inside them: the why, the discovery order
- when it explains the result, the purpose frame, the synthesis judgment -- for the orchestrator
- and the next agent reading the row, never the end user. No evidence here, and no re-narrating a list.
+ `report_prose` sits beside these seven lists, never inside them: the why, the discovery order when it explains the result, the purpose frame, the synthesis judgment -- for the orchestrator and the next agent reading the row, never the end user. No evidence here, and no re-narrating a list.
## 6. The phase is declared before doing that phase's work
- Write `framing`, `investigating`, `planning`, `executing` or `verifying` before that phase's work, not
- after: reading as "investigating, four files in" rather than as an opaque box decides whether the
- orchestrator waits or dispatches over the top of you. Write only the phases you entered.
+ Write `framing`, `investigating`, `planning`, `executing` or `verifying` before that phase's work, not after: reading as "investigating, four files in" rather than as an opaque box decides whether the orchestrator waits or dispatches over the top of you. Write only the phases you entered.
## 7. Every increment closes verified, and fixing starts by going back to the sources
- Close each piece verified before starting the next, by result and never by exit code -- failures
- compound, and separating two entangled ones costs more than verifying the first. On failure, search
- before retrying: a rejected contract is a problem of form, reissued complete without re-investigating;
- a rejected operation is a problem of knowledge, and varying the attempt only stacks another state.
+ Close each piece verified before starting the next, by result and never by exit code -- failures compound, and separating two entangled ones costs more than verifying the first. On failure, search before retrying: a rejected contract is a problem of form, reissued complete without re-investigating; a rejected operation is a problem of knowledge, and varying the attempt only stacks another state.
## 8. Before declaring yourself blocked, ask
- Three doors come first: the answer is in the goal you received, in context or memory you can query,
- or it is a material choice only the user can make -- then close `NEEDS_INPUT` naming the concrete
- options. `BLOCKED` is the fourth and costliest: an answered question comes back with your draft
- unreset, while a block is routed to whoever owns the obstacle, with none of what you found.
+ Three doors come first: the answer is in the goal you received, in context or memory you can query, or it is a material choice only the user can make -- then close `NEEDS_INPUT` naming the concrete options. `BLOCKED` is the fourth and costliest: an answered question comes back with your draft unreset, while a block is routed to whoever owns the obstacle, with none of what you found.
## 9. The producer does not verify its own production
- Evidence is the command's output, not your assertion about it: a `COMPLETE` needs a `pass` in
- `evidence_report.verification.result` (`VERIFICATION_RESULT`), which cannot tell a fabricated one from
- a real one. A plan-task-bound turn cannot seal itself (`_blind_verification_required`); it closes
- `NEEDS_VERIFICATION` for an independent verifier.
+ Evidence is the command's output, not your assertion about it: a `COMPLETE` needs a `pass` in `evidence_report.verification.result` (`VERIFICATION_RESULT`), which cannot tell a fabricated one from a real one. A plan-task-bound turn cannot seal itself (`_blind_verification_required`); it closes `NEEDS_VERIFICATION` for an independent verifier.
## 10. Every turn closes by declaring a state
- `IN_PROGRESS`, `BLOCKED`, `NEEDS_INPUT`, `APPROVAL_REQUEST`, `NEEDS_VERIFICATION`, `COMPLETE`; only
- `COMPLETE` is terminal, anything outside the six is rejected (`PLAN_STATUS`). Set `agent_status.agent_state`
- to the closing value, then `gaia contract finalize --draft-id <contract_id>` last: it is the only
- promotion of that row to a clean close, and it refuses `IN_PROGRESS` (`cmd_finalize`). Add
- `--plan-task-id <id>` when the turn executes a plan task, and never pass `--session-id` unless the
- dispatch handed one over -- the born row already carries it, and an invented `unknown` corrupts it.
+ `IN_PROGRESS`, `BLOCKED`, `NEEDS_INPUT`, `APPROVAL_REQUEST`, `NEEDS_VERIFICATION`, `COMPLETE`; only `COMPLETE` is terminal, anything outside the six is rejected (`PLAN_STATUS`). Set `agent_status.agent_state` to the closing value, then `gaia contract finalize --draft-id <contract_id>` last: it is the only promotion of that row to a clean close, and it refuses `IN_PROGRESS` (`cmd_finalize`). Add `--plan-task-id <id>` when the turn executes a plan task, and never pass `--session-id` unless the dispatch handed one over -- the born row already carries it, and an invented `unknown` corrupts it.
## 11. Degrading honestly costs less than faking
- What you could not do, what you did not verify and what stayed open go in the record: a gap declared
- gets routed, a gap hidden surfaces later. A complete-looking turn with one invented field is worth nothing.
+ What you could not do, what you did not verify and what stayed open go in the record: a gap declared gets routed, a gap hidden surfaces later. A complete-looking turn with one invented field is worth nothing.
## Where to go next
- `reference.md` -- the argument behind each principle, the state machines, storage and recovery, what the gate rejects; `agent-contract-handoff` -- envelope schema; `examples.md` -- filled envelopes; `read-map.md` -- read verbs. Then `investigation` -> `security-tiers` -> `command-execution` for one operation or `subagent-request-approval` -> `execution` for a COMMAND_SET; orchestrator-side: `orchestrator-present-approval`, `pending-approvals`, `agent-response`.