- One saved fact, end to end - declare, save, read
- Start with the next reader - who needs this value
- Separate a request from an outcome - asked for, not booked
- Group fields that describe one result - when to use a shape
- Match the type to the actual value - what your tools return
- Choose a current value or a list - latest record, or every one
- Finish as soon as the work succeeds - save, then finish at once
- Reuse verification deliberately - and what confirmed means
- Write for a missing value - write for the empty case
- Check the whole path - both prompts, then a trace
One saved fact, end to end
Every saved fact has the same three parts. Declare it, save it in the step that learns it, and read it in the prompt that needs it:agent.yaml
instructions.md
Start with the next reader
For each value, identify who saves it and who needs it later:
If nothing reads a value, you probably do not need it. If a later prompt needs
it, add the placeholder there. A description alone does not share the value.
Separate a request from an outcome
A caller asking for Friday does not mean Friday is booked. Keep the requested date separate from the successfully saved appointment. Update the saved appointment only after the booking tool reports success. This prevents a failed change from looking like a confirmed booking. It also gives later tasks a clear answer when the conversation mentions both the old and new times.Group fields that describe one result
Start with separate variables for independent facts, such as a caller’s name and preferred language. Use a shape when the fields describe the same record and should be saved together. For a booking flow:- Look at the successful booking tool result. Identify the fields later tasks need, such as its ID, service, date, and time.
- Declare an
Appointmentshape with those fields. UseIdonly if the actual booking ID fits its limits, andDateandTimefor the saved time. - Declare
appointmentwithtype: Appointment. Give it a description such as “The latest appointment successfully saved by the booking tool.” - Assign
appointment: result.appointmentin the booking task. Tell the task to copy the successful result and finish immediately. - Reference
{{appointment}}in the owner, or just{{appointment.date}}in a prompt that needs only the date.
Match the type to the actual value
Use a shape for fields that belong together. Include fields your tools return or the caller can supply. Do not require an ID that no tool produces. UseT | None when a successful result may legitimately have no value. A
required Id cannot be replaced by an empty string just to finish the task.
An external identifier may need str. For example, a booking slot containing
| does not fit Id. Preserve the exact value the tool returned. The
type reference lists the
format checks and their limits.
Choose a current value or a list
Use one shaped variable for the latest successful appointment. Replacing it makes the new date the current one. Use a list when later tasks need several records. Append with+:
list[str], or list[Note] for a shape.
An identical structured item is not added twice. A changed item is added
separately; append does not find and replace an earlier record with the same
ID. Plain values may repeat.
Finish as soon as the work succeeds
A task that performs an action and then waits for another caller turn can accidentally absorb a new request. For example, a booking task might complete a move, hear a complaint, and returnunserved instead of saving the move.
Write the task prompt to save the successful result and make the finish call
immediately. Let the owner read the saved value and confirm it once. For a task
designed to save one record, finish after that record; run it again for another
request.
Better still, when the task’s last action is a tool, name that tool under
finish:. The task then ends on the tool’s success result by itself, saves its
assign: from that result, and the model never has to decide that the work is
done. See
Say what success looks like.
A non-empty unserved_request saves no assignments and returns only a status.
It does not undo an action already completed by a tool.
Reuse verification deliberately
When verification is the first step of a task group, declare the skip rather than asking a prompt to remember it. Putskip_when_confirmed: on that step,
naming the variable the step confirms. The group then skips the step when
that variable is confirmed at the moment the group starts, and runs it
otherwise. See
Skip a step whose work is already done.
Confirmed here is a real mark on the variable, set by confirm: alone: when
the task it names saves the value, and cleared by any other write. A prompt
sentence saying the caller was verified is not that mark, and neither is a
separate status variable a task assigns on success. Do not also keep a
separate status variable for this: once the group reads the confirm mark
itself, nothing needs a second copy of the same fact.
Use confirm: for a
candidate value that must be checked with the caller. When that candidate
changes, prefetched values derived from the old candidate are cleared, and
the group runs the confirming step again on its own.
Write for a missing value
Prefer a label and a clear fallback:none recorded yet. An empty list renders as [].
Neither proves that your booking system has no records; it means the call
has not saved that information.
Check the whole path
Read the task prompt and the owner’s prompt together. Check who asks the question, who saves the answer, and who speaks after completion. Then inspect a trace to confirm that each receiving prompt contains the facts it needs.Where to go next
Reduce context sharing step by step
A practical walkthrough, one boundary at a time.
Making a task actually run
Task structure and tool placement, so the step gets entered.
Variables
The YAML for declaring a value, a shape, and a list.
Checking what the agent did
Reading a trace to see which saved value each prompt received.