# Tools during calls

> Let an agent read and update your own system while it talks, through your MCP server, with confirmation for actions.


# Tools during calls

An agent can use the tools of **your own MCP server** while it is on the phone: check availability, look up a case, book an appointment. Allerto knows nothing about your domain; it connects to the server you name, offers its tools to the voice model and applies the same safety rules to every customer.

Tools need the `gemini-3.8-live` voice model, which keeps talking while a tool runs.

```json
{
  "type": "inbound",
  "name": "Reception",
  "persona": "Giulia",
  "model": "gemini-3.8-live",
  "voice": "Erinome",
  "greeting": "Buongiorno, sono Giulia dello Studio Rossi. Come posso aiutarla?",
  "instructions": "Help the caller find and book a cleaning appointment.",
  "result": [{ "key": "name", "label": "Name", "type": "text" }],
  "mcp": {
    "url": "https://agenda.example.com/mcp",
    "tools": ["availability", "book"]
  }
}
```

| Key         | Type          | Meaning                                                                      |
| ----------- | ------------- | ---------------------------------------------------------------------------- |
| `mcp.url`   | https URL     | Your MCP server, Streamable HTTP transport, on a public address (port 443)   |
| `mcp.tools` | list of names | Optional allow-list; without it every tool of the server is offered (max 20) |

Store the bearer token Allerto sends as `Authorization: Bearer …` separately. It is encrypted and never returned (the agent shows `mcp_token_set`):

```sh
curl -X PUT https://api.allerto.cloud/v1/agents/$AGENT/mcp-token \
  -H "Authorization: Bearer $ALLERTO_API_KEY" -H "Content-Type: application/json" \
  -d '{"token": "…"}'
curl -X POST https://api.allerto.cloud/v1/agents/$AGENT/mcp-test \
  -H "Authorization: Bearer $ALLERTO_API_KEY"
```

`mcp-test` connects with the draft's settings and lists the tools the agent would get, each marked `read` or `action`. The same is available as `allerto agents mcp-token` / `allerto agents mcp-test`, as the MCP tools `set_agent_mcp_token` / `test_agent_mcp`, and in the console (agent → **Tools**).

## Reads and actions

A tool annotated `readOnlyHint: true` is a **read**: it runs as soon as the agent calls it. Every other tool is an **action**, and Allerto enforces a confirmation that the model cannot skip:

1. The agent calls the action with its data. Nothing is sent to your server: the agent gets back a summary and a one-time confirmation code.
2. The agent reads the summary to the person and asks for an explicit yes.
3. Only a second call with **the same data** and the code reaches your server, once. A repeated call returns the first result without calling you again.

Each executed action carries `_meta["allerto/idempotency_key"]` (and every call `_meta["allerto/call_id"]`), so your server can refuse duplicates on its side too.

## When your server is slow or down

- Tools are listed when the call starts (at most 4 seconds, then cached for 5 minutes). If the server cannot be reached the call goes on without tools and the error is logged on the call.
- A read waits at most 5 seconds, an action 8 seconds. After that the agent is told the system is not answering; after an action it is told it does not know whether the action went through, must not say it is done, and that the team will get back to the person.
- Results are cut to 1,500 characters and treated as data, never as instructions. At most 15 tool calls per call.

Keep results short and phone-sized (two or three options, not a full list): the agent reads them aloud.

## What you get after the call

Every tool call is on the call as `tool_calls` (API, `call.completed`, console):

```json
"tool_calls": [
  { "name": "availability", "status": "ok", "arguments": { "day": "thursday" }, "result": "Thursday 15:30 or 17:00.", "duration_ms": 640, "at": "2026-10-01T09:12:03.000Z" },
  { "name": "book", "status": "confirmation_required", "arguments": { "time": "15:30" }, "result": "…", "duration_ms": 1, "at": "…" },
  { "name": "book", "status": "ok", "arguments": { "time": "15:30" }, "result": "Booked, code R-1001.", "duration_ms": 810, "at": "…" }
]
```

`status` is `ok`, `error` (your server answered with an error), `confirmation_required`, `timeout`, `unknown_tool` or `limit`. An action whose last entry is not `ok` did not happen, whatever the agent said: check `tool_calls`, not the transcript.
