Hold on, let me check
Consultant runs the slow agent inside a live call. You supply a factory; what it builds is yours.
DEFAULT_CONSULT_TIMEOUT_MS, which
is 45 seconds. ask takes an optional second argument that overrides it for one question, which is
how resume below runs the same consultant on a five minute budget instead.
Two behaviours are not obvious, and both exist because a caller is listening.
One at a time, and the second asker is told so. A model that can delegate can delegate twice before the first answer lands. Queueing the second means it waits out both timeouts and answers far too late, so it is refused immediately with a sentence the model can say out loud.
A timeout is admitted. The work cannot be cancelled: the promise runs to its end whatever this returns. The answer says it stopped rather than promising a follow-up nothing will send, and the timed-out agent is dropped so the next question builds a fresh one.
ask never throws. It always returns something speakable, because an exception in a tool result is an agent that goes quiet mid-sentence.I’ll send you the result
When the work will not finish while somebody waits, it becomes a promise, and a promise made on a call that is about to end has to outlive the process that made it.BackgroundTasks writes each task to disk before the work starts and removes it only once the result has actually been delivered.
resume returns how many tasks it actually delivered. Its third argument is the per-task timeout,
DEFAULT_TASK_TIMEOUT_MS or five minutes by default, which is far longer than a consultation’s
because nobody is on the line waiting for it. BackgroundTasks takes directory, ttlMs and
resumeLimit. The directory defaults to a tasks folder under STANDIN_STATE_DIR, or under
~/.standin/state when that is unset. Deliberately never a temp directory: a temp directory passes
every test and loses every parked promise on the next reboot, which is invisible until somebody is
waiting for an answer that no longer exists.
The two-phase claim is what makes a restart safe. A task waiting to run is a .json; a task being run is a .claimed. A process that dies mid-run leaves a claim behind, and the next startup takes it back once it is old enough to be sure nobody is still working on it. A delivery that fails puts the task back rather than dropping it.
The two tools
Both areToolSpec values, ready to register on CallTools. They are not built in, because an agent with no second agent behind it should not be told it has one.
true as the Consultant’s third argument and a timeout will point the caller at it. Leave it off and it will not, because promising a path that does not exist is worse than admitting the work stopped.
Next
Call tools
Where both tools are registered, beside the built-ins.
Meeting recap
The other job a
Consultant is normally handed.Reaching people
When the answer should ring somebody back rather than land in a chat.
Configuration
STANDIN_STATE_DIR and every other variable the SDK reads.