Context and handoff¶
When the workflow moves to a new node, that subagent is working from its own instructions and its own pages — not from a replay of the call so far. Everything it needs to avoid re-asking, re-explaining or contradicting what came before has to be carried forward explicitly. That payload is the handoff state, and it is the one piece of the design that has to be got right — the rest degrades gracefully, this fails loudly and in front of the client.
The context budget¶
Why the workflow is split at all. A rough accounting of what a single undivided agent would carry:
| Approximate size | |
|---|---|
| Eleven section pages | ~55 KB |
| The full reference directory | ~25 KB |
| A ninety-minute transcript, by the end | large and growing |
| The section currently being asked | ~5 KB |
The last row is the point. Undivided, the thing the agent is actually doing occupies a few per cent of its attention, and the proportion gets worse with every turn as the transcript grows.
A section subagent carries its own page, three or four short reference pages, and a handoff state measured in kilobytes. What it is doing dominates what it is holding.
Budget per node, not per call
Splitting does not reduce the work the call does in total — it changes what is competing for attention at any one moment, and only that second number affects whether the client gets asked the right question.
Nothing is shared from the agent down: every node lists its own pages and inherits none. Shared pages are repeated rather than pooled, which costs a little duplication in the config and buys the guarantee that a subagent cannot see a section it does not own.
What travels¶
The handoff state, carried as dynamic variables as the workflow moves from node
to node. The four seeded at call time — client_name, practice, coach,
form_version — are declared on the agent under
dynamic_variable_placeholders; the rest accumulate as the call runs.
| Key | Carries | Why the next subagent needs it |
|---|---|---|
client_name |
What the client asked to be called | So subagent five doesn't reintroduce itself to someone forty minutes in |
form_version |
The questionnaire version being asked | Goes in the handover; answers are meaningless without it |
sections_done |
Which sections completed | Answering "how much is left?" honestly |
answers |
Every field ID with its value and status | The whole record so far |
volunteered |
Field IDs answered out of turn, with values | So the owning subagent skips them and says it already has them |
declines |
Field IDs the client declined | Never ask these again. See below |
flags |
Red flags found, with triggering fields | The handover assembles the triage proposal from these |
stopped_at |
Set only if a stop condition fired | Tells stop-and-refer what it is dealing with |
notes |
Free text a coach should read | Things that fit no field |
Every entry in answers carries one of the four statuses from
the handover record:
answered, declined, skipped — not triggered, skipped — section omitted.
A decline that arrives as a blank gets asked again
This is the failure mode the handoff exists to prevent, and it is the worst one available — the client declined something personal, was promised it would not come up again, and a later subagent asks it twenty minutes on because the decline reached it as an empty field.
declined is a value, not an absence. Every subagent treats it as final,
and optional and sensitive
questions is loaded by all four
sections where it matters most.
The rules of a handoff¶
- Pass state before speaking. The next subagent announces its section; it cannot do that correctly without knowing what has already been answered.
- Never pass a summary in place of fields. "Client seems generally healthy" is not a handoff. Field IDs and values are.
- Never drop a key you did not use. A section subagent that has no red
flags still passes
flagsthrough untouched. State accumulates; it does not get rewritten by each hop. - Volunteered answers move up, not down. If section 2 catches an answer
belonging to section 8, it goes in
volunteeredand section 8 skips it. It does not get re-asked "properly" in context. - The client's own words survive. Where phrasing carries information the option label loses, both travel. "I can't get down on the floor since the surgery" is worth more than a boolean.
What deliberately does not travel¶
- The transcript. Subagents get structured state, not a conversation log. Passing the transcript would reintroduce exactly the context growth the split removed.
- The previous subagent's reasoning. Why section 3 thought something was worth flagging is not section 4's business; the flag itself is.
- Reference pages. Each node carries its own, per the load map. Nothing forwards documentation to the next node.
When a call drops¶
The state is the record. A call that ends at section 7 has produced a valid, partial intake — and because state is passed at every hop rather than held in one context, nothing is lost that had already been handed on.
The handover subagent runs against whatever state exists, marks the remaining
sections skipped — section omitted, and notes where the call ended. A
callback resumes from sections_done rather than from the top; the client is
not asked sections 1 to 6 a second time.