Voice agents
A Wordcab agent is a system prompt, a voice, an LLM, and a set of tools. Create one, attach a phone number, and start taking calls.
A Wordcab agent is a named configuration: a system prompt, a voice, an LLM, a set of tools, and call-lifecycle settings. Once created, an agent can handle outbound or inbound calls, join meetings via SIP or WebRTC, or run as a text-only chat endpoint.
Create an agent
agent = client.agents.create(
name="Support Agent",
system_prompt=(
"You are a support agent for Contoso Health. "
"Verify the caller, answer benefits questions, and book a callback if you cannot help."
),
voice_id="ember",
llm_model="qwen3.5-4b",
stt_model="voxtral-realtime",
language="en",
interruption_threshold=0.5,
first_message="Thanks for calling Contoso. How can I help you today?",
tools=[
{"type": "function", "function": { ... } },
],
context_window=20,
)
print(agent.id)const agent = await client.agents.create({
name: "Support Agent",
systemPrompt: "You are a support agent for Contoso Health...",
voiceId: "ember",
llmModel: "qwen3.5-4b",
sttModel: "voxtral-realtime",
language: "en",
interruptionThreshold: 0.5,
firstMessage: "Thanks for calling Contoso. How can I help you today?",
tools: [...],
});System-prompt variables
Use {{variable}} placeholders in the system prompt; pass values through the context object when you start a call.
system_prompt = \"\"\"You are calling {customer_name} about order {order_number}.
The order contains: {items}. Delivery: {delivery_date}.\"\"\"
client.agents.calls.create(
agent_id=agent.id,
phone_number="+14155551234",
context={
"customer_name": "Jane",
"order_number": "ORD-12345",
"items": ["Widget Pro", "Gadget Plus"],
"delivery_date": "April 30",
},
)Tool use
Agents call tools the same way chat completions do. Register tools on the agent, and implement the handlers in your backend. Wordcab will dispatch a webhook to your tool_url when a tool is invoked.
{
"type": "function",
"function": {
"name": "lookup_member",
"description": "Find a member by phone number.",
"parameters": {
"type": "object",
"properties": {"phone": {"type": "string"},
"required": ["phone"]
}
}
}Handler
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post("/tools/lookup_member")
def lookup_member():
body = request.get_json()
phone = body["arguments"]["phone"]
member = db.get_member_by_phone(phone)
return jsonify({"member_id": member.id, "plan": member.plan})Wordcab posts to tool_url with {"name": "...", "arguments": {...}, "call_id": "..."}. The response body is passed back to the model. Add HMAC signature verification — see Webhooks.
Start a call
Outbound:
call = client.agents.calls.create(
agent_id=agent.id,
phone_number="+14155551234",
context={"customer_name": "Jane"},
max_duration=300,
record=True,
)Inbound: attach a phone number to the agent in the dashboard (or via client.agents.update(agent_id, phone_numbers=[...])). Incoming calls to that number are answered by the agent.
Monitor & end
Poll for state, or subscribe to call.started, call.completed, and call.failed webhooks.
call = client.calls.get(call.id)
print(call.status) # initiating | ringing | in_progress | completed | failed | no_answer
# ...later
client.calls.end(call.id) # force-end a live callTranscripts & recordings
Every call produces a transcript and, when record=True, an audio recording stored in your configured object store (in cloud) or your VPC bucket / on-prem MinIO (self-hosted).
tx = client.transcripts.get(call.transcript_id)
for u in tx.utterances:
who = "Agent" if u.speaker == 0 else "Caller"
print(f"{who}: {u.text}")The Gym runs your agent against a suite of scripted callers and asserts on outputs — tool calls made, facts extracted, tone. Gate every agent change behind a green Gym run.