AI agent playbooks
Voice calls through an assistant
Place or answer a 1:1 Telegram voice call from an AI assistant, with the audio in a ready browser tab and the person confirming before anything rings.
Goal
You start, answer, decline or hang up a 1:1 Telegram voice call on the user's behalf. You do not carry the audio: it flows between the worker and one of the user's browser tabs.
Permissions needed
- Scope
callsforcalls.start,calls.answer,calls.decline,calls.hangup,calls.endpoints. messages.readforcalls.readiness,calls.list,calls.get.- The account must be within the connection's reach. The
callsscope is not part of the Operations or Setup presets: the user has to switch it on or choose Full access.
Ask the person before
A call makes a real person's phone ring. Ask the user whom to call, from which account and why. Never call someone just because they are on a list.
Check first
- Call
whoamito make sure you have thecallsscope. - Call
calls.endpoints. An empty list means no tab has Ready for calls placed by an agent switched on: ask the user to open the app and switch it on (on the AI connections page or in Call settings). Without a tab,calls.startanswersaudio_endpoint_requiredand nothing rings. - Call
calls.readinesswithconversationId. Whenreadyisfalse, read the reason code in the table below and stop.
Steps
- Call
calls.startwithconversationId. The first answer is alwaysconfirmation_requiredwith aconfirm_token.
- Take the
callIdand follow the dialling withoperations_get, then the call itself withcalls.get(or thecalls.*events):ringing→exchanging_keys→active→ended. - To answer an incoming call that is
ringing, callcalls.answerwithcallId; the audio goes to the ready tab. If someone already answered, you getalready_answered. - Call
calls.hangupto end, orcalls.declinefor an incoming call nobody answered. Both always run and never count against limits.
Check afterwards
Read calls.get: state = ended and end_reason tell the outcome (hangup, remote_hangup, declined, missed, busy, failed, media_unreachable…). Only tell the user "you talked" when the call was active and has a duration.
When it fails
| Code | Meaning | What to do |
|---|---|---|
proxy_no_udp |
The account's proxy cannot carry audio (HTTP, or SOCKS5 without confirmed UDP) | Tell the user a SOCKS5 proxy with UDP is needed; do not retry |
audio_endpoint_required |
No ready tab | Ask the user to switch on Ready for calls placed by an agent |
account_unavailable |
The account is not logged in, paused, its proxy fails or the worker is off | Stop and tell the user |
worker_outdated |
The worker is older than 1.0.49 | Wait for it to update itself |
not_private_chat |
Not a private chat with one person | Pick another private chat |
peer_opted_out |
The person asked not to be contacted | Do not call |
quota_exceeded |
A Safe account already made 10 calls today, or calls are too close together | Wait; never switch accounts to get around it |
account_busy, node_calls_full |
The account or machine already carries its calls | Try again later |
calls_disabled |
Calls are switched off system-wide | Wait |
already_answered, call_ended, call_not_found |
Someone answered, the call ended, or it is out of reach | Read calls.get again |
An end of media_unreachable means the call was picked up but the audio could not get through the proxy. Do not call again right away; ask the user to check the proxy.
Stop conditions
Stop when the call is ended, when the user does not confirm, or on any error code above other than account_busy / node_calls_full.