Skip to main content
Some tools need no code from you because the platform already has them. You select one by id, and you can pin the settings it takes. Reach for a prebuilt when the capability already exists, so writing your own would just duplicate it. That is hanging up, reading the clock, sending a text message, and reading the caller’s number. For anything else, write a webhook, a Python handler, or point at an MCP server. On this page:
tools/end_call.yaml
That is the file unmute init scaffolds, so a new agent can hang up from its first run.

The block

string
required
Accepts end_call, send_sms, current_datetime or user_phone_number from the registry below. No id is inferred. end_call compiles on every target; the other three are SLNG only.
string
Instruction the runtime gives the model as the prebuilt runs. For end_call, use it for a final line or action before ending. Omit to add no custom instructions to the prebuilt.

The registry, in full

Four rows. The registry is closed: you cannot add to it from a package, and there is no plugin seam. Adding a prebuilt means a row in the compiler plus a lowering for each target, which is a change to Unmute, not to your agent. end_call compiles on every target. The other three are capabilities SLNG curates and compile on the slng target only for now. Livekit and pipecat refuse them by name. A capability’s settings are written with with:. On a builtin that block is the tool’s own configuration, not an argument, because a curated capability publishes no argument schema for one to go in. The model never sees a pinned value either way. send_sms takes one setting, the sender:
tools/send_sms.yaml
from_number is a literal number in international format starting with a plus sign, and it is the only key with: may carry here: SLNG requires the sender on the attachment and lets the model supply the recipient and the body. SLNG reads the Twilio credentials from your vault under TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN, so unmute deploy checks both. Pair it with a source: conversation variable so the number the caller confirmed is recorded on the call. current_datetime takes one setting, an IANA zone name:
tools/current_datetime.yaml
Write the zone whenever your agent is not in UTC. The curated tool defaults to UTC and belongs to no organisation, so it cannot be changed on the platform. An agent without the setting is told the wrong date for part of every day. A zone name survives daylight saving; an offset written into the prompt does not. user_phone_number takes no settings. The platform knows the number from the call leg. So read this page as a list of four things that exist, not as a catalog to browse. If what you want is none of them, it is a webhook, a Python handler, or an MCP server.

Settings

A prebuilt’s settings are written with with:, a list whose every item holds one key. On a prebuilt that block is the capability’s own configuration, not an argument the model could supply, because a curated capability publishes no argument schema. The model never sees a pinned value.
tools/current_datetime.yaml
A key the capability does not declare is refused, naming the ones it does:

current_datetime

string
An IANA zone name, such as America/Los_Angeles or Europe/Madrid. Omit it and the agent reads the clock in UTC.
Write the zone whenever your agent is not in UTC. The curated tool defaults to UTC and belongs to no organisation, so it cannot be changed on the platform. An agent without the setting is told the wrong date for part of every day. A zone name survives daylight saving; an offset written into the prompt does not. Keep the clock a tool rather than copying its answer into a variable. A variable is fixed when the session starts and the tool is not, so on a long call the model ends up with two answers and trusts the one already in its prompt.

send_sms

string
required
The sender, as a literal number in international format starting with a plus sign, such as +447700900123. A template reference is refused: SLNG requires a literal here.
It is the only key send_sms takes. The model supplies the recipient and the body itself, and SLNG reads the Twilio credentials from your vault under TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN, which unmute deploy checks. Pair it with a source: conversation variable so the number the caller confirmed is recorded on the call.

end_call and user_phone_number

Neither takes a setting. user_phone_number reads the number from the call leg. On slng, end_call always says a goodbye before it hangs up. Without start: say: it is SLNG’s default line, “Thanks for calling. Goodbye!”. Write start: say: to choose your own. A goodbye set by hand in the dashboard is removed by the next push, and unmute deploy --dry-run says so before it happens.

What the registry decides for you

The effect. end_call implies ends_conversation, and writing anything else fails rather than being quietly ignored:
The parameters. A prebuilt owns its own schema, so the contract fields have nowhere to go:
The description, unless you write one. Leave description out and the registry default is used. Write your own description when the agent needs a narrower instruction, for example telling it to confirm before hanging up. Yours is added on top of the default rather than replacing the tool’s behavior. Use builtin.instructions when the model must do something at execution time:
It does not change the tool’s id, parameters, or fixed ends_conversation effect.

Speaking before it runs

On the slng target a prebuilt is an attachment like any other, so it can speak a fixed line as it starts. The line goes on the tool’s entry in agent.yaml:
agent.yaml
list of strings
One fixed sentence the agent speaks as the tool starts. More than one is refused here: an attachment carries a single pre-action message. No {{variables}}.
On end_call the line is the goodbye. It replaces SLNG’s own goodbye, so the caller hears it once, then the call ends. Do not also tell the model to say goodbye before it calls end_call, or the caller hears two. Every other line runs alongside the tool, which is the point of it: a sentence so a slow call is not silence. A code target refuses start: say: on a prebuilt. It builds the capability from its own SDK and has no seam in front of it, and the refusal says so.

Turning it on

The agent names it, as with any other tool:
agent.yaml

Advanced

Resolving on SLNG

SLNG offers every one of these as a curated capability, so unmute deploy’s preflight check has to match your reference against it before pushing. It matches by the tool file’s name, tools/end_call.yaml, never by the builtin.id you selected inside it. So name the file after the id. unmute validate refuses the mismatch on the slng target and says which file to rename:
A code target lowers the builtin to a function and does not care what the file is called, which is why this is not a rule everywhere. A name can also be held twice. SLNG publishes end_call to everybody and your organisation can hold its own copy; unmute deploy attaches yours and names both in its output, so you can see which one is running.

Troubleshooting

An id the registry does not hold

An id the registry does not hold is refused by name. Every line below is prefixed with the target instance that refused it, so a fresh scaffold, which has one livekit instance, reads like this:
Fix: pick one of the two ids in the registry, or write the capability yourself as a webhook, a Python handler, or an MCP source.

The SLNG preflight says the organisation has no tool of that name

A file tools/hang_up.yaml holding builtin: {id: end_call} compiles and validates, but the organisation has no tool named hang_up. The preflight then reports it absent, even though the capability exists:
Fix: keep a builtin: file’s name matching its id.

Where to go next

Knowledge bases

Answer from a folder of your own documents.

Tools

Return to all eight execution blocks.