Answering without a person
An agent attaches to one or more sessions, answers from a knowledge base you control, can call your own HTTP endpoints, and hands off to a human when it should not be the one replying.
Endpoints
Configuring one
{
"name": "Support",
"sessions": ["support"],
"persona": "You are the support agent for Ndoli Electronics in Douala. You are brief and warm.",
"guardrails": "Never quote a price you have not read in the catalogue. Never promise a refund. Never give delivery dates.",
"greeting": "Hi! How can we help?",
"confidence_threshold": 0.6,
"max_replies_per_conversation": 10,
"simulate_typing": true,
"reply_in_customer_language": true
}| Field | Default | Why it matters |
|---|---|---|
persona | — | Who the agent is and how it speaks. It is cached, so keep it stable rather than templating it per conversation. |
guardrails | — | What it must never do. Worth more than a longer persona: this is where you stop it inventing prices and promising refunds. |
confidence_threshold | 0.6 | Below this it hands off rather than guessing. The single most important setting here. |
max_replies_per_conversation | 10 | After this many replies without a human, it hands off regardless. Stops a loop running all night. |
simulate_typing | true | Waits and shows a typing indicator. An instant paragraph is what makes a bot obvious. |
reply_in_customer_language | true | Detects and answers in the language the customer wrote in. |
respect_business_hours | false | Outside them, sends your out-of-hours message and queues for a person. |
transcribe_voice_notes | — | Voice notes are the most common inbound type in several markets. Without this the agent cannot read them. |
effort | low | Reasoning depth. WhatsApp is a fast medium; a considered answer that arrives 20 seconds late reads as broken. |
Knowledge
Documents are chunked, embedded and retrieved per question — the agent answers from what you gave it rather than from what the model happens to remember. Add text directly, upload a file, or point at a URL; priority breaks ties when two documents disagree, which is how you make a price list win over an old blog post.
{
"agent": "8f14e45f-...",
"title": "Returns policy 2026",
"source": "text",
"content": "Returns are accepted within 14 days with a receipt...",
"priority": 10
}Indexing is asynchronous: the document reports pending, then ready with a chunk_count. Edit it and call reindex — a stale knowledge base is the most common cause of an agent confidently quoting last year’s prices.
Tools
A tool is one of your HTTP endpoints, described well enough for the agent to know when to call it. This is what turns “I can tell you about our returns policy” into “your order shipped on Tuesday”.
{
"agent": "8f14e45f-...",
"name": "order_status",
"description": "Look up a customer's order by its reference. Use when the customer asks where their order is.",
"url": "https://example.com/api/orders/{reference}",
"method": "GET",
"parameters": {
"type": "object",
"properties": {
"reference": { "type": "string", "description": "The order reference, like ND-1042." }
},
"required": ["reference"]
},
"requires_confirmation": false
}probe calls the tool with a sample payload and reports what came back. Worth running after any change to your own API, because a tool that started returning 500 makes the agent look broken rather than your service.
Handoff
A handoff parks the conversation in the console inbox and stops the agent replying. The reason tells your team what they are walking into:
| Reason | Meaning |
|---|---|
low_confidence | It did not know, and said so instead of guessing. |
customer_asked | They asked for a human. Always honoured immediately. |
negative_sentiment | The customer is upset. Do not make them repeat themselves. |
tool_confirmation | An action needs a person to approve it. |
reply_limit | Too many replies without a human. Usually a loop. |
out_of_hours | Outside business hours, queued for the morning. |
refused | The model declined — normally a guardrail doing its job. |
error | The agent failed. Check the run. |
Subscribe to ai.handoff to page whoever is on duty, and to ai.replied if you want to log what the agent said somewhere of your own.
Testing before it faces anyone
{ "message": "do you deliver to Buea, and how much?" }Returns the answer, the confidence, the knowledge chunks it used and any tools it wanted to call — without a real conversation. Run your twenty most common questions through it after every change to the persona or the knowledge base.