Teardown: the capability list from the launch deck
Five bullets that describe what the bot can do, two that describe what it cannot, and a green check. Three of the seven are now obligations, four of them are scenery, and the split was decided by which verbs happened to be in the checker's dictionary.
TL;DR A capability slide pasted into a system prompt becomes rules nobody wrote: a bare imperative with a catalog verb at its head is a hard obligation wherever it sits, so Track an order. is an instruction to track one, while The assistant cannot change a price. has no modal and binds nothing. The deck checks clean at B (85/100); rewritten as guarded rules it is A (100/100).
Cadnam Outdoors sells tents and walking gear to about sixty thousand customers a year. Their support bot went live in July, and the prompt it went live with opens with the slide from the launch deck: What I can do, five bullets, What I cannot do, three lines. It was the clearest artifact anyone on the project had produced, which is exactly why it was pasted. The deck was written to tell a steering group what the bot is. The prompt is read by something that takes every sentence in it as an instruction about what to do next.
§1The slide, pasted
Seventeen lines. This is the file, unedited, as it shipped.
# Role You are Wren, the support assistant for Cadnam Outdoors. # What I can do Track an order. Process a return. Update a delivery address. Issue a refund of up to 50 dollars. Answer a question about stock. # What I cannot do The assistant cannot change a price. The assistant cannot contact the warehouse team. Escalations go to a human. # Constraints - MUST keep every reply to at most 3 sentences.
$ typeglish check wren.tg wren.tg:13:1 info prompt/unintroduced-definite "the warehouse team" retrieves something this document never introduces - a model must guess which team is meant. wren.tg:14:1 info prompt/unregistered-doer A bare generic doer never enters the world model - instruction to the agent, or background about users? ✓ 1 file - 0 error, 0 warning, 2 info $ typeglish check wren.tg --strict ✓ 1 file - 0 error, 0 warning, 2 info $ typeglish score wren.tg wren.tg - B (85/100) proven errors: none tiers: base+z3 planes runtime 97 (what the model reads) · hygiene 50 (source only) facets enforceability 100 x.21 · hardness 100 x.12 · directness 87 x.08 consistency 100 x.17 · structure 100 x.12 · annotation 0 x.12 style 85 x.08 · security 100 x.08 lever annotation 0/100 (up to +12 overall) - 10 statements without a @@ note rules 4 of 4 rule-shaped lines read
--strict escalates nothing. The number to hold on to is 4 of 4 rule-shaped lines read: the file has one MUST in it, and the checker is counting four rules.§2Three of the five promises are rules now
A rule does not need a modal. A line whose head is a verb the checker knows, standing as a bare imperative, is an obligation wherever it sits, and that is deliberate: Escalate to a human. in a prompt means escalate to a human. The score card will name them.
$ typeglish score wren.tg --json | jq -r '.card.rules[] | "L\(.line) \(.text)"' L5 Track an order. L7 Update a delivery address. L9 Answer a question about stock. L17 MUST keep every reply to at most 3 sentences. $ typeglish score wren.tg --json | jq -c '.card.facets[]|select(.key=="hardness")|.measures' {"forceStatements":8,"meanHardness":1,"hardShare":1,"softStatements":0}
hardShare 1 means every force-bearing statement in the file is at the hard end of the deontic scale. Three of them are slide bullets. The prompt now obliges Wren to track an order, update a delivery address, and answer a question about stock, in every conversation, with no occasion attached.Two bullets did not make the list, and the reason has nothing to do with intent. Process a return and Issue a refund of up to 50 dollars are prose, because process and issue are not in the verb ontology the directive parser reads. Swap them for two verbs that are, change nothing else, and the split disappears:
# "Process a return." -> "Send a return label." # "Issue a refund of up to 50 dollars." -> "Give a refund of up to 50 dollars." $ typeglish score wren-verbs.tg --json | jq -r '.card.rules[] | "L\(.line) \(.text)"' L5 Track an order. L6 Send a return label. L7 Update a delivery address. L8 Give a refund of up to 50 dollars. L9 Answer a question about stock. L17 MUST keep every reply to at most 3 sentences. $ typeglish score wren-verbs.tg wren-verbs.tg - B (85/100) proven errors: none tiers: base+z3
A heading that says "what I can do" is a comment. The lines underneath it are instructions.
§3The limits are the part that does not bind
Turn the slide over. The assistant cannot change a price. is a statement about the agent in the third person with no modal in it: a description, not a requirement, and it appears in no rules table. Neither does the second line. The third, Escalations go to a human, is the one the checker speaks up about, and what it says is that nobody is doing the escalating.
So the file's promises bind and the file's limits do not. That is precisely backwards from what the deck meant, and it is the reverse of the failure most teams expect: they worry the model will not do what the prompt allows, when the live risk is a model doing the allowed things unprompted and ignoring the boundaries entirely. Write the two limits as prohibitions and they join the table:
# "The assistant cannot change a price." -> "- NEVER change a price." # "The assistant cannot contact the warehouse team." -> "- NEVER contact the warehouse team." $ typeglish score wren-never.tg --json | jq -r '.card.rules[] | "L\(.line) \(.text)"' L5 Track an order. L7 Update a delivery address. L9 Answer a question about stock. L12 NEVER change a price. L13 NEVER contact the warehouse team. L17 MUST keep every reply to at most 3 sentences.
NEVER can be compared with every other rule in the file, and a sentence beginning The assistant cannot cannot be compared with anything, because it is not a claim about what to do.There is a third defect, and it only shows up in the artifact. The slide's bullets were never bullets: they are prose lines, and prose reflows on build.
$ typeglish build wren.tg ✓ built .typeglish/dist/wren.txt ← wren.tg (44d0a0476baf, full) # Role You are Wren, the support assistant for Cadnam Outdoors. # What I can do Track an order. Process a return. Update a delivery address. Issue a refund of up to 50 dollars. Answer a question about stock. # What I cannot do The assistant cannot change a price. The assistant cannot contact the warehouse team. Escalations go to a human. # Constraints - MUST keep every reply to at most 3 sentences.
§4What ships
The rewrite is not a translation of the slide. It is the answer to a different question: not what can this agent do but on what occasion must it do what, and with which tool. Every capability gets a trigger and a tool pointer, every limit gets a modal, and the refund ceiling the deck buried in up to 50 dollars becomes a bound the prover can hold.
$IMPORT tool track_order, send_return_label, update_address # Role @@ role: one line names the agent and the brand, so every later "you" is Wren You are Wren, the support assistant for Cadnam Outdoors. # Constraints @@ order_status: an order status is a lookup, never a recollection - WHEN the customer asks where an order is THEN MUST call @[track_order]. @@ returns: the label carries the current returns address - WHEN the customer asks to return an item THEN MUST call @[send_return_label]. @@ address_change: the courier owns the address after dispatch - WHEN the customer asks to change a delivery address THEN MUST call @[update_address]. @@ refund_ceiling: the desk limit, and the reason the deck said up to 50 - NEVER approve a refund over 50 dollars. @@ escalation: name the destination, or the handover is a guess - WHEN the customer asks for a refund over 50 dollars THEN MUST escalate to a human agent. @@ stock: stock moves faster than this prompt does - NEVER state a stock level. @@ price: a price change belongs to the merchandising team - NEVER change a price. @@ brevity: three sentences keeps a chat reply scannable - MUST keep every reply to at most 3 sentences. $TEST over_the_desk_limit - input:: The tent poles snapped on the first night. I want 80 dollars back. - expect:: - escalates to a human agent - at most 3 sentences
$ typeglish score wren-fixed.tg wren-fixed.tg - A (100/100) proven errors: none tiers: base+z3 planes runtime 99 (what the model reads) · hygiene 100 (source only) facets enforceability 100 x.21 · hardness 100 x.12 · directness 95 x.08 consistency 100 x.17 · structure 100 x.12 (hygiene) annotation 100 x.12 (hygiene) · style 100 x.08 · security 100 x.08 rules 8 of 8 rule-shaped lines read · 3/8 covered by $TEST $ typeglish test wren-fixed.tg --dry ✓ wren-fixed.tg coverage: 3/8 rules exercised uncovered (no case shares the rule's wording): L9 call @[track_order]. L11 call @[send_return_label]. L13 call @[update_address]. L19 state a stock level. L21 change a price. · over_the_desk_limit - "The tent poles snapped on the first night. I want 80 dollars" (not run) ✓ at most 3 sentences $ typeglish build wren-fixed.tg ✓ built .typeglish/dist/wren-fixed.txt ← wren-fixed.tg (51af5850aa36, full) # Constraints - WHEN the customer asks where an order is THEN MUST call track_order. - WHEN the customer asks to return an item THEN MUST call send_return_label. - WHEN the customer asks to change a delivery address THEN MUST call update_address. - NEVER approve a refund over 50 dollars. - WHEN the customer asks for a refund over 50 dollars THEN MUST escalate to a human agent. - NEVER state a stock level. - NEVER change a price. - MUST keep every reply to at most 3 sentences.
B (85/100) to A (100/100), and almost none of the gain is the part that mattered. Twelve points are the @@ notes, which are hygiene and never reach the model. The part that mattered does not show in the grade at all, because the deck's version was already scoring enforceability 100 on rules nobody meant to write. The honest measure of the rewrite is the last figure: eight lines in the artifact, every one of them a thing to do and the occasion to do it on.coverage: 3/8 is the real to-do list. Five rules have no case, and four of those five are tool calls, which is the kind of behaviour a suite should pin before a launch rather than after one. The deck, to be fair to the deck, told you which five things to write cases for.
§5Common questions
- Can I paste our agent's capability list into the system prompt?
- You can, but it stops being a description the moment it lands. A bare imperative headed by a verb the checker knows is a rule wherever it sits, so
Track an order.under a heading that says What I can do is an obligation to track an order, scored as hard as anyMUSTin the file. The deck in this post checks clean and scoresB (85/100)with every promise read as a standing instruction. Write the list as guarded rules instead:WHEN the customer asks where an order is THEN MUST call the tool. - Why does my agent try to do something the customer never asked for?
- Look for rules with no trigger. A rule is a standing obligation unless a
WHEN,IForUNLESSscopes it to an occasion, and a capability list pasted from a deck is a column of untriggered obligations. The fix is one clause per line: put the occasion in front withWHENand the action afterTHEN, so the rule only applies to the turns it was written for. - Does writing what the agent cannot do actually stop it?
- Only if you write it as a prohibition.
The assistant cannot change a price.is a third-person description with no modal in it: it describes, it does not require, and it does not appear in the rules table at all. Rewritten asNEVER change a price.the same limit becomes a hard rule the checker reads and the prover can compare with everything else in the file. - How do I turn a capability list into rules a checker can read?
- Three passes. Give every capability a trigger and a tool, so
WHEN the customer asks to return an item THEN MUST call the return-label toolreplacesProcess a return.Turn every cannot line into aNEVERwith one verb and one object. Then annotate each rule with a@@note saying why it exists, which is the cheapest facet in the grade. The rewritten prompt in this post scoresA (100/100)with every rule-shaped line read.
The deck is not the villain here, and neither is the person who pasted it. A capability list is the correct artifact for the conversation it was made for, which is a steering group deciding scope, and its whole job is to be readable without conditions, tools or bounds. What goes wrong is the handoff: the slide arrives already looking like a specification, in a format that fits a prompt, at the exact moment somebody needs a prompt. The tell is grammatical and you can grep for it. Scan your prompt for lines that describe the agent in the third person, the assistant, the bot, this agent, and for lines with no modal and no WHEN. The first set is your boundaries, currently doing nothing; the second is your feature list, currently running the conversation. Your agent has no team lead to ask is the same handoff going wrong with a different document.