When a caller says something that matches a tool’s trigger (defined in its description field), the agent fires that tool automatically mid-conversation.
The key thing to understand: tools are attached to LLM models, not to agents directly.
Agent → LLM Model → Tools
One LLM model can have multiple tools. Every agent that uses that model inherits all its tools automatically. To give an agent a new tool, update the LLM model it is linked to — not the agent itself.
If you haven’t built an agent yet, start with the Quickstart first.
| Type | What the agent does | Best for |
|---|
api_call | Calls your HTTP endpoint | Lookups, CRM updates, custom logic |
transfer_call | Transfers to a phone number | Routing to humans |
extract_information | Saves structured data from the conversation | Capturing name, email, budget |
end_call | Hangs up the call | Completing a flow cleanly |
send_sms | Sends a text message | Follow-ups, confirmations |
send_email | Sends an email | Lead handoffs, summaries |
schedule_calendar_event | Books a calendar event | Demo scheduling, appointments |
Whenever a tool talks to a third-party provider — send_sms, send_email, or schedule_calendar_event — you’ll need a credential_id pointing at an integration for that provider. api_call, transfer_call, extract_information, and end_call don’t need one.
send_sms
Sends a text message when triggered. No credential_id needed — the SMS is sent from the same number used to make the call (your purchased OneInbox number or your Twilio/Telnyx number registered with OneInbox).
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "notify_team_sms",
"type": "send_sms",
"description": "SMS the team when a lead is captured. Trigger when the caller shares their contact details.",
"messaging_config": {
"to": "caller",
"body_template": "New lead: {name} ({phone})"
}
}'
| Field | What it does |
|---|
description | How the agent decides when to fire this tool — write it as a trigger condition |
messaging_config.to | "caller" to text whoever is on the call, or an explicit E.164 number to notify your team |
messaging_config.body_template | Message text. Use {variable_name} (single braces) for dynamic values. Use {{caller}} to auto-insert the caller’s phone number |
The SMS sends from the same number used for the call — make sure that number has SMS capability enabled. When purchasing a number via OneInbox or registering your own Twilio/Telnyx number, verify that it supports SMS before using this tool.
{{caller}} is a built-in variable that auto-resolves to the caller’s phone number at call time — the system fills it in automatically. Never ask the caller for their number just to include it in the message body.
send_email
Sends an email when triggered. Use this to deliver lead summaries to your sales team, send follow-up emails to callers, or notify someone when a key moment happens in a call.
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "notify_team_email",
"type": "send_email",
"description": "Email the sales team when a lead is captured. Trigger when the caller expresses interest.",
"credential_id": "<resend_or_sendgrid_credential_id>",
"messaging_config": {
"to": "sales@example.com",
"subject_template": "New lead: {name}",
"body_template": "{summary}"
}
}'
| Field | What it does |
|---|
description | How the agent decides when to fire this tool — write it as a trigger condition |
credential_id | UUID of a resend or sendgrid integration. The email sends from that integration’s from_email — which must be on a domain you’ve verified with the provider, or the send fails with HTTP 403 |
messaging_config.to | Recipient email address. Use {{email}} to send to the caller’s email address |
messaging_config.subject_template | Email subject line. Use {variable_name} (single braces) for dynamic values |
messaging_config.body_template | Email body text. Use {variable_name} (single braces) for dynamic values pulled from the conversation |
Want every call to auto-send a summary SMS/email without a tool call? Set
post_call_sms / post_call_email directly on the agent instead — see
Agents. Tools fire mid-call based on a trigger; post-call
config fires once, automatically, after every call ends.
{{email}} resolves from the dynamic_variables object passed when the call is initiated — for example "dynamic_variables": {"email": "caller@example.com"} in the outbound call request. Pass the caller’s email at dial time and use {{email}} anywhere in to, subject_template, or body_template to insert it automatically.
schedule_calendar_event
Books a calendar event when triggered. Use this when you want the agent to schedule a demo or follow-up meeting directly during the call.
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "book_demo",
"type": "schedule_calendar_event",
"description": "Book a product demo when the caller asks to schedule a meeting or demo. Trigger phrases: schedule, book a demo, set up a call.",
"credential_id": "<calcom_credential_id>",
"calendar_config": {
"event_type_id": 123456,
"duration_minutes": 30,
"timezone": "America/New_York"
}
}'
| Field | What it does |
|---|
description | Trigger condition — tell the agent exactly when to fire this (e.g. “when the caller agrees to a meeting”) |
credential_id | UUID of a calcom integration. Required — the tool checks availability and books against this Cal.com account |
calendar_config.event_type_id | The Cal.com event type ID to book against. Find it in your Cal.com dashboard URL or via GET https://api.cal.com/v2/event-types |
calendar_config.duration_minutes | Length of the event in minutes |
calendar_config.timezone | IANA timezone string for the booking (e.g. "Asia/Kolkata", "Asia/Tokyo", "Europe/London", "America/New_York"). Defaults to UTC if omitted — set this to the caller’s timezone so the booked slot appears at the correct local time |
The agent must collect the attendee’s name and email during the call —
both are required by Cal.com to complete the booking. If the requested slot
has no availability (e.g. outside your Cal.com working hours), the booking
fails with HTTP 400.
api_call
Calls your own HTTP endpoint during the call. Use this to look up information (e.g. order status, account details), push data to your CRM, or trigger custom business logic based on what the caller says.
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "check_inventory",
"type": "api_call",
"description": "Look up inventory by SKU when the caller asks about stock or availability.",
"url": "https://api.example.com/inventory",
"method": "POST",
"headers": {
"Authorization": "Bearer <your_secret>"
},
"parameters": [
{
"name": "sku",
"type": "string",
"required": true,
"description": "Product SKU the caller mentioned"
}
],
"run_in_background": true,
"speak_during_execution": true
}'
| Field | What it does |
|---|
url | Your endpoint URL — must be publicly reachable |
method | HTTP method (GET, POST, PUT, PATCH) |
headers | Any auth headers your endpoint requires |
parameters | Fields the agent extracts from the conversation and passes to your API as the request body |
run_in_background | true = agent keeps talking while the API call runs in parallel. false = agent pauses and waits for the response |
speak_during_execution | true = agent says something like “Let me check that for you…” while the API call is in progress |
Nested parameters (full JSON Schema)
parameters only supports a flat list of fields. If your endpoint needs
nested objects, arrays, or enums, use parameters_schema instead — a raw
JSON Schema object, validated server-side before save. Use one or the other,
not both:
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "create_ticket",
"type": "api_call",
"description": "Open a support ticket when the caller reports an issue.",
"url": "https://api.example.com/tickets",
"method": "POST",
"parameters_schema": {
"type": "object",
"properties": {
"subject": { "type": "string", "description": "Ticket subject" },
"priority": { "type": "string", "enum": ["low", "high"] },
"items": {
"type": "array",
"items": {
"type": "object",
"properties": { "sku": { "type": "string" } },
"required": ["sku"]
}
}
},
"required": ["subject"]
}
}'
transfer_call
Transfers the caller to a real phone number. Use this when the caller asks to speak with a human or needs to reach a specific team. OneInbox supports two transfer modes — cold (default) and warm.
| Mode | What happens |
|---|
| Cold (default) | Blind SIP REFER — caller is immediately handed off. The human picks up with no prior context. |
| Warm | Agent calls the human first, briefs them with the caller’s context, then connects the caller once the human is ready. Caller hears hold music during the briefing. |
Cold transfer
The default. The caller is transferred instantly — no briefing, no hold music. Use this when speed matters more than context handoff (e.g. routing to a general support queue).
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "transfer_to_support",
"type": "transfer_call",
"description": "Transfer to a human agent when the caller asks to speak to a person or escalate. Trigger phrases: talk to someone, speak to a human, I want a real person.",
"transfer_to": "+15105550100"
}'
Omitting transfer_config entirely is equivalent to transfer_config.mode: "cold".
Warm transfer
The agent calls the human first, gives them a briefing (caller’s name, reason for calling, any relevant context), then bridges the caller in once the human is ready. The caller hears hold music during the consult.
Use this when the human needs context before picking up — e.g. transferring to a sales manager for a high-value lead.
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "warm_transfer_to_supervisor",
"type": "transfer_call",
"description": "Warm transfer to a supervisor when the caller needs escalation.",
"transfer_to": "+15105550100",
"transfer_config": {
"mode": "warm",
"extra_instructions": "Greet the supervisor, give them the caller'\''s name and issue, and ask if they'\''re ready before connecting."
}
}'
| Field | What it does |
|---|
transfer_to | E.164 phone number to transfer the caller to |
description | Trigger condition — be specific so the agent knows exactly when to fire this tool |
transfer_config.mode | "cold" (default) — blind handoff; "warm" — agent briefs human first |
transfer_config.extra_instructions | Warm mode only — guides what the agent should say to the human during the briefing |
Silently captures structured data from the conversation as it happens — the agent doesn’t announce it to the caller. Use this to save lead qualification data, capture names and emails, or record key facts from the call.
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "lead_capture",
"type": "extract_information",
"description": "Extract lead info from the conversation. Run this once the caller has shared their name and contact details.",
"extraction_schema": {
"fields": [
{
"name": "full_name",
"type": "string",
"required": true,
"description": "Caller full name"
},
{
"name": "email",
"type": "string",
"description": "Caller email address"
},
{
"name": "interested",
"type": "boolean",
"description": "Whether the caller expressed interest"
}
]
}
}'
| Field | What it does |
|---|
description | Tells the agent when to run the extraction — not a phrase trigger, but a condition (e.g. “once the caller has answered the qualifying questions”) |
extraction_schema.fields | List of fields to extract. Each field has a name, type (string, boolean, number), optional required, and a description that guides the extraction |
The captured data is available in the call record after the call ends.
end_call
Hangs up the call cleanly. Use this at the end of a flow — after a booking, after the caller says goodbye, or when the agent has completed its task. Without this tool, the call continues until the silence timeout is reached.
curl -X POST https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"name": "hangup",
"type": "end_call",
"description": "End the call cleanly after the agent has completed its task or the caller says goodbye."
}'
Creating a tool makes it available in your account, but the agent can’t use it yet. You need to attach it to the LLM model linked to your agent. Use the llm_id from your agent’s create response — this is the AI brain that decides what to do during a call.
curl -X PATCH https://api.oneinbox.ai/v1/models/<llm_id> \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{
"tool_ids": ["<tool_id_1>", "<tool_id_2>"]
}'
Every agent linked to this llm_id picks up the change immediately — no restart required.
The description on each tool is the trigger signal — the LLM reads it to decide when to fire the tool automatically. The system prompt gives the agent context and ordering for how to use tools in the flow.
Reference tools by their name field (the name you set when creating the tool), not by tool ID. The LLM matches the name to the tool it has available and fires it at the right moment.
You are a helpful sales assistant for Acme Corp.
When the caller shares their name and email, use the lead_capture tool immediately.
After capturing their info, ask if they'd like to receive a follow-up SMS. If they say yes, use notify_team_sms.
If at any point the caller asks to speak to a human, use transfer_to_human.
After the task is complete or the caller says goodbye, use end_call.
Keep all replies under two sentences. Be warm and direct.
Write the description as a trigger condition (“Fire when the caller says X” or “Run once the caller has answered the qualifying questions”). The system prompt then reinforces the order and flow. Both are read by the LLM — the description drives when, the system prompt drives how.
After the call ends, the extracted data and tool activity appear in the call record. Stop the call first, wait a few seconds, then fetch:
# 1. Stop the call
curl -X POST https://api.oneinbox.ai/v1/calls/<call_id>/stop \
-H "Authorization: Bearer <api_key>"
# 2. Wait 2–3 seconds, then fetch
curl https://api.oneinbox.ai/v1/calls/<call_id> \
-H "Authorization: Bearer <api_key>"
{
"id": "call_abc123",
"status": "completed",
"messages": [
{ "role": "agent", "content": "Hi! How can I help?" },
{ "role": "user", "content": "My name is Sama, my email is sama@acme.com" }
],
"outcome": "Interested",
"analysis": {
"summary": "Caller expressed interest and shared contact details."
}
}
messages and analysis are only available after the call ends — both are empty while the call is active.
Retrieve every tool in your account. Useful for finding tool IDs when you need to attach or update them.
curl https://api.oneinbox.ai/v1/tools \
-H "Authorization: Bearer <api_key>"
Change a tool’s name, description, or config. For example, update the trigger description to make the agent more (or less) sensitive to firing it.
curl -X PATCH https://api.oneinbox.ai/v1/tools/<tool_id> \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{ "description": "Updated trigger description" }'
Remove a tool permanently. If the tool is attached to an LLM model, detach it first by PATCHing the model with an updated tool_ids array that excludes the deleted tool’s ID.
curl -X DELETE https://api.oneinbox.ai/v1/tools/<tool_id> \
-H "Authorization: Bearer <api_key>"
API reference
Create tool · List tools · Update tool · Delete tool