The Response Protocol
What the agent emits, in what order, and what switches each part off — specified rather than left to taste.
Every response is assembled from a fixed ordered set of blocks, each with its own trigger and its own suppressor. Specifying the order removes a decision from every single response; specifying suppressors is what stops the agent from talking past a request for brevity.
Problem
An agent that decides the shape of each response from scratch produces inconsistent output: sometimes a summary, sometimes a wall, sometimes three suggestions nobody asked for.
Inconsistency is not merely untidy. It costs the reader a decode on every response — what am I looking at, is there a recommendation, where is the number — and that cost is paid hundreds of times.
The naive fix, a fixed template, fails in the other direction: a template emits its blocks regardless of whether they apply, which is how an agent ends up appending suggested next steps to a one-word factual answer.
Design
Responses are assembled from an ordered set of blocks, each with a trigger and a suppressor.
| Block | Fires when | Suppressed by |
|---|---|---|
| Header | first response of a session | never |
| Greeting | new session | not a new session |
| Answer | always | never |
| Risk flag | irreversible or material downside | nothing |
| Sources | a framework changed the method | it did not |
| Next steps | business task or decision | brevity request, factual question |
| Single next action | audit, debug, planning | brevity request |
| Idea | high-value observation, capped per session | brevity request, below threshold |
The set holds 8 blocks. Three properties do the work.
Order is fixed. The reader learns where things are once. A recommendation is always in the same place, so it can be found without reading everything above it.
Each block has an explicit trigger. Blocks do not fire by default; they fire on a condition. This is what stops a factual question from receiving a planning apparatus.
The suppression gate is written once, centrally:
brief mode: omit suggestions, framing, sources, extras. Exceptions: risk flag, safety lens, anything the operator asked to always receive.
Suppressors are specified, and one block has none. A request for brevity removes suggestions, framing, sources and extras. It does not remove a risk flag — because the moments someone asks for speed are, empirically, the moments a warning matters most.
Never both recommendation blocks. Multiple next steps and a single next action are alternatives, and emitting both is a reliable sign the protocol was not applied.
Trade-offs
Specification is rigid where taste would be better. Some responses would read more naturally in a different order. The protocol trades a small amount of per-response elegance for predictability across hundreds, which is the right trade for a tool used daily and the wrong one for a piece of writing.
Triggers are judgement calls wearing a rule's clothes. Business task and material downside are not crisply defined. In practice the boundary cases are rare and the cost of a wrong call is one unnecessary block, which is acceptable.
The suppressor list is the part that rots. Every new block arrives with an obvious trigger and a vague suppressor, and a year later half the blocks fire more often than intended.
One word means three things. Briefly means emit less in this protocol, do not block me with a plan in the planning gate, and do not escalate reasoning in the effort policy. Keeping them separate costs a paragraph of specification and prevents the wrong one from winning.
How a block is specified
Adding a block to the protocol is the operation that most often goes wrong, so it has its own shape. Each block is defined by 5 fields, and a block missing any of them will misbehave within a month.
name · fires when — a condition, not a vibe · suppressed by — explicit list, or the word nothing · position — fixed index in the order · cap — how often it may appear per response and per session
The cap field is the one that looks unnecessary and is not. A block with a good trigger and no cap will fire 3 times in one response when 3 things qualify, which is technically correct and reads as noise. The idea block carries a cap of 1 per response and 3 per session for exactly this reason.
The position field prevents a subtler failure. Blocks added later tend to be appended, so over time the most recently added block sits closest to the end — which is where the reader's attention is lowest, regardless of the block's importance. Assigning a position explicitly forces the question where does this belong rather than defaulting to last.
Two rules govern changes to the set as a whole.
A new block names what it replaces or narrows. The protocol grows monotonically otherwise, and a response assembled from 12 conditional blocks is a response nobody can predict.
The suppression gate is central, never per-block. This was learned the expensive way: the same suppressor written into 3 separate protocols drifted apart within weeks, and the version that governed the noisiest block was the one that never got updated. One gate, one exception list, referenced rather than copied.
What broke
Suggestions after a request for brevity. The suppressor existed in one protocol and not in the two others that also emitted blocks. Fixed by making suppression a global gate with a short published exception list, rather than a rule repeated per block — repetition is how the copies drift apart.
A safety flag suppressed along with the rest. The gate was applied uniformly, which removed exactly the block that should never be removed. Fixed by naming the exceptions explicitly rather than relying on judgement.
Both recommendation blocks in one response. Reliable symptom of the protocol not being applied at all, and useful as a self-check.
Why not let the model decide
The obvious objection: a capable model can judge what a response needs, and a fixed protocol prevents it from doing so.
That is true and it is the trade being made. Three reasons it is the right one here.
Consistency compounds across hundreds of interactions. A reader who has learned where the recommendation lives saves a decode every single time. A slightly better-shaped individual response does not compound at all.
Judgement is unstable under load. The shape of a response varies with context length, time pressure and how the request was phrased — none of which should change where a warning appears. A protocol removes that variance for free.
Suppression is the part that cannot be left to judgement. An agent deciding case by case whether the operator wants the extras will resolve ambiguity toward emitting them, because emitting is the helpful-feeling option. That is exactly how an explicit request for brevity gets talked past.
Where judgement genuinely belongs is inside a block, not in whether it appears. What the answer says, how the risk is characterised, which next action is recommended — all judgement. The frame around it is specification, and keeping those two separate is what lets the frame be boring.
Files
One protocol file holding the block table, the order, and the global suppression gate with its exceptions. Per-block detail lives in separate files loaded on trigger, so the always-loaded specification stays short.
The exception list is deliberately hard to extend. It is 3 items, and adding a fourth should feel like a decision rather than an edit.