Skip to main content
Send a message and get the agent’s reply. The agent is identified by your access token, and the conversation thread is created automatically on the first message — there is no separate “create thread” call. Two ways to receive the reply: Runtime v1 agents additionally accept a bidirectional WebSocket session at wss .../messaging/v1/session.

Send a message

cURL

POST /messaging/v1/messages

Request body

string
required
The message to send to the agent.
string
required
Your identifier for the end user. New threads are attributed to this user.
string
Continue an existing thread. Omit it to start a new one — the created thread’s id is returned in the response.
string
Signed image URL for vision input.
object
Per-message values for the agent’s configured context variables — a flat object of key/value pairs. See Agent variables below.
string
Advanced — pins the turn to a specific runtime build (e.g. 0.8.0). Normally omit it: the platform uses the agent’s own build. Ignored by runtime v1 agents. Also accepted on the stream and rerun endpoints.
boolean
default:"false"
When true, the reply carries its reasoning trace as message.trace_info — the same object the trace endpoints return, so no second request is needed. Off by default: a trace can be large. Also accepted on the stream (the final message event carries it) and rerun endpoints.

Response

string
The thread the message landed on — newly created when the request omitted thread_id. Pass it back to continue the conversation.
object
The agent’s reply: id (the interaction id — used for reruns and traces), text, cards, followup_suggestions, token counts, and trace_info (the reasoning trace, present only when the request set include_trace).

Cards

When the agent surfaces entities — products, bookings, search results — the reply carries them as cards. Each card is the same entity in two self-contained representations, so you pick the one that fits your stack:
string
The card as a ready-to-render JSX string — drop it straight into a React UI.
object
The card as structured JSON — build your own UI in any framework (Vue, Angular, mobile, …). entity is a flat key–value map of the card’s fields; sub_entities holds nested groups such as product variants, each with a name and a list of items in the same key–value shape.
Whether the agent flagged this card as its top recommendation.
number
The card’s position in the reply.
string
The card’s authored title. Optional; may be null.
string
Which of the agent’s capabilities produced the card — useful for picking a widget template. Optional; may be null.
string
The specific record the card is about, if any. Optional; may be null.
Example card
The keys inside entity and sub_entities[].items are defined by your agent’s card templates — treat them as data, not as a fixed schema.

Agent variables

agent_variables is how you hand the agent structured data alongside — or instead of — the caller’s words: who is signed in, which account they are on, what your own systems already know. It is a flat object of key/value pairs, and values may be any JSON type.

What the agent does with them

The keys are not free text as far as the agent is concerned. They arrive as the agent’s context at the opening of the session — the values its program declares that the host will supply, rather than ask the caller for. That has two consequences worth designing around:
  • A key the program does not declare is ignored. Sending customer.tier does nothing unless the agent’s program declares it and says it comes from the host. Adding a new variable is a change to the agent, not only to your request.
  • A value the program requires must be sent. When the program declares a variable as required context, a request that omits it is rejected rather than run with a gap. This is deliberate: the agent never guesses at an identity it was supposed to be given.
Use them for anything the caller should not have to state and should not be trusted to state — the signed-in user’s id, the account they are viewing, the entitlement your backend already verified. A fact that arrives this way carries the authority of your system; a fact the caller types carries only theirs, and the agent’s rules can tell the two apart.

Where they are accepted

rerun does not take them — a rerun replays an existing interaction, so it keeps the context the original turn ran with.
There is no request field for choosing a capability. Which job the agent does is decided by its program from the message and the context it was given — so if you need a particular behavior to trigger, pass the fact that distinguishes the situation and let the program route on it.

Stream the reply (SSE)

POST /messaging/v1/messages/stream takes the same request body and streams the reply token-by-token over server-sent events. It’s plain HTTP — the same auth as the REST call, no upgrade handshake, no connection to keep alive between turns — and a dropped stream resumes with the standard Last-Event-ID header instead of re-running the turn.
cURL
Events are JSON objects discriminated on type: The stream ends with a standalone data: [DONE] terminator.
Example stream

Resuming a dropped stream

event and message frames carry a monotonic seq. If the connection drops, reconnect with the standard Last-Event-ID header set to the last seq you saw — missed events replay without running the turn again:

Rerun an interaction

Regenerate a previous interaction — with the original or edited text — against the agent’s live version. The rerun happens on a new thread branched from the original, so the source conversation is untouched.
cURL

POST /messaging/v1/threads/{threadId}/rerun

Request body

string
required
The interaction to regenerate — the message.id from a previous response.
string
required
The message to replay: the original text, or an edited variant.
string
End user to attribute the rerun to. Omitted, the thread’s original user is kept.
string
Signed image URL on the replayed message.
string
Pin the rerun to a specific agent version instead of the live one.
string
Pin to a specific version tag (e.g. v3.2).
boolean
default:"false"
When true, the regenerated reply carries the replayed turn’s reasoning trace as message.trace_info.

Response

Same shape as send: thread_id is the new thread the rerun created, and message is the regenerated reply (with trace_info when the request set include_trace).