Agents
An agent is one JSON document. The console editor, allerto agents push, POST /v1/agents and the MCP tool create_agent all take exactly this object. The machine-readable schema is at /v1/agents/schema and in the reference.
Common keys
| Key | Type | Default | Meaning |
|---|---|---|---|
type | inbound | outbound | — | Set at creation, never changes |
name | text (2–100) | — | Internal name |
persona | text (1–80) | — | How the agent introduces itself ("Giulia") |
language | it | en | it | Language of the conversation and of extracted text |
model | gpt-live-1 | gemini-3.8-live | gpt-live-1 | Live voice model; gemini-3.8-live is required for mcp tools |
voice | voice id | model default | A voice of the chosen model (bossa… / Erinome…); or customVoiceId (GPT-Live only) |
instructions | text (10–12000) | — | What the agent does. Outbound agents may use {{input}} placeholders |
result | list of fields | [] | Data extracted after the call (at least one for inbound) |
delivery | object | sandbox | Where call.completed goes: sandbox, webhook, email or both |
review | on_issues | always | never | inbound on_issues, outbound never | When an operator must check the data before it is delivered |
transfer | object | none | Hand the call to an operator, see below |
mcp | object | none | Your MCP server: its tools during the call, see Tools during calls |
recording | boolean | false | Record the audio of phone calls; the agent announces it, see Privacy |
Inbound keys
| Key | Type | Meaning |
|---|---|---|
greeting | text (10–1000) | First sentence when someone calls |
Numbers belong to your account: Allerto buys them and assigns them to it. You route each one to any of your inbound agents with PUT /v1/numbers/{id} ({"agent": "<id>"}) or in the console, and every agent shows the numbers it answers on (numbers in the agent object). An agent from another account is refused with different_account.
Clients are an optional grouping (GET/POST /v1/clients). DELETE /v1/clients/{id} removes one: its agents are archived, its queued calls cancelled and its console login removed, while its calls and usage stay in your history. A client whose numbers are still active is refused with client_has_numbers; its external_id can be reused afterwards.
Outbound keys
| Key | Type | Default | Meaning |
|---|---|---|---|
opening | text with {{input}} | — | First sentence when the person answers |
inputs | list of fields | [] | Data you pass with every call; required ones are enforced |
calling.callerId | E.164 | an active number of the account | Caller ID; must be one of your numbers, checked on publish and again before each call |
calling.identityCheck | boolean | true | Confirm the person before revealing why you call |
calling.hours | {days, from, to} | Mon–Sat 09:00–20:00 | Calling window, Italian time; within Mon–Sat 08:00–21:00 |
calling.maxAttempts | 1–5 | 3 | Attempts when nobody answers (retries after 15 min, 1 h, 3 h) |
calling.autoCallback | boolean | true | Call back automatically when the person asks for a later time |
Transfer to an operator
"transfer": {
"to": "+390212345678",
"when": "gas leaks, flooding or other emergencies",
"hours": { "days": [1, 2, 3, 4, 5], "from": "09:00", "to": "18:00" },
"announcement": "La metto in contatto con un operatore, resti in linea.",
"musicUrl": "https://example.com/hold.mp3"
}
When the person asks to speak with an operator or a real person (or in the situations of when), the agent may ask once for their name and reason, then says the announcement and the call is transferred to to. Only to is required.
to: the operator's number (E.164). It is the only number the agent ever transfers to, and it cannot be one of your Allerto numbers.hours: Italian time, any day of the week. Outside them the agent says nobody is available and takes the request. Withouthoursthe transfer is always available.announcement: said word for word; the default is "La metto in contatto con un operatore, resti in linea." (Italian) or "I'm putting you through to a colleague, please hold." (English).musicUrl: an https audio file played while the operator's phone rings; without it the person hears the normal ringing tone.
The operator sees the Allerto number the person called (Italian networks block calls from abroad that show an Italian mobile number, so the caller's own number cannot be passed through); the caller's number is in the call data. If nobody answers within 25 seconds, the person hears that no operator is available and that their request has been recorded. A transfer lasts at most 30 minutes. The call keeps what was collected before the transfer, with outcome: "transferred" and a transfer object (see Calls).
Fields
inputs and result use the same field shape:
{
"key": "pay_by",
"label": "Promised date",
"type": "date",
"required": false,
"options": [],
"when": { "field": "answer", "equals": "will_pay" },
"description": "Only if they commit to a date"
}
| Key | Meaning |
|---|---|
key | Lowercase letters, digits and _; unique in the list. Appears in data and webhooks |
label | Human name, also used by the agent when asking |
type | text, number, boolean, select, date (YYYY-MM-DD), phone, email |
required | Missing required values become issues (and trigger review for inbound agents) |
options | Allowed values for select |
when | Result fields only: required only when another field has a value |
description | Extra guidance for extraction |
Domain outcomes (promise to pay, dispute, confirmed appointment) belong in a select result field. The call outcome stays generic across sectors.
Examples
Inbound:
{
"type": "inbound",
"name": "Fault reports",
"persona": "Giulia",
"greeting": "Good morning, this is Giulia, the virtual assistant of Studio Ferrario. How can I help?",
"instructions": "Collect fault reports for the buildings we manage. Ask one question at a time.",
"result": [
{ "key": "caller_name", "label": "Name", "type": "text", "required": true },
{
"key": "callback_phone",
"label": "Callback number",
"type": "phone",
"required": true
},
{
"key": "address",
"label": "Building address",
"type": "text",
"required": true
},
{
"key": "description",
"label": "Description",
"type": "text",
"required": true
}
],
"delivery": { "mode": "email", "email": { "to": ["office@example.com"] } }
}
Outbound: see the Quickstart.
Drafts, versions and concurrency
| Step | API | CLI |
|---|---|---|
| Create | POST /v1/agents {"config", "client"?} | allerto agents push file.json |
| Edit | PUT /v1/agents/{id}/draft {"config", "revision"} | allerto agents push file.json |
| Check | POST /v1/agents/validate {"config"} | allerto agents validate file.json |
| Preview | POST /v1/agents/{id}/preview {"inputs"} | allerto agents preview <id> |
| Publish | POST /v1/agents/{id}/publish {"revision"} | allerto agents publish <id> |
| History | GET /v1/agents/{id}/versions | — |
| Archive | POST /v1/agents/{id}/archive | allerto agents archive <id> |
Every save needs the current revision. If someone else saved in between you get 409 revision_conflict with the current revision in details: reload, merge, save again. Publishing creates an immutable version; calls always record which version spoke.
Validation errors carry a path per problem (for example opening or result.2.when), so a program can point at the exact field.