Tools are capabilities you can attach to a persona. When the agent determines it needs to perform an action — like transferring a call, looking up information, or sending a follow-up message — it invokes the appropriate tool.
Kejue provides a set of built-in tools and lets you create custom HTTP tools that call your own APIs.
Tool Scoping: In-Call vs Post-Call
Each tool attached to a persona is assigned to a specific scope that determines when it can be used:
| Scope | When It Runs | Use Case |
|---|
voice:in-call | During the live call, in real-time | Transfer calls, play DTMF tones, look up live data |
voice:post-call | After the call ends, as a background action | Send follow-up messages, update CRM, create tickets |
whatsapp | During a WhatsApp conversation | Send media, templates, or trigger actions |
A tool cannot be enabled for both voice:in-call and voice:post-call at the same time. Choose the scope that matches how you want the tool to be used.
This separation is important because in-call tools run synchronously during the conversation (the agent waits for the result), while post-call tools run asynchronously after the call ends.
These tools interact directly with the call and are only available during live voice calls (voice:in-call).
| Tool | Description |
|---|
hang_up | End the call immediately |
warm_transfer | Transfer the call with context — the AI stays on the line during handoff |
cold_transfer | Transfer the call directly without staying on the line |
leave_voicemail | Leave a voicemail message |
play_dtmf | Play touch-tone digits (for navigating IVR systems) |
These tools interact with the Kejue platform and are available across all scopes.
| Tool | Description |
|---|
get_contact_info | Retrieve information about the current contact |
update_contact_info | Update the contact’s details |
add_contact_note | Add a note to the contact’s record |
set_contact_status | Update the contact’s stage or outcome |
schedule_callback | Schedule a follow-up call at a specific time |
cancel_callback | Cancel a previously scheduled callback |
request_removal | Mark the contact as Do Not Contact |
get_current_time | Get the current time in a specific timezone |
get_datetime | Get the caller’s current date and time |
agent_transfer | Transfer the live call to a different persona via call stages (in-call only) |
create_call | Create a new outbound call to a contact on behalf of a persona |
agent_transfer
Hands the live call off to a different persona mid-conversation. Configure one or more transfer targets — the AI picks among them based on each target’s when_to_use description.
| Field | Type | Description |
|---|
targets | array | Required. List of transfer targets. |
targets[].key | string | Required. Unique slug the AI uses to pick this target (e.g. billing). |
targets[].persona_id | string | Required. ID of the persona to transfer to. |
targets[].voice_config_id | string | Optional. Voice config to use on the new stage; defaults to the target persona’s default. |
targets[].when_to_use | string | Required. Natural-language hint describing when to choose this target. |
{
"tool_name": "agent_transfer",
"channels": ["voice:in-call"],
"config": {
"targets": [
{
"key": "billing",
"persona_id": "prs_01H...",
"when_to_use": "Caller has questions about invoices, refunds, or payments."
},
{
"key": "tech_support",
"persona_id": "prs_02K...",
"voice_config_id": "vc_03L...",
"when_to_use": "Caller is reporting a technical issue with the product."
}
]
}
}
create_call
Lets the agent dial a contact (now or scheduled) on behalf of a persona. The new call runs as a separate session — it does not interrupt the current conversation.
| Field | Type | Description |
|---|
default_persona_id | string | Persona to use when the AI does not specify one. |
default_voice_config_id | string | Optional. Specific voice config (agent) to use; falls back to the persona’s default when omitted. |
default_context | string | Default context shared with the receiving persona if the AI does not supply one. |
allow_persona_override | boolean | If true, the AI may pick a different persona via the persona_id parameter. Defaults to false. |
{
"tool_name": "create_call",
"channels": ["voice:in-call", "voice:post-call"],
"config": {
"default_persona_id": "prs_01H...",
"default_context": "Follow-up call about the contact's inquiry.",
"allow_persona_override": false
}
}
These tools connect with external messaging platforms.
| Tool | Description |
|---|
send_media | Send an image, video, or document via WhatsApp |
send_template | Send a pre-approved WhatsApp template message |
send_text | Send a text message via WhatsApp |
Custom HTTP tools let you connect your agent to any external API. When the agent invokes a custom tool, Kejue makes an HTTP request to your endpoint with the parameters the agent provides.
| Setting | Description |
|---|
| Name | A unique name the agent uses to invoke the tool |
| Description | Explains to the agent what the tool does and when to use it |
| URL | The HTTP endpoint to call |
| Method | HTTP method (GET, POST, PUT, PATCH, DELETE) |
| Authentication | Auth type — none, basic, bearer, or API key |
| Headers | Custom headers to include in the request |
| Timeout | Request timeout (1-60 seconds) |
Parameters
Each parameter you define has a source that controls who provides the value:
- AI Generated (
source: "ai") — the AI fills in the value based on the conversation. You provide a description and type so the AI knows what to supply. These are visible to the AI.
- System Injected (
source: "system") — the value is injected automatically from the execution context (e.g. call ID, contact ID). These are hidden from the AI.
You also have static parameters — fixed values with a constant string, useful for API keys or account identifiers. These are hidden from the AI.
All parameters can be routed to different parts of the HTTP request: the request body, query string, URL path, or headers.
System-Injected Parameters
When you set a parameter’s source to system, you choose which system variable to inject. This lets you pass execution context to your external APIs without exposing it to the AI.
Available System Variables
| Variable | Description |
|---|
call_id | Current call job ID |
workspace_id | Workspace ID |
contact_id | Contact being spoken to |
conversation_id | Current conversation ID |
persona_id | Persona/agent in use |
channel | Channel type (voice, whatsapp, sms, web) |
campaign_id | Campaign ID (if part of a campaign) |
Example
A CRM integration tool that creates a ticket with the call and contact context:
{
"name": "create_ticket",
"description": "Create a support ticket when the customer reports an issue",
"http_config": {
"url": "https://api.example.com/tickets",
"method": "POST"
},
"dynamic_parameters": [
{
"name": "subject",
"description": "Brief summary of the issue",
"param_type": "string",
"required": true,
"source": "ai"
},
{
"name": "call_id",
"source": "system",
"system_variable": "call_id",
"location": "body"
},
{
"name": "customer_id",
"source": "system",
"system_variable": "contact_id",
"location": "body"
}
]
}
The AI only sees subject as a parameter. The call_id and customer_id are injected silently by the system.
If a system variable is not available in the current context (e.g., campaign_id for a non-campaign call), it is omitted from the request.
After creating a tool (or choosing a built-in one), you attach it to a persona with a specific channel scope. The attachment specifies:
- Which tool to attach
- Which channels it’s active on (e.g.
voice:in-call, voice:post-call, whatsapp)
- Any tool-specific configuration (like transfer phone numbers)
Use post-call tools for actions that don’t need to happen during the live conversation. This keeps calls fast and responsive while still letting your agent take follow-up actions automatically.