Template
Agent design canvas
A working record of your agentic system: its purpose, evidence, permissions, uncertainty routes and run records.
Use the six prompts to expose the decisions that still need an answer, then compare your canvas with the worked example.
Use it when you are about to build something that acts, or somebody has handed you a design and asked whether it is sound.
By Sunil Mathew.
The blank
Copy the headings into your working document and answer each prompt. Keep unanswered decisions visible for the review.
System: ⟨name⟩
Owner: ⟨name⟩
Date: ⟨date⟩
Status: ⟨design status⟩
Does this need an agent at all?
Which part of this work genuinely depends on what the system finds at run time? Write that part here, and write the part whose steps you already know underneath it.
Choosing an agent gives the system scope to select its next step at run time. The closed part is a function, and calling it from a model does not make it one.
What it is for, and where it stops
The purpose as a task and a boundary, in one sentence somebody else can check. Then the non-goals, as part of the design rather than as a disclaimer.
A goal is only worth writing if it is testable. "Safer" is not a goal. "No order is refunded twice" is a goal, because you can go and look.
What must be true before it acts
For each action, the facts that must be established first and where each one comes from. Name the reference, not the recollection.
"The policy says returns are accepted within the window" is a paraphrase sitting in a context window. A clause identifier and a version can be checked afterwards, and can be checked by the tool at the moment of the call.
What each tool may do
One row per tool: its one job, the narrowest scope that does that job, the limit it enforces itself, and the identity it acts under.
Enforce authority at the tool boundary. An instruction not to exceed a limit is guidance; a tool that refuses to exceed it is a control.
What it does when it is uncertain
Define three outcomes: act, refuse and hand over with the specific gap named. Which situations route to which, and who receives a hand-over?
An unresolved case needs an output that identifies the gap and routes it to someone who can settle it.
What you can see afterwards
List the contents of a run record: the task, evidence references, tool calls and results, choices and outcome.
Record the evidence and actions alongside the conversation transcript.
The Markdown file is the blank with every prompt as a quoted block you delete as you answer it.
A completed example
Illustrative scenario, not a claimed customer incident. This example follows the returns assistant from recommendation to refund authority. Fields in ⟨angle brackets⟩ are for your own design and measurements.
A returns assistant that can issue a refund
A returns assistant reads a customer's message, finds the relevant policy, looks up the order and recommends a refund. Then someone asks whether it can issue the refund as well. On a diagram that is one more connection; in the world, the system can now move money. The canvas below is that system, after the refund tool has been connected.
System: Returns assistant
Owner: ⟨the engineer who owns this design⟩
Date: ⟨date⟩
Status: In design, not yet reviewed
Does this need an agent at all?
Open. Reading an unstructured message, working out which of several policies applies, noticing that a shipment was partial, deciding whether the request is even about a return. The next step depends on what the previous one found.
Closed. Given an identified order, a policy version and an amount, issuing the refund is a fixed sequence. That is a function. It is called by the agent; it is not part of the agent's reasoning.
What it is for, and where it stops
Purpose. Reads a customer's return request, identifies the order, applies the published returns policy, and recommends or issues a refund within the window that policy defines.
Non-goals. It does not amend an order. It does not cancel a subscription. It does not contact a bank. It does not act on an order it could not identify. A request outside the published policy goes to a person, even where an exception may be justified.
What must be true before it acts
Before
issue_refundmay be called, all five must be established:- the order, identified by id, not by description
- the state of that order, read at the time of the decision
- the policy clause that permits the refund, with the version it came from
- the amount that clause allows
- the absence of a prior refund against the same order
Each is carried as a reference. The clause is
returns-policy@⟨version⟩ §⟨clause⟩, not a summary of it.What each tool may do
Tool Job Enforces itself Acts as find_orderRead one order by id Read-only; no cross-customer lookup Service identity with read scope read_policyReturn a clause by id and version Read-only; refuses an unversioned request Service identity with read scope issue_refundMove money against one order Re-reads the cited clause and order; checks the permitted amount and prior refunds Its own identity with write scope; every call recorded The refund tool does not trust the arguments it was called with. It re-checks the evidence it was handed, because the caller is a model and the caller's reasoning is not a control.
What it does when it is uncertain
- The policy does not cover this case. Hand over, naming the case and the clauses considered. Never a best guess dressed as a decision.
- The order state is ambiguous, such as a partial shipment or a return in transit. Hand over with the ambiguity stated.
- Two policy versions disagree. Refuse and raise; this is a content problem, not a customer problem.
- The refund tool times out and the outcome is unknown. Do not retry. Read the state of the action first, then decide. ⟨name the person or queue that receives each hand-over, an unrouted hand-over is a refusal with extra steps⟩
What you can see afterwards
Per run: the customer's request; the order id; every policy clause read, with version; every tool call with arguments, result and duration; the point at which it chose to act rather than hand over, and on what basis; the outcome, including a refusal or a hand-over.
Kept because a dispute about a refund is settled by evidence, and "the system decided to" is not evidence. ⟨set a retention period here, and check it against your own data policy⟩
The worked example as a Markdown file, with its illustrative label.
How to use it
Answer the six prompts in order and keep unanswered questions visible. They identify decisions that need an owner before delivery pressure or an incident forces the choice.
The order matters more than it looks. The decisions get cheaper to change as you go down the list: swapping a model is a swap, while rewriting a purpose boundary means revisiting everything built on top of it. Choose the model after defining the purpose, evidence and controls; that is why this canvas has no model-selection box.
Allow about fifteen minutes for a first pass, then revisit any unanswered decisions. Take it into a design review as the pre-read; it is the document the design review agenda expects to have been circulated beforehand.
What it will not do
Answering the six questions makes the proposed boundaries and records available for review. It does not establish that they work, and a completed canvas is not a readiness certificate. Three areas are deliberately absent: evaluating behaviour rather than answers, the reliability questions around retries and duplicate actions, and the full cost of running the thing.
If the content your system reads can be written by somebody who benefits from the action (a customer’s own message, a supplier’s document or a web page), then box three is harder than it sounds here, because some of the input is adversarial by construction. The design holds; the sourcing rules have to get stricter.
Take the canvas into a review
Circulate your completed canvas with the Design review agenda. Leave unanswered decisions visible so reviewers can work on them.
If you want to build the agent behind those decisions with live guidance, explore Build Reliable AI Agents.