Lifecycle Hooks
A lifecycle hook runs automatically around a call, without the agent deciding to call it.PRE_CALLhooks run before the agent speaks. Use them to fetch context — look the caller up in your CRM, pull their order history — and expose the result to the prompt.POST_CALLhooks run after the call ends. Use them to push the outcome somewhere — log an activity, append a row, open a ticket.
These endpoints return a bare object (
{ "hook": … }, { "hooks": [ … ] }) and a bare
{ "error": … } on failure, rather than the success/data envelope used elsewhere in this API.
Validation failures return 422 with an issues array naming each bad field.Create a hook
A hook needs a source: either an integration (toolSlug plus toolFn) or one of your own custom
functions (functionId).
position and the hook is appended to the end of its stage.
input is a template
Values in input are substituted from the call’s variables and from the output of hooks that ran
earlier in the same stage. So a second hook can consume the first one’s result.
exposeAs publishes the result to the prompt
"exposeAs": "lead" makes the hook’s response available as {{lead.FirstName}},
{{lead.Company}}, and so on inside the agent’s prompt. It is pre-call only — a post-call hook has
no prompt left to feed — and must be unique among that agent’s pre-call hooks.
Response mapping
exposeAs keeps the whole response under one name, so a deep field needs a long path in the prompt:
{{account.data.var_business_name}}. responseMap lifts chosen fields out to top-level variables
instead, so the prompt can say {{business_name}}.
Each row names a path in the hook’s response and the variable it is published as:
Business: Sunrise Bakery (active). The long form, {{account.data.var_business_name}},
keeps working too.
Rules:
- Pre-call only. The hook must have
stage: "PRE_CALL"and anexposeAs. APATCHthat clearsexposeAswhile rows remain is rejected. - Not on
lookup_row. A Google Sheets lookup already maps its columns ininput.columns. - At most 200 rows.
pathis a dot path into the response. It is 1–200 characters with no empty segment (a..b). List items are read by index, e.g.items.0.sku.variablematches^[a-z_][a-z0-9_]*$and appears once per hook.- Blank values never override. If a path comes back
"",nullor missing, the variable is left as it was.0andfalsedo count. - A mapped name beats a per-call variable of the same name. If you pass
variables: { "business_name": "…" }at call start and the hook mapsbusiness_namewith a value, the hook’s value wins. When two hooks map the same name, the later one wins. - If the hook fails, nothing is mapped. The variables keep their per-call values, if they had any.
PATCH with "responseMap": null or [] removes every row.
Failure handling
All pre-call hooks share a 5-second wall budget. Two hooks at
timeoutMs: 3000 can exhaust it,
and every remaining hook in the stage is skipped and recorded as failed — so keep the sum of your
pre-call timeouts under 5000.
Preview before you ship
A mistyped template key does not error; it renders empty and the agent quietly gets nothing. Check it first:variables to render against
built-in samples.
Ordering
Hooks run by ascendingposition within their stage. To change the order, send the stage’s hook IDs
in the order you want:
Turn one off without deleting it
PATCH with enabled: false leaves the hook and its position intact:
DELETE while debugging — deleting loses the configuration and the ordering.
stage cannot be changed on an existing hook. Delete it and create it on the other stage.
Debugging
When a hook does not seem to fire,GET /integration-logs has the audit row —
what was sent, what came back, the upstream status code, and how long it took:
Next steps
Custom Functions
Tools the agent chooses to call mid-conversation.
Pre-call Variables
What a pre-call hook can read from and write to.
B2B2B Customers
Connect integrations on behalf of your own customers.
API Reference
Every hook field and error code.