How it fits together
The model decides to call the tool. Our runtime does the rest. You have ten seconds for the answer.Set it up
1
Tell us the URL to call
That is a tool endpoint connection. The URL can be your own server, an n8n workflow with a Webhook trigger, or anything else that answers an HTTPS POST with JSON. On n8n, set the Webhook node to respond when the workflow finishes, not immediately. Add it on the portal’s Webhooks page: a name, the HTTPS URL, and a signing secret. Generate makes a strong secret for you. Store it on your server. Every request is signed with it.Keep the new connection’s id. A tool endpoint only ever receives tool calls and the health check, never call events. Those go to a webhook, and a tool pointed at one fails. I recommend a route of its own for tool calls, so the two never share a handler.
2
Add the tool to your assistant
It goes in That is a create assistant body. On the portal you can create the same tool once under Settings → Tools and assign it to any assistant.
config.agent.tools, next to the prompt that will use it. The execution block is what makes it a webhook tool:3
Tell the prompt to say it's checking
Silence while the tool runs reads as a dropped line. One line in the prompt fixes it:
On web sessions, only tools assigned from the portal’s tool registry reach your endpoint today. A tool written inline on the assistant config runs on phone calls and campaigns. On a web session the model can still pick it and get an error result.
The request
- Signed like event webhooks. Same header, same HMAC over
${t}.${body}with the connection’ssigningSecret. Verify it the way the webhooks page shows. - Only
toolandargs. The body carries no call id, no phone number, no assistant id. If the handler needs to know who is on the line, make it an argument and give the model the value up front as a variable.
The response
Any 2xx with a JSON body. The body lands in the conversation as the tool result, and the model writes its next sentence from it. Write for that reader: smart, in a hurry, about to speak out loud.- Respond within ten seconds. The budget runs from our connect to your response headers. The
timeouton a tool definition is for client tools and does not stretch this. - Answer the question, not the schema. Return the two or three fields the next sentence needs. A big body costs tokens and time on every turn that follows.
- Lead with what happened. A
statusthe model can act on:shipped,not_found,already_booked. For an action with nothing to report,{ "status": "done" }is enough. - Make values speakable. “Thursday”, not an ISO timestamp. “5,999 rupees”, not
599900. The model says it the way you wrote it. - Treat errors as results. Return
{ "status": "error", "message": "no order with that number" }with a 2xx, and the model tells the caller in its own words. A 4xx or 5xx only tells it the tool failed. - Use names a person would quote. The order number, yes. Database keys and internal codes, no. The model handles words far better than opaque ids.
- Steer the wording when it matters. A
sayfield is a hint the model usually follows:{ "status": "pending", "say": "someone will call you back with that" }.
Handle it on your server
A Node handler that verifies, branches, and answers inside the budget:Testing from localhost
We only call public HTTPS URLs.localhost and private addresses are rejected when you save the connection, so put a tunnel in front of your dev server:
https://a1b2c3d4.ngrok-free.app. The url is that address plus your route. Add a tool endpoint with it on the Webhooks page, exactly as in Set it up, with the secret your local server checks. Put the new connection’s id in the tool’s execution, so the agent calls your tunnel instead of the production endpoint:
http://127.0.0.1:4040, headers and body included. Replay one from there while you fix the handler.
- Free ngrok URLs change every restart. Claim ngrok’s free static domain, so the URL you saved keeps working.
- The tunnel is public. Keep the signature check on, even on your laptop.
Before you ship
- Cache what you can. A cache or a fast index answers inside the budget. If the real answer takes longer, return a
pendingstatus and do the work on your side. - Campaign calls carry the same tools. A webhook tool on the assistant runs on every campaign call that assistant makes, next to the goal’s system tools.
- Debug from the session detail. It lists every tool call afterwards, arguments and result included.
