Telephony only. WebSocket and browser sessions never trigger pre-connect requests.
How it works
- A call arrives on the agent’s number. Before answering, the platform runs the agent’s
pre_connect_requestsin order, at most two. - For each entry it makes one HTTPS request to your URL, carrying the values named in
sends, such ascaller_number. - Your endpoint replies with JSON within the timeout, 800 ms at most. The platform reads the values named in
returnsoff the response by dotted path. - The platform answers the call. If your response included a
greetingand the entry allows it, that greeting is spoken. Otherwise the agent’s greeting is spoken, with any{{name}}placeholders filled from the captured values. - The captured values are placed at the top of the conversation, so the model knows them from the first turn.
{"reject": true}, which ends the call unanswered.
Add it to your agent
pre_connect_requests is a field on the agent record. Add it with PUT /v1/agents/{id} on an agent you already have, or include it in the body of POST /v1/agents when you create one. This update asks a CRM for the patient behind the caller’s number, greets them by name, and keeps their record id for the conversation:
What your endpoint receives
The request carries only whatsends names. The platform supplies five call facts that any entry may send:
With
"sends": ["caller_number", "dialed_number", "direction"] a POST endpoint receives:
GET endpoint receives the same values as query parameters: ?caller_number=%2B14155550100&dialed_number=%2B14155550199&direction=inbound.
A fact the platform does not have is left out, not sent blank. When the caller withholds their number, caller_number is missing from the request; treat that as an unknown caller, and the default on each capture applies.
The request is a plain HTTPS call with the headers you configured. There is no signature; authenticate it with a header value only you and the platform know.
What your endpoint returns
Respond with200 and a JSON object within the timeout.
A response that is not JSON, not a 2xx, larger than 8 KB, or later than the timeout counts as no response. The platform does not retry.
For the clinic agent above, the CRM might answer:
patient_name as Maria and patient_id as pt_48213, and the caller hears “Thanks for calling Northside Dental, Maria. How can I help?”
Use the captured values
In the greeting
Write{{name}} in the agent’s greeting for any name in returns. The platform fills it from the captured value, or from that capture’s default when the lookup returned nothing. An unknown caller to the clinic agent hears “Thanks for calling Northside Dental, there. How can I help?”, so pick a default that reads well in the sentence.
Every placeholder has to end up with a non-empty value. If any {{name}} has neither a value nor a default, or resolves to an empty string, the platform speaks the agent’s greeting exactly as written, braces included. An empty default is not a way to make a placeholder disappear.
Only names in returns are substituted. To speak the caller’s number back, have your endpoint return it and capture it.
As a greeting your endpoint writes
When your endpoint should decide the wording, return a top-levelgreeting and list "greeting" in the entry’s allow_overrides:
In the conversation
The platform puts the captured values at the top of the transcript as the result of a platform tool namedaai_pre_connect_context:
patient_id to a tool without asking the caller for it. Tell the model in the system_prompt what the names mean, as the clinic agent does. If you connect your own LLM, the same tool result appears in the messages your endpoint receives.
Chain two lookups
A second entry can send what the first captured. Here the first request resolves the caller to a patient id and the second fetches that patient’s next appointment:patient_id is not sent because nothing captured it. If an earlier entry captures a value under the same name as a call fact, a later entry that sends that name sends your value, not the platform’s.
Limits and validation
The API checks the configuration when you save the agent and returns422 naming the failing field:
At call time: each entry has 800 ms, responses are read up to 8 KB, and each captured value is kept up to 512 characters.
Test it
You can watch what the platform sends without writing any code. Point an entry at a request-capture service, name every call fact insends, attach a number, and call it:
Troubleshooting
The request body is empty. The entry’ssends is empty or missing. The platform sends nothing you did not name; add "sends": ["caller_number"] and save the agent again.
The request never arrives. Check that the number is attached to this agent on the same regional host you created it on; agent ids are not shared between agents.assemblyai.com and agents.us.assemblyai.com. Then check your endpoint answers 200 within the timeout to a POST carrying your headers. A 401 from your own auth layer looks the same as a lookup that never ran, because the platform fails open either way.
The greeting did not change. A greeting in the response needs "allow_overrides": ["greeting"] on that entry. A templated greeting needs every {{name}} to resolve to a non-empty value, from the response or from its default.
The number is missing on some calls. The caller withheld their number. The platform omits caller_number rather than sending a placeholder.
The model does not use the values. Name them in the system_prompt and say what to do with them.
Next steps
Connect to Twilio
Attach a phone number so calls reach this agent.
Tools
Let the agent act on the caller’s record during the call.
Webhooks
Get the call’s
from_number and outcome after it ends.