What this covers. A talking agent that can only talk isn't worth much. The moment it can do things, book the appointment, look up the order, check what times are free, it becomes useful. It does those things by calling tools, which are just webhooks. This lesson explains the concept end to end and uses n8n as the example automation layer that receives the call.
The one idea to hold onto. A tool is a doorway. The agent stays on the phone and speaks; behind the scenes it sends a small packet of data to a URL, your automation does the real work, and a result comes back, all while the caller keeps talking. The agent never leaves the conversation.
This is the tools step from Build a Voice Agent From a Transcript, explained on its own. Everything here is generic; swap in whatever automation platform you like.
A tool (often called a "server tool" or "webhook tool") has three parts:
Like book_appointment with a clear description of when to use it. This is what the agent reads to decide whether to call it. Descriptive names and a good description are what make the agent pick the right tool at the right moment.
The webhook endpoint and how to hit it, usually a POST to something like https://YOUR-N8N-INSTANCE/webhook/book-appointment. This is where your automation lives.
The shape of the data the agent will send: which fields, what each one means, which are required. For a booking that's the caller's name, phone, and the requested time.
When the agent decides to use the tool, ElevenLabs makes the HTTP request from its own servers (not from the caller's phone) and waits for your response.
Here's the sequence during a live conversation. The caller never sees any of the machinery.
{ "status": "booked", "time": "Thursday 9am" }.Without it, the caller hears silence while the webhook runs, which on a phone feels broken. Telling the agent to say what it's doing before every tool call (and enabling the platform's pre-tool-speech setting) turns a multi-second dead pause into a natural "one moment" beat.
Most business voice agents need some combination of these. The pattern is identical; only the data changes.
Read-only. The agent sends a requested date or window and gets back open slots. Usually called before booking so the agent only offers times that are actually free.
Write. The agent sends the caller's details and a chosen time, and the automation creates the booking. The rule in the prompt: always check availability first, then book.
Read-only. The caller gives an order number, the agent sends it, and the automation returns status and details. The agent reads the status back in plain language.
The sequencing lives in your system prompt, not in the tool itself. "Always call check_availability before book_appointment" is a prompt instruction the agent follows.
On the receiving end, n8n (or any automation platform) is just a workflow that starts with a Webhook node. The flow is straightforward:
https://YOUR-N8N-INSTANCE/webhook/book-appointment. It receives the JSON the agent sent.You never expose this URL or any secret in your agent's prompt. The webhook URL is configured on the tool, and any API keys live in the automation platform or as a stored secret on the tool's headers, never in text the model reads.
Use placeholder URLs like https://YOUR-N8N-INSTANCE/webhook/book-appointment while you build. The real URL and keys belong in your tool config and your automation platform, not in the system prompt, not in anything you'd share.
A webhook tool is a small JSON file. You don't have to memorize it, the workflow generates it, but it helps to recognize the shape. A POST tool always needs a requestBodySchema with a top-level description, or it may not fire correctly.
Note the conventions: tool name in snake_case, JSON properties in camelCase, and every field carries a description so the agent knows exactly what to send.
You do not need a working n8n flow to test the agent's behavior around a tool. The test suite mocks every tool, it feeds the agent a fake response so you can check the conversation logic with no backend at all.
This lets you test two things that matter most:
{ "status": "booked" } and you confirm the agent reads it back correctly and ends cleanly.The generated tool-failure scenario sets the mock to return an error on purpose, then checks that the agent never claims success it didn't get. That's the test you most want to pass before going live, because a tool failing on a real call is a matter of when, not if. (See the testing lesson for how to read those results.)
Build and test the whole conversation with mocks first. Wire up the actual n8n workflow only once the agent talks to the tool correctly. That order keeps you from debugging two things at once.
Built by AI Service Engine · back to the main voice-agent lesson · install Claude Code first