Flow Functions
Define reusable HTTP functions that the LLM can invoke during a call.
Flow functions let the LLM call your backend during a conversation. You define the HTTP request shape once, attach the function to one or more agents, and the bot executes it server-side when the LLM decides to invoke it.
Use cases: look up an order, check availability, create a ticket, verify a customer — anything where the conversation needs live data or needs to cause a side effect in your system.
Function types
Agent nodes accept two function types, discriminated by the type field:
| Type | Use |
|---|---|
builtin | Bot-provided primitives. Only end_call is available. |
http_request | An HTTP call to your backend. References a flow function by config.functionId. |
builtin is the default when type is omitted. http_request requires config.functionId to point at an active flow function in the same account.
Request shape
A flow function describes a structured HTTP request with three independent parameter locations: path, query, and body.
{
"name": "create_order",
"description": "Create a new customer order",
"request": {
"method": "POST",
"url": "https://api.example.com/customers/{customerId}/orders",
"pathParams": { "type": "object", "properties": { "customerId": { "type": "string" } }, "required": ["customerId"] },
"queryParams": { "type": "object", "properties": { "source": { "type": "string", "enum": ["phone", "web"] } } },
"body": { "type": "object", "properties": { "sku": { "type": "string" }, "quantity": { "type": "integer" } }, "required": ["sku", "quantity"] }
},
"paramBindings": {
"customerId": { "source": "call_context", "contextKey": "caller.contact_id", "onNull": "reject" },
"source": { "source": "static", "value": "phone" }
},
"webhookHeaders": { "Authorization": "Bearer ..." },
"timeoutMs": 5000
}Method and URL
| Field | Rules |
|---|---|
method | One of GET, POST, PUT, PATCH, DELETE. |
url | Fully qualified. May contain {placeholder} tokens. Every placeholder must have a matching property in pathParams, and every pathParams property must appear as a placeholder. Values are percent-encoded at dispatch to prevent path injection. |
Parameter locations
Each location (pathParams, queryParams, body) is an independent JSON Schema object. Parameter names must be unique across all three — customerId cannot appear in both pathParams and body.
| Type | pathParams | queryParams | body |
|---|---|---|---|
string (with optional enum) | ✓ | ✓ | ✓ |
number / integer (with optional enum) | ✓ | ✓ | ✓ |
boolean | ✓ | ✓ | ✓ |
array — must declare items | — | — | ✓ |
object — must declare properties | — | — | ✓ |
Nested object / array | — | — | ✓ (max depth 5) |
Path and query parameters are restricted to primitives because they flatten into URL strings. Body supports nested structures up to depth 5 to match OpenAI Structured Outputs.
Validation keywords like format, minimum/maximum, pattern, minLength/maxLength pass through to JSON Schema enforcement at dispatch time.
Parameter bindings
paramBindings controls where each parameter's value comes from. Keys match property names at the top of pathParams, queryParams, or body. Dotted paths (body.customer.id) are not supported — bind the whole top-level object instead.
| Source | Shape | Behavior |
|---|---|---|
llm | { "source": "llm" } | The LLM extracts the value from conversation. Default when no binding is declared. |
call_context | { "source": "call_context", "contextKey": "<key>", "onNull": "reject" | "fallback_to_llm" } | The value is resolved from the active call's context (caller identity, variables, etc.). Never shown to the LLM. |
static | { "source": "static", "value": <any> } | A fixed value baked into every invocation. Never shown to the LLM. |
onNull behavior
When a call_context binding resolves to null:
| Mode | Effect |
|---|---|
reject | The function is hidden from the LLM for that call — it won't appear as a tool. Use for parameters without which the call can't function (e.g. authenticated user ID). |
fallback_to_llm | The parameter is exposed to the LLM and extracted from conversation instead. |
Visibility rules
- Parameters bound to
call_contextorstaticare stripped from the LLM's tool schema. The model never sees them. - Parameters with no binding or
{ "source": "llm" }appear in the LLM's tool schema and are extracted from conversation. - At dispatch, the bot merges LLM arguments with context/static values and splits them back into
pathParams/queryParams/bodybuckets.
Headers and timeout
| Field | Notes |
|---|---|
webhookHeaders | Map of HTTP headers sent with every invocation. Encrypted at rest with AES-256-GCM. Write-only — the API never returns header values, only a hasWebhookHeaders boolean. Pass null on update to clear. |
timeoutMs | Request timeout in milliseconds. Range: 100–30000. Default: 5000. |
Execution model
Flow functions run server-side:
- At publish time, the backend resolves every
http_requestreference to its current function definition.staticandcall_contextbindings are stripped from the LLM schema. - Per call, any
call_contextvalues are resolved from the live call state. IfonNull: rejecttrips, the function is removed from the tool list for that call. - When the LLM invokes the function, the bot publishes a NATS request to the function executor. The executor injects
static/call_contextvalues, templates URL placeholders, sends the HTTP request, and returns the response to the bot. - The bot feeds the result back to the LLM as the tool result.
Transitions and failure
If the function definition includes transitionTo, the agent transitions to the target node regardless of whether the HTTP call succeeded. On failure the LLM receives the error as the tool result and can reference it from the new node's context. This makes functions usable as deterministic handoff triggers even when the downstream service is flaky.
Attaching to an agent
Add the function to an agent's functions array using type: "http_request" and reference the function ID:
{
"type": "http_request",
"name": "create_order",
"description": "Create a new customer order",
"config": { "functionId": "550e8400-e29b-41d4-a716-446655440000" },
"transitionTo": "ConfirmationAgent"
}The agent's LLM decides when to invoke the function based on the description and the JSON-Schema-derived tool signature. Multiple agents can reference the same function.
Validation
The backend rejects http_request function references at publish time with these error codes:
| Code | Condition |
|---|---|
invalid_function_type | type is not builtin or http_request. |
missing_function_id | http_request without config.functionId. |
unknown_function_id | functionId does not exist or is not active in this account. |
unknown_builtin | builtin with a name other than end_call. |
Request-shape validation at flow-function create/update time includes: method allowlist, unique parameter names across locations, URL placeholders matching pathParams, JSON Schema type/location constraints, and timeout range.