Custom actions
Build your own tools: the agent collects inputs, calls your endpoint, and speaks the response.
A custom action is a tool you define yourself — like a single Zapier or Make step, but the agent triggers it mid-conversation. You build the exact HTTP request (method, URL, headers, JSON body) using a mix of static values you type and {{placeholders}} the agent fills in. Then the agent calls your endpoint and speaks the response back to the visitor. Create up to ten per agent on the Integrations tab → Custom actions.
The idea that makes this powerful: some of the request is fixed (your Jira project key, an issue type, a currency), and some of it is filled by the AI at call time (a ticket summary it writes, an email it collected). You decide which is which.
1 · Inputs — the values the agent provides
An input is a named value the agent supplies each time it calls the action. Reference it anywhere in the request as {{name}}. Each input has:
- A name — snake_case, e.g.
summary, used as{{summary}}. - A source — the switch that makes this feel like Zapier:
- Collect — the agent gathers it from the visitor in conversation (their email, an order number, a phone number).
- Generate — the agent writes it itself from the conversation (a one-line ticket summary, a tidy description of the problem, a suggested priority).
- A description — tells the agent what to ask for, or how to write it.
- Required or optional — a required input is a gate: the agent won't call until it has a valid value.
Three built-in placeholders are always available without defining an input: {{secret}} (your stored token), {{agent_name}} and {{conversation_id}}.
2 · The request — where static meets dynamic
- Method & URL —
GET,POST,PUT,PATCHorDELETE(HTTPS only). The URL can be fully static, or contain placeholders in the path, e.g.…/issue/{{issue_key}}. OnGET/DELETE, any input not used in the URL is appended as a query parameter. - Authentication — None, Bearer token (sent as
Authorization: Bearer <token>), or Basic (pasteemail:api_token, we base64-encode it — this is exactly what Jira Cloud wants). The token is stored server-side and never returned to the browser. - Headers — any extra headers. Values can use placeholders too, including
{{secret}}. - JSON body (for
POST/PUT/PATCH) — write the body your endpoint expects as literal JSON, and drop{{placeholders}}(inside quotes) wherever the agent should fill a value. Values are safely JSON-escaped, so a quote or newline the AI produces can never break your JSON.
Worked example — raise a Jira ticket
Suppose a visitor reports a bug the agent can't resolve. You want a ticket on the CUS board with a summary and description the agent writes.
- Name:
create_jira_ticket - Description: "Raise a Jira ticket when a visitor reports a bug or issue we can't resolve from the knowledge base. First get a clear picture of the problem."
- Inputs:
summary(Generate — "a short one-line title for the issue") anddescription(Generate — "a clear description of the problem in the visitor's words, with any steps to reproduce"). - Method / URL:
POSThttps://yourco.atlassian.net/rest/api/3/issue - Auth: Basic —
you@yourco.com:your_api_token - JSON body:
{
"fields": {
"project": { "key": "CUS" },
"issuetype": { "name": "Task" },
"summary": "{{summary}}",
"description": "{{description}}"
}
}
The project key and issue type are static — every ticket lands on CUS as a Task. The summary and description are generated by the agent from the conversation. You never scripted a single question; the agent asks what it needs, writes the two fields, and posts the ticket. If you'd rather the agent ask the visitor for a value instead of writing it, set that input's source to Collect.
To guarantee it never calls with something missing, reinforce it in the agent's Instructions: "Never call create_jira_ticket until you understand the problem well enough to write a clear summary."
What your endpoint should return
Reply within 10 seconds. The agent speaks whatever you return:
- JSON with a
message(orreply) string — "Your quote is €120, valid 30 days." — is spoken back through the agent's own voice. - Any other JSON (an object or array without
message) is handed to the agent as data — up to ~1,800 characters — so it can answer from the actual payload. For big collections, prefer an endpoint that returns the one item asked about rather than the whole list. - Anything else is passed through as plain text (first 1,800 characters).
- A non-2xx status makes the agent apologise gracefully — the visitor never sees a raw error.
Test it before you ship it
Open the agent's Playground tab, pick your action, type the inputs by hand and run it — you'll see the exact text the model would receive, including your endpoint's real response. The lead webhook can be tested the same way.