AI Agents
Policy-bound LLM agent personas for WhatsApp automation — CRUD, completions, prompt-version history, and response logs.
Beta. Published under the
ai_agents capability marked Beta in /openapi.json. The route set and response fields may still expand; existing fields stay stable.Provider API keys are encrypted at rest and never returned.
AIAgentResponse exposes only api_key_suffix. Cross-organization lookups return 404, never 403.Create
POST/v1/ai-agents
Request
| Field | Type | Notes |
|---|---|---|
namerequired | string | len 1..120 |
description | string | len 0..500 |
providerrequired | "anthropic" | "openai" | |
modelrequired | string | len 1..∞ |
api_keyrequired | string | len 10..∞ |
system_promptrequired | string | len 40..∞ |
max_tokens | integer | range 1..4096 |
temperature | number | range 0..2 |
daily_cost_cap_brl | string | pattern: ^\d+(\.\d{1,2})?$ |
handoff_phrases | string[] | |
blocked_topics | object[] | |
blocked_topic_fallback_response | string | len 1..1000 |
max_context_messages | integer | range 1..100 |
max_context_age_seconds | integer | null | |
memory_persistence | "disabled" | "opt_in" | "opt_out" | |
enabled | boolean |
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "ai_agent" | |
namerequired | string | |
descriptionrequired | string | null | |
providerrequired | "anthropic" | "openai" | |
modelrequired | string | |
environmentrequired | "sandbox" | "production" | |
system_promptrequired | string | |
current_prompt_versionrequired | integer | range -∞..9007199254740991 |
max_tokensrequired | integer | range -∞..9007199254740991 |
temperaturerequired | string | |
daily_cost_cap_brlrequired | string | null | |
handoff_phrasesrequired | string[] | |
blocked_topicsrequired | object[] | |
blocked_topic_fallback_responserequired | string | |
max_context_messagesrequired | integer | range -∞..9007199254740991 |
max_context_age_secondsrequired | integer | null | |
memory_persistencerequired | "disabled" | "opt_in" | "opt_out" | |
enabledrequired | boolean | |
api_key_suffixrequired | string | |
archived_atrequired | string<ISO-8601> | null | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
List
GET/v1/ai-agents
Query
| Field | Type | Notes |
|---|---|---|
limitrequired | integer | range 1..100 |
starting_after | string | |
include_archived | boolean |
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "list" | |
datarequired | object[] | |
has_morerequired | boolean | |
next_cursorrequired | string | null |
Retrieve
GET/v1/ai-agents/{agent_id}
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "ai_agent" | |
namerequired | string | |
descriptionrequired | string | null | |
providerrequired | "anthropic" | "openai" | |
modelrequired | string | |
environmentrequired | "sandbox" | "production" | |
system_promptrequired | string | |
current_prompt_versionrequired | integer | range -∞..9007199254740991 |
max_tokensrequired | integer | range -∞..9007199254740991 |
temperaturerequired | string | |
daily_cost_cap_brlrequired | string | null | |
handoff_phrasesrequired | string[] | |
blocked_topicsrequired | object[] | |
blocked_topic_fallback_responserequired | string | |
max_context_messagesrequired | integer | range -∞..9007199254740991 |
max_context_age_secondsrequired | integer | null | |
memory_persistencerequired | "disabled" | "opt_in" | "opt_out" | |
enabledrequired | boolean | |
api_key_suffixrequired | string | |
archived_atrequired | string<ISO-8601> | null | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
Update
PATCH/v1/ai-agents/{agent_id}
Request
| Field | Type | Notes |
|---|---|---|
name | string | len 1..120 |
description | string | null | |
model | string | len 1..∞ |
api_key | string | len 10..∞ |
system_prompt | string | len 40..∞ |
max_tokens | integer | range 1..4096 |
temperature | number | range 0..2 |
daily_cost_cap_brl | string | null | |
handoff_phrases | string[] | |
blocked_topics | object[] | |
blocked_topic_fallback_response | string | len 1..1000 |
max_context_messages | integer | range 1..100 |
max_context_age_seconds | integer | null | |
memory_persistence | "disabled" | "opt_in" | "opt_out" | |
enabled | boolean | |
archived | boolean |
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
objectrequired | "ai_agent" | |
namerequired | string | |
descriptionrequired | string | null | |
providerrequired | "anthropic" | "openai" | |
modelrequired | string | |
environmentrequired | "sandbox" | "production" | |
system_promptrequired | string | |
current_prompt_versionrequired | integer | range -∞..9007199254740991 |
max_tokensrequired | integer | range -∞..9007199254740991 |
temperaturerequired | string | |
daily_cost_cap_brlrequired | string | null | |
handoff_phrasesrequired | string[] | |
blocked_topicsrequired | object[] | |
blocked_topic_fallback_responserequired | string | |
max_context_messagesrequired | integer | range -∞..9007199254740991 |
max_context_age_secondsrequired | integer | null | |
memory_persistencerequired | "disabled" | "opt_in" | "opt_out" | |
enabledrequired | boolean | |
api_key_suffixrequired | string | |
archived_atrequired | string<ISO-8601> | null | |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
Delete
DELETE/v1/ai-agents/{agent_id}
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | |
deletedrequired | "true" |
Run a completion
POST/v1/ai-agents/{agent_id}/completions
Runs one completion against the agent persona. Policy enforcement runs before any provider call.
A completion with
handoff: true returns empty content(no provider call, zero tokens and cost) — the agent deliberately declined to auto-reply so a human can take over. Treat it as a deliberate signal, not a missing reply. A blocked-topic match instead returns the agent's blocked_topic_fallback_response with handoff: false.402 ai_agent_cost_cap_reached is returned synchronously when the agent's daily_cost_cap_brl has already been spent today — before any provider call — and emits ai_agent.cost_cap_reached.Request
| Field | Type | Notes |
|---|---|---|
messagesrequired | object[] | |
contact_phone | string | pattern: ^\+\d{8,15}$ |
trace_id | string |
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "ai_agent_completion" | |
ai_agent_idrequired | string | |
contentrequired | string | |
modelrequired | string | |
tokens_inrequired | integer | range 0..9007199254740991 |
tokens_outrequired | integer | range 0..9007199254740991 |
cost_brlrequired | string | |
handoffrequired | boolean | |
trace_idrequired | string |
List prompt versions
GET/v1/ai-agents/{agent_id}/prompt-versions
Query
| Field | Type | Notes |
|---|---|---|
limitrequired | integer | range 1..100 |
starting_after | string |
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "list" | |
datarequired | object[] | |
has_morerequired | boolean | |
next_cursorrequired | string | null |
List response logs
GET/v1/ai-agents/{agent_id}/response-logs
Query
| Field | Type | Notes |
|---|---|---|
limitrequired | integer | range 1..100 |
starting_after | string |
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "list" | |
datarequired | object[] | |
has_morerequired | boolean | |
next_cursorrequired | string | null |