Add a tool
tools.py
local_toolturns a typed Python function into a tool. The docstring tells the model what it does, andFieldlimits go into its schema.- A bad argument goes back to the model with what to fix. Your function gets real Python types.
- The return annotation,
Booking, is the output. A result that does not fit fails the call, and the model reads which field is wrong.
Use it in your agent
The same registry works in a full agent and in a plain one.- Build the tools once per call. They read that call’s state.
callis the call’sCallHooks. It runs your tool hooks and lets background webhooks finish when the call ends.- Set
language=andtimezone=onAgentSpec, or onfunction_toolsandtools_schema, so spoken dates follow the call.
Say a line while it works
- The agent says one line as the tool starts, never the same one twice in a row. A refused call says nothing.
{{day}}reads an argument or a State value.{{call.session_id}}reads what the call carries.announce_wait=Trueruns the tool only after the line has played, for a line like “Putting you through now.”
Keep a tool running when the caller talks
- Pipecat cancels a running tool when the caller speaks.
continuelets it finish, as LiveKit always does. - Use it for a tool that changes something, like a booking or a payment. A lookup can keep the default.
- A plain Pipecat pipeline also needs
attach_call(..., llm=llm), so the prompt stays the same as on LiveKit.
Tell the model a tool failed
ToolErrorcomes fromunmute_core.tools. The model reads your words and acts on them.- Any other error tells the model the tool failed and not to claim success. The log keeps the details.
- A call that reads a value not set yet does not run. The model gets a hint instead. See A call that is refused.
Save a result and speak it
assignsaves the result into State values.path=()saves the whole result, andpath=("order_id",)one field.repliesare tried in order. Code speaks the first one that matches and fills, and the model is asked for no reply.- A date reads “tomorrow, October 16” in the call’s language. A task step lists the same rows on its
TaskSpec. See Confirm in code.
Locked arguments
- The model never sees a locked argument. A value it sends is replaced.
{{customer.id}}reads the call state, and{{call.session_id}}what the call carries. The tool is refused, with a hint, while a value is unset.Transcript()sends the call’s transcript so far. See Send the transcript.
Call a webhook
inputis the model of what the model sends, andoutputthe model of the answer. Withwait_for_response=False, the output isAccepted, and the request runs in the background.- The token is read from
CRM_KEYat each call. One 10 second deadline covers the whole request, and each body is capped at 64 KiB. - Each address must be public. Set
allow_private_network=Trueonly for your own service, or forlocalhostwhile you develop.
End the call
- The call ends once the tool succeeds. The model is not asked for another reply, so the goodbye goes in the reply that calls the tool.
- A failed tool never ends the call.
- On Pipecat,
end_call_toolends the call with no second model request. See End the call.
Add the date or the caller number
current_datetime_tooltakes an IANA zone and returns the local date, time and day of the week.user_phone_number_toolreads the number fromstate.call. On a call with no number, it returns"available": false.
Watch tool calls
- The sink hears each stage, like
tool.started,tool.failedortool.refused, with names and timing only. It never gets argument values. - In a call, use the call’s hooks instead. See Hooks.
Where to go next
Tools reference
Every option, webhook argument, rule and edge case.
Knowledge
Search a folder of documents from a tool.
Hooks
Run your code around each tool call.
Unmute tools
How
agent.yaml declares the same tools.