How it works
1
Create the function in the dashboard
Open the Integrations tab, choose the phone number, open Custom Functions, and add a function. Custom functions are configured per phone number. You give it a name, a description (the agent reads this every turn), an HTTPS URL, and a parameter schema.
2
The agent sees it as a tool
On every conversation turn, the agent is aware of every active function on the agent. Based on the description you wrote, the agent decides when to call it.
3
Engine calls your URL
When the agent triggers a function, the engine makes an HTTP request to your URL with a JSON body containing the call context, what the agent extracted, and 14 dynamic variables.
4
Your endpoint replies with JSON
You return a JSON response. The engine reads the
result field (if present) and feeds it back to the agent as the tool result.5
The agent responds to the caller
The agent uses the data you returned to compose the next reply, spoken naturally to the caller via TTS.
What your endpoint receives
Every request from the engine looks like this:
The only header you receive is
User-Agent: Nixflex-VoiceEngine/1.0. There is no signature header yet (see Authentication below).
The 14 dynamic variables
These are always present invariables on every request. They cover everything the engine knows about the call.
There is no
caller_name variable. Speech-to-text often mishears names. If a name matters to your flow, instruct the agent in its system prompt to ask the caller to spell it and confirm it back before calling the function.What to send back
Your endpoint should respond with JSON. Two valid shapes: Recommended — wrap the data in aresult field:
result and feeds just that to the agent. Cleaner context, faster agent responses.
Also accepted — return the data at the top level:
result field, the engine stringifies the whole body and feeds it to the agent.
Status codes
Errors never crash the call — the agent always handles them gracefully.
Writing a good description
This is the most important field on the whole function. The agent reads your description on every conversation turn to decide whether to call the function. A vague description means the agent either never fires it, or fires it at the wrong time. Bad:URL and header variable substitution
Even though all 14 variables are sent in the request body automatically, sometimes you need them in the URL itself (REST APIs) or in a header (authentication). Use{{variable_name}} syntax in the URL or Headers fields.
URL substitution
Header substitution
Headers also support substitution, useful for passing call context through to upstream services that expect it in headers.When to use which
Most modern APIs use the third pattern, so most developers leave the URL static and just read variables from the body. URL substitution is for REST-style and GET endpoints.
Substitution only works in URL and Headers. It does not substitute in the description, name, or parameter schema fields.
Authentication
Custom function endpoints are public by default — the engine identifies itself withUser-Agent: Nixflex-VoiceEngine/1.0 but does not yet sign requests.
For now, the recommended pattern is a bearer token in the Headers field:
Request signing (HMAC with rotating secrets) is on the roadmap. When it lands, the engine will send an
X-Nixflex-Signature header you can verify with a per-agent secret. Until then, use bearer tokens in Headers.Mentioning functions in the prompt
You can let the agent discover when to use functions purely from the descriptions, but adding an Actions section to the system prompt makes triggering more reliable:Common use cases
Calendar lookups
Check availability before promising a slot.
CRM record fetches
Pull customer history when they call.
Booking creation
Create the booking in your system once confirmed.
Inventory checks
Verify a product is in stock before quoting.
Order status
“Where’s my order?” — look it up and reply naturally.
Payment links
Generate a Stripe checkout URL and text it via
[SEND_SMS:].Speak while running
Some functions call a slow API, or the agent may call one without saying anything first. To avoid the caller hearing silence during the wait, set a Speak while running line (speak_during) on the function - a short phrase the engine speaks as the function runs.
Limits and constraints
Limitations
- Functions are triggered by the agent during conversation — you cannot trigger them externally.
- The engine does not retry failed functions automatically. Make your endpoint idempotent if the agent might call it twice.
- Function calls happen per conversation turn. There is no streaming partial results back to the agent.
- The tool-aware path is slightly slower than the no-functions path because it waits for the full agent response (including tool calls) before speaking.
Testing your function
The dashboard has a Test Webhook button on every function. It sends a request to your URL with:- Fake
caller_phone(+44XXXXXXXXXX) - Fake
business_phone(+44XXXXXXXXXX) - Fake
call_id(test_<timestamp>) - Real date/time variables (from your agent’s timezone setting)
- Args you type into the Sample Args field
call_id.
For more standardised integrations (Stripe, Salesforce, Google Calendar etc.), MCP server support is on the roadmap.