Overview
Use this path if you’re not on Node.js, or if you need to send data the SDK doesn’t capture. The ingest endpoint accepts conversations and agent definitions in one of five formats.Endpoint
Authentication
Pass your agent’s API key as a Bearer token.cl_ and managed from your agent’s Settings page in the dashboard.
Request format
The top-level request body:Required
At least one ofconversations or agentDefinitions must be present. Empty payloads are rejected.
Optional
Pin the request to a specific agent. Validated against the API key. If omitted, the key’s default agent is used.
Only set this when forwarding provider request/response bodies untouched. One of
anthropic, openai_chat, openai_responses. Omit to use the default shape shown in the examples. See Format selector below.Array of conversation objects. Max 1,000 per request.
Array of agent definition objects. Max 100 per request.
Conversation object
Required
Array of message objects. Min 1, max 10,000.
Optional
Your stable id for this conversation. 1-255 characters. Used to link conversations across ingest calls (for multi-turn sessions) and to deduplicate.
Grouping id for related conversations. Max 255 characters.
Link this conversation to a specific agent definition version. Used when analyzing against a known spec.
Arbitrary key-value data. Surfaces in the dashboard under the conversation.
Structured trace information. See Trace data below.
Message object
Required
Typically
user, assistant, system, or tool. Any non-empty string is accepted.Either a plain string (max 100 KB) or an array of content blocks (1-1,000 blocks).
Optional
When the message was produced. Used for ordering when multiple messages share the same logical turn.
Agent definition object
Required
Human-readable name. 1-500 characters. Combined with
type to dedupe versions.One of
system_prompt or tool_schema.The definition text. 1 byte to 100 KB.
Content blocks
Messages support either a plain string or typed content blocks. Block types mirror Anthropic’s:| Type | Shape |
|---|---|
text | { type: "text", text: string } |
thinking | { type: "thinking", thinking: string } |
tool_use | { type: "tool_use", id?: string, name: string, input: unknown } |
tool_result | { type: "tool_result", tool_use_id?: string, content?: string | Array<{type:"text", text:string}>, is_error?: boolean } |
| other | { type: string, ...anything } — unknown block types pass through |
Trace data
When you have structured trace info (tool calls with outputs, retrieval results), attach it so analysis has more to work with.{ type, timestamp, duration?, metadata? }[]. Generic trace events.{ name, input, output?, error?, timestamp?, duration? }[]. One entry per tool invocation.{ query, chunks[], sourceDocIds?, timestamp? }[]. RAG retrieval results.Steps
When a conversation is one call inside a multi-agent orchestration, attach astep so calado can render the run as a tree and attribute behavior to the right sub-agent. Omit it for single-agent conversations.
Stable id for this step within the run.
Id of the parent step. Omit for the root step. Cannot equal
step.id.Human-readable role for this sub-agent, e.g.
orchestrator or flight_search.The sub-agent’s dynamic prompt or tool schema for this call — the “how it should work” side calado analyzes this step against. String or object, up to 100 KB. Omit it and the step is analyzed against the agent’s static definition.
Format selector
Theformat field tells calado how to parse the conversations array when you’re forwarding provider bodies untouched. Omit it to use the default shape shown in the examples.
| Value | When to use |
|---|---|
anthropic | You’re forwarding Anthropic messages.create request/response bodies untouched. |
openai_chat | You’re forwarding OpenAI chat.completions request/response bodies. |
openai_responses | You’re using OpenAI’s newer responses.create API. |
Example
Response
Success (202 Accepted)
| Field | Meaning |
|---|---|
conversations.accepted | Stored with pending classification. Analysis runs when you click Run Analysis in the dashboard. |
conversations.skipped | Rejected for structural reasons (see warnings). |
conversations.failed | Stored, but analysis will not run. |
agentDefinitions.created | New definitions stored (content hash changed or new). |
agentDefinitions.unchanged | Content hash matched an existing version. |
warnings | Non-fatal per-item messages. |
Error
| Code | Meaning |
|---|---|
400 Bad Request | Payload failed schema validation. Body contains Zod error details. |
401 Unauthorized | Missing, malformed, or invalid API key. |
403 Forbidden | Key exists but doesn’t have access to the specified agentId. |
413 Payload Too Large | Request body exceeds 5 MB. |
429 Too Many Requests | Rate limited. Back off and retry. |
5xx | Server error. Safe to retry with exponential backoff. |
Batch limits
| Limit | Value |
|---|---|
| Request body size | 5 MB |
| Conversations per request | 1,000 |
| Agent definitions per request | 100 |
| Combined conversations + agent definitions | 1,000 |
| Messages per conversation | 10,000 |
| Content blocks per message | 1,000 |
| Message content | 1 MB |
Agent definition content | 100 KB |
| Tool schemas per conversation (adapter-extracted) | 256 |
Error handling
Retry on5xx and network errors only, with jittered exponential backoff. 4xx responses are permanent and should not be retried.
On repeated 401 responses, stop retrying and surface the error to your operator. The key is wrong, and retrying won’t fix it.
Next: serverless patterns
Flush the queue before your function freezes.