Quickstart
agent.py
choose_service tool. When the model calls it, a step
runs on its own prompt. The step saves requested_service and hands the call
back. A value outside the three services is refused, and the model asks again.
Why use unmute for this
A task is data. You describe the step, and the library checks it at startup, runs it the same way on both frameworks and saves the values it collects. A broken flow fails the deploy, not the call.Name a task
A task or group name is lower snake case. It becomes the prompt sitetask:<name>. A prompt site is the place in the agent where a prompt is used: the
main prompt, or the prompt of one task step. Three names are taken:
finishandgo_back_to_step, the step’s own tools.summary, because a handoff summary uses the prompt sitetask:summary.
end_call, is refused when the agent is built. This is the same
on LiveKit and Pipecat.
Define a task
Every spec class is immutable and refuses keys it does not know. They are Pydantic models, so you can build them as literals or from JSON withmodel_validate. Import them from unmute_core.tasks. A step that checks the caller’s phone number looks like this:
agent.py
TaskSpec are:
name: lower snake case.instructions: the step’s prompt.when: when the main agent starts it.tools: the tools the step may call.assign: the values it saves.
Instructions
A step’sinstructions may hold {{name}} placeholders and plain text, including JSON.
- A lone
}}is plain text.{"a": {"b": 1}}passes. - A
{{...}}that is not a valid placeholder is refused, and so is a{{that never closes. - Blank instructions are refused.
- Spoken lines, announce lines, locked arguments and the greeting keep a stricter rule: they take only placeholders.
Assign
One value a step saves. AnAssign has a variable and a path. The path says where the value sits in the step’s result, like ("order", "id").
path, (), saves the whole result, into a State value typed as the
tool’s output model. The finish parameter is the field itself for a one-part path.
For a longer or an empty path it is the variable name. Two assignments may not share a finish parameter. append adds one entry onto a list instead of replacing it. This is Unmute’s +. optional lets the step finish without the value. This is Unmute’s ?. Otherwise a served finish must carry it, unless it appends.
Modes
TasksSpec.mode is status or record. Everything on these pages describes record mode. status mode keeps Unmute’s older behaviour: a run hands the main agent a status, and a hand-back saves nothing.
Run the tasks
TaskPlan
TaskPlan holds the tasks and groups of one agent, checked once and read by every call.
It checks the spec against the State and the tools. It raises
ValueError and names the first task, group or value that does not fit.
TaskPlan.check_then_targets(known) refuses a group that transfers to an agent
the adapter was not given. The adapters call it when they are built.
check_native_tools(names)refuses a task that lists a native tool the agent does not have. It raisesValueErrorand names the first task and the missing tool.check_handoff_tools(names, fix=)refuses a task whosehandoffsnames a tool the agent has no handoff for.fixis the end of the message. Say how to add the tool.- Both take
task=to check one task. Without it, they check every task. - The adapters call them when the agent is built. Call them yourself when you write your own host.
CallTasks
CallTasks holds the tasks of one call: the main agent’s task tools, and every run they start.
Both adapters build their own from the spec, once per call: read it as agent.tasks on LiveKit and flows.tasks on Pipecat. Build one yourself only when you write your own host.
CallTasks.empty(state, tools=...) gives the tasks of an agent
that has none. Use it in your own host when it needs a stack and you have no tasks.
TasksSpec.owners() returns each State value that a task saves, with the first
task that saves it. The save tool for values no task saves uses it. See
State.
Troubleshooting
ValueError names a task, group or value when the plan is built
TaskPlan checks every name a task reads against the State and the tools.
Fix: read the message. It names the first thing that does not fit, like a
{{name}} the State does not have, a tool the task does not list, or a group
that transfers to a target then_targets does not hold.
A task has no when, and nothing can start it
A task with no when must be a step of a group, or be entered by a via tool.
Fix: add a when, put the task in a group, or add a via tool.
A task name is refused
finish, go_back_to_step, the built-in tool names and summary are taken.
Fix: rename the task or group.
In the salon tutorial: Book step by step.
Every argument: Tasks reference.
Where to go next
Task groups
Run several tasks in order, and decide what follows.
Tasks reference
Every argument of every task class.
Tools
The tools a step lists in
tools.