AI Agent API
Talk to your domain's data in natural language: the AI Data Agent turns your uploaded schemas into callable tools, runs a reasoning loop over them, and returns structured results — as a single response or a live SSE stream.
Overview
curl -X POST https://api.supero.dev/ai/v1/chat \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "Show me all customers with tier '\''enterprise'\''",
"mode": "auto"
}'⚠️ Bearer JWT only
ℹ️ The agent carries your caller's authority and adds none of its own
Chat: POST /ai/v1/chat
| Field | Type | Required | Notes |
|---|---|---|---|
| message | string | yes | 1–10,000 characters |
| session_id | string | no | Continues an existing conversation. A new session is generated if omitted. |
| provider | string | no | Advanced: pin this turn to a specific upstream AI provider. Omit it to use your domain's default. |
| max_iterations | integer | no | 1–10, default 5. Caps how many tool-call rounds the agent can take in one turn before it must respond. |
| stream | boolean | no | Default false. Set true for a Server-Sent Events response instead of a single JSON body — see Streaming below. |
| mode | string | no | auto (default) | single | loop — see Routing modes below. |
Routing modes
| mode | Behavior | Write confirmations |
|---|---|---|
| auto | Default. Uses the multi-step agentic loop when it is available in your deployment, falling back to a single-shot pass if it is not. The fallback is silent. | Yes, when the loop runs the turn |
| single | Always uses a single reasoning pass: the agent can still call tools, but does not plan across multiple turns. | No — tools execute as soon as the model calls them |
| loop | Forces the multi-step agentic loop. Returns 503 if the loop engine is not available rather than silently falling back. | Yes, always |
⚠️ mode: single executes writes without an approval step
Non-streaming response
{
"response": "I found 3 enterprise customers:\n\n1. Acme Corp (UUID: abc-123)\n2. TechGiant Inc (UUID: def-456)\n3. Global Systems (UUID: ghi-789)",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"tool_calls": [
{
"name": "search_customer",
"arguments": { "filters": { "tier": "enterprise" } },
"result": { "success": true, "count": 3 }
}
],
"usage": { "input_tokens": 612, "output_tokens": 84, "total_tokens": 696 },
"error": null,
"correlation_id": "a1b2c3d4"
}| Field | Meaning |
|---|---|
| response | The agent's reply text. If the turn paused for approval before taking an action, this instead describes what it wants to do and names the gate_id to confirm with. |
| session_id | The conversation this turn belongs to — pass it back on the next call to continue. |
| tool_calls | Array of { name, arguments, result } for every tool the agent invoked this turn, or null if it answered without calling any. |
| usage | Token counts for this turn's AI calls: input_tokens, output_tokens, total_tokens. May be null. |
| files | Present for tools that produce downloadable output (e.g. an export or generated document). |
| error | Populated when something went wrong; response still carries a human-readable explanation. |
| correlation_id | Trace id for this request — include it when contacting support about a specific call. |
ℹ️ What differs in mode: single
Streaming responses
curl -N -X POST https://api.supero.dev/ai/v1/chat \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"message": "Create a task called Follow up with Acme",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"stream": true
}'| event type | Shape | Meaning |
|---|---|---|
| content | { type, text } | A chunk of the agent's reply text. Concatenate chunks in order to build the full response. |
| tool_call | { type, name, arguments } | The agent is invoking a tool. |
| tool_result | { type, name, result } | That tool finished; result carries success, and, when relevant, count / items / error. |
| file | { type, filename, mime_type, file_data, size } | A downloadable artifact (export, generated document) is ready. |
| error | { type, message } | Something went wrong. The stream ends after this event. |
| done | { type, session_id } | The turn is complete — no further events follow. Store session_id for the next message. |
data: {"type": "content", "text": "I'll create that task now."}
data: {"type": "tool_call", "name": "create_task", "arguments": {"title": "Follow up with Acme"}}
data: {"type": "tool_result", "name": "create_task", "result": {"success": true, "count": 1, "items": [{"uuid": "9c1f2a3b-..."}], "error": null}}
data: {"type": "content", "text": "Done — I created the task."}
data: {"type": "done", "session_id": "550e8400-e29b-41d4-a716-446655440000"}💡 Mapping events to UI callbacks
Filter grammar
// 1) Flat equality
{ "country": "IN", "tier": "enterprise" }
// 2) Operator form
{ "amount": { "gt": 120 } }| Operator | Argument | Matches |
|---|---|---|
| eq / ne | a value | Equal / not equal. |
| gt / gte / lt / lte | a value | Ordered comparison, for numbers and ISO-8601 dates. |
| in / not_in | an array | Value is (or is not) one of the listed values. |
| between | a two-element array | Inclusive range: ["2026-02-01", "2026-02-28"]. |
| contains | a string | Substring match. |
| starts_with / ends_with | a string | Prefix / suffix match. |
| regex | a pattern string | Regular-expression match. |
| exists | true or false | The field is set / is not set. |
Combining conditions
{
"op": "and",
"conditions": [
{ "country": "IN" },
{ "created_at": { "gte": "2026-01-01" } },
{ "status": { "in": ["SCHEDULED", "PENDING"] } }
]
}Sorting and paging
| Argument | Type | Notes |
|---|---|---|
| sort | array | [{ "field": "<name>", "order": "asc" | "desc" }] — applied in order. |
| limit | integer | Default 50, maximum 1000. A larger value is clamped, not rejected. |
| offset | integer | Default 0. Page through results beyond the limit. |
{
"filters": {
"op": "and",
"conditions": [
{ "visit_date": { "between": ["2026-02-01", "2026-02-28"] } },
{ "amount": { "gt": 120 } }
]
},
"sort": [{ "field": "visit_date", "order": "desc" }],
"limit": 50,
"offset": 0
}ℹ️ Conventions
⚠️ filters is for record selection only
Confirmation gates in loop mode
How the pending gate reaches you
| Transport | Where the gate appears | Human-readable text field |
|---|---|---|
| SSE stream | A confirmation event carrying gate_id, tool_name, tool_arguments. | prompt_message |
| Non-streaming chat | HTTP 200. response describes the pending action and names the gate_id; there is no separate status field on this body. | — (inside response) |
| GET /ai/v1/loop/session/{id} | status is waiting_confirmation and pending_confirmation holds gate_id, tool_name, tool_arguments, affected_records, expires_at. | prompt |
⚠️ One field, two names
Resolving a gate
curl -X POST https://api.supero.dev/ai/v1/loop/confirm \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"gate_id": "gate_9c1f2a3b",
"approved": true
}'| Field | Type | Required | Notes |
|---|---|---|---|
| session_id | string | yes | The session holding the pending gate. |
| gate_id | string | yes | From the confirmation event or pending_confirmation. |
| approved | boolean | yes | false rejects the pending call and resumes the session without executing it. |
| modified_arguments | object | no | Approve with edits: run the pending tool with these arguments instead of the ones the model proposed. |
| user_message | string | no | Optional note carried into the resumed turn — useful for "yes, but only the ones from March". |
Loop session routes
| Method | Path | Purpose |
|---|---|---|
| GET | /ai/v1/loop/session/{session_id} | Session status, turn count, metrics, and any pending_confirmation. |
| POST | /ai/v1/loop/session/{session_id}/close | Close the session and drop any pending gate and working context. Idempotent — safe to call more than once. |
ℹ️ Gates expire after five minutes
Tools API
The filter grammar
| Operator | Meaning |
|---|---|
eq / ne | Equal, not equal. |
gt / gte / lt / lte | Numeric and date comparison. |
in / not_in | Membership in a list of values. |
between | Inclusive range — takes two values. |
contains / starts_with / ends_with | Substring matching on a string field. |
regex | Pattern match on a string field. |
exists | Whether the field is present at all. |
{
"filters": {
"op": "and",
"conditions": [
{ "field": "status", "op": "in", "value": ["open", "in_progress"] },
{ "field": "created_at", "op": "gte", "value": "2026-08-01" }
]
},
"sort": [{ "field": "created_at", "order": "desc" }],
"limit": 50,
"offset": 0
}ℹ️ limit defaults to 50 and caps at 1000
| Method | Path | Purpose |
|---|---|---|
| GET | /ai/v1/tools | List every schema-generated tool available for your domain, with its parameter schema. |
| POST | /ai/v1/tools/refresh | Clear the cached tool list and regenerate it. Call this after uploading or changing schemas. |
| POST | /ai/v1/tools/{tool_name}/invoke | Run one tool directly with explicit arguments — deterministic, no AI reasoning step involved. |
curl https://api.supero.dev/ai/v1/tools \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"domain": "acme",
"tools": [
{
"name": "search_customer",
"description": "Search for customer records. Filters support comparison/range/set operators.",
"parameters": {
"type": "object",
"properties": {
"filters": { "type": "object" },
"sort": { "type": "array" },
"limit": { "type": "integer", "default": 50 },
"offset": { "type": "integer", "default": 0 }
}
},
"schema_name": "customer",
"operation": "search",
"namespace": "billing",
"obj_type": "customer"
}
],
"count": 1
}| Field | Meaning |
|---|---|
| name | The tool name the agent calls and the one you put in the invoke path. Named {operation}_{namespace}_{type}, or {operation}_{type} in the default namespace. |
| description | The text handed to the model, including the filter grammar and this entity's filterable fields with their types and enum values. |
| parameters | JSON Schema for the arguments. For search, that is filters, sort, limit (default 50, max 1000) and offset. |
| schema_name / obj_type | The schema this tool was generated from, and the normalized object type it operates on. |
| namespace | Present when the schema is not in the default namespace. |
| parent_type | Present when the entity is a child type that must be created under a parent. |
ℹ️ The agent has tools this listing does not show
Invoking a tool directly
curl -X POST https://api.supero.dev/ai/v1/tools/search_customer/invoke \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"arguments": {
"filters": { "tier": "enterprise", "created_at": { "gte": "2026-01-01" } },
"sort": [{ "field": "created_at", "order": "desc" }],
"limit": 50
}
}'{
"success": true,
"result": {
"operation": "search",
"schema": "customer",
"items": [ { "uuid": "abc-123", "name": "Acme Corp", "tier": "enterprise" } ],
"count": 1,
"total": 1
},
"tool_name": "search_customer",
"error": null
}ℹ️ A tool_name that doesn't exist
Sessions API
| Method | Path | Purpose |
|---|---|---|
| GET | /ai/v1/sessions | List active sessions in your domain/project/tenant scope. |
| POST | /ai/v1/sessions | Explicitly create a new session before the first message. |
| GET | /ai/v1/sessions/{id} | Get session metadata plus its full message history. |
| DELETE | /ai/v1/sessions/{id} | Delete a session and its stored history. |
# Create a session
curl -X POST https://api.supero.dev/ai/v1/sessions \
-H "Authorization: Bearer $ACCESS_TOKEN"
# Get its history
curl https://api.supero.dev/ai/v1/sessions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $ACCESS_TOKEN"
# Delete it
curl -X DELETE https://api.supero.dev/ai/v1/sessions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $ACCESS_TOKEN"{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"domain": "acme",
"project": "proj-uuid-123",
"project_name": "sales",
"tenant_uuid": "tenant-uuid-456",
"tenant_name": "northwind",
"messages": [
{ "role": "user", "content": "Show me enterprise customers", "timestamp": "2026-07-18T10:00:00Z" },
{ "role": "assistant", "content": "I found 3 enterprise customers...", "timestamp": "2026-07-18T10:00:02Z", "tool_calls": [ { "name": "search_customer", "arguments": { "filters": { "tier": "enterprise" } } } ] }
],
"message_count": 2,
"created_at": "2026-07-18T10:00:00Z",
"updated_at": "2026-07-18T10:00:02Z"
}Errors and status codes
| Status | Meaning |
|---|---|
| 400 | Bad request — e.g. your JWT doesn't carry a resolvable domain. |
| 401 | Missing, malformed, or expired Authorization: Bearer token. |
| 402 | Your AI agent usage allowance is exhausted for this period, where usage enforcement is enabled for your account — see Plans & Billing. |
| 404 | The tool name or session id in the path doesn't exist. |
| 422 | Request body failed validation (e.g. message over 10,000 characters, max_iterations out of range). |
| 503 | The agent, the loop engine, or the tool executor backing this endpoint isn't available right now — retry shortly. mode: loop returns this rather than falling back to a single pass. |
{
"error": "authentication_error",
"message": "Authorization header with Bearer token required",
"details": {}
}{
"detail": {
"error": "quota_exceeded",
"upgrade_required": true,
"meter": "agent.prompt",
"limit": 10,
"used": 10,
"remaining": 0,
"message": "10 free AI queries this month used — add the AI Agent add-on or upgrade your plan."
}
}⚠️ Do not render an unexpected error string to end users
🚨 Non-streaming errors don't always come back as an HTTP error
Next steps
- •AI Data Agent — the builder-facing guide: what the agent can do, how it turns a question into a filter, and how access control bounds it
- •API Overview & Conventions — base URL, auth schemes, and the response envelope shared across the whole platform
- •CRUD Endpoints — the underlying data endpoints the agent's generated tools call on your behalf
- •Querying & Pagination — the same filtering concepts applied directly to the data API
- •Schema Reference — how fields, references, and parent_type shape the tools this API generates for you
On this page