Guides
Testing without a phone
Run the whole call lifecycle with the mock engine and mock telephony, script the caller, and read the development outboxes.
You can build and test almost everything without dialling anyone. Two independent switches make this possible, and both default to the safe setting:
| Switch | Mock value | What it means |
|---|---|---|
| Engine | mock | A scripted simulation plays both sides of the call. No audio, no models |
| Telephony mode | mock | Number search, buy and release are simulated, and nothing is dialled at a carrier |
The telephony mode is an operator setting. The engine is yours to choose: set agent_config.engine, or agent_data.engine on one call, to mock. If neither is set, the operator's default applies, and the shipped default is mock.
A first mock call
curl -X POST https://api.sevennadi.si/call \
-H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "3c90c3cc-0d44-4b50-8822-8dd25736052a",
"recipient_phone_number": "+919876500123",
"user_data": {"name": "Asha"},
"agent_data": {"engine": "mock"}
}'The call goes through the real lifecycle: queued, initiated, ringing, in-progress, call-disconnected, completed. Webhooks fire for each status. At the end the execution has a transcript, an itemised cost, a recording, and extraction results, and the wallet is charged at the price book's rates.
Mock calls run faster than real time; the speed is an operator setting.
By default the caller says three fixed lines:
Hello, yes, who is this?
Okay, tell me more.
Sounds good. Thank you, bye!Magic recipient numbers
The last four digits of the recipient number choose the outcome.
| Number ends in | Outcome |
|---|---|
0000 | no-answer |
1111 | busy |
2222 | failed, with error_message Mock telephony failure |
3333 | An answering machine |
| Anything else | A conversation, ending completed |
For 3333, the machine is detected (unless task_config.voicemail is false), the call ends with answered_by_voice_mail: true and hangup reason Voicemail detected. With voicemail: false the agent talks to the machine and hangs up after hangup_after_silence.
Script the caller
agent_data.mock_script replaces the caller's lines.
{
"agent_id": "3c90c3cc-0d44-4b50-8822-8dd25736052a",
"recipient_phone_number": "+919876500123",
"agent_data": {
"engine": "mock",
"mock_script": ["Hi, I want to check my order status", "It is ORD-1", "Thanks, bye"]
}
}For graph agents, a line event:<name> injects an external event and takes the current node's matching event edge. It is not a caller turn.
Script tool calls
Without instructions, a caller line triggers the first tool whose name is said in it, else the first whose description shares a keyword of four or more letters with it. To be exact, use agent_data.mock_tool_calls:
{"agent_data": {
"engine": "mock",
"mock_script": ["Where is my order?", "Thanks, bye"],
"mock_tool_calls": [{"turn": 1, "name": "check_order_status", "arguments": {"order_id": "ORD-1"}}]
}}turn is the caller line the tool fires on, counted from 1. When mock_tool_calls is present, only those tools fire.
A custom function on a mock call makes its real HTTP request to your API, with the same private-network check and 10 second timeout as on a live call. The agent then says <tool> returned: <body>, or Sorry, I could not complete <tool>: HTTP 500. A transfer tool fills transfer_call_data and ends the call; end_call ends it.
What the mock engine does and does not do
It honours:
{name}and{{name}}variables in the welcome message and graph prompts.- Knowledge bases: a reply that quotes the best-matching sentence, prefixed
From our documents:. - Graph routing by the deterministic keyword rule, with
node_pathandnode_extracted_dataon the execution. welcome_message_delay,call_hangup_message(said when the caller says "bye"), voicemail detection.auto_reschedule: a line such as "call me back in 30 minutes", "tomorrow" or "at 6 pm" ends the call and creates a newscheduledcall. The two executions point at each other incontext_details.- The
send_smstool, through the compliance checks and the message provider.
It only logs, without acting on them: the ambient noise track, noise cancellation level, keypad setting, and the transcriber's keywords.
It never uses an LLM: replies are placeholders, and a graph's LLM nodes say [<node_id>] <prompt>. It tests your wiring, not the quality of the conversation.
Test chat
For a quick text conversation with the agent's real prompt, tools and knowledge base, use POST /agent-chat/{agent_id}; see Agents. With LLM credentials it answers with the agent's own model. Without, it follows the same rules as the mock engine. It accepts mock_tool_calls too.
To hear the agent, use a browser voice test. That one needs the real engine.
The mock recording
A mock call has a real, playable WAV file at telephony_data.recording_url: one tone per turn, higher for the agent and lower for the caller, each as long as the turn. It contains no speech.
Mock telephony and other development defaults
With the shipped defaults:
GET /phone-numbers/searchreturns made-up numbers, andPOST /phone-numbers/buyalways succeeds. The wallet is still debited.- The per-number daily cap is not applied.
POST /phone-numbers/verifiedreturns the code asmock_otpinstead of sending an SMS, while the message provider is the mock one.- Top-ups with the mock payment provider are paid at once.
Development outboxes
When the operator has not configured real email or SMS, messages are stored instead of sent.
curl "https://api.sevennadi.si/dev/outbox?kind=invite&limit=5" \
-H "Authorization: Bearer vs-0123456789abcdef0123456789abcdef"[{"id": "8e7d6c5b-4a39-4281-9706-f5e4d3c2b1a0", "to": "ravi@example.test", "subject": "...", "kind": "invite",
"text": "...", "html": "...", "link": "https://app.sevennadi.si/accept-invite?token=...",
"created_at": "2026-10-13T12:30:00Z", "sent_at": null}]GET /dev/outboxreturns stored emails with the first link extracted. You see mail addressed to your own login; admins also see invitations sent into their workspace.GET /dev/messagesreturns stored SMS and WhatsApp messages with their full text (admin). With the mock message provider, numbers ending0000fail.
GET /dev/outbox answers 404 in live telephony mode, and GET /dev/messages in production or live mode.
Limitations
- The mock engine does not exercise speech recognition, the LLM, the voice, barge-in or latency.
- Its transcripts are not passed through PII redaction.
- Mock calls are charged like real ones. Use a test account, or expect the wallet to move.
- If the operator runs live telephony, an agent on the
ownengine dials for real. Check which mode you are in before testing with real numbers.