/execute endpoint can deliver.
Endpoint:
wss://api.artaios.ai/ws/amas/A session must already exist. Create one over REST first — see Connecting Your Agent.Authentication
Pick whichever fits your client. The connection is rejected (close code4003) when none of them authenticates.
- API key (server-side)
- JWT (browser)
- Agent key (public agent)
Send your API key as a header on the upgrade request:Browsers cannot set headers on a
WebSocket, so this works only from a server-side client (Node, Python, Go …).End-user identity (optional)
When the agent has External Auth configured, send your own end user’s JWT as a header on the handshake:user_message as ext_token — otherwise the message is rejected with missing_ext_token. See External Authentication.
Close codes
Message envelope
Every message in both directions carriestype and client_type.
string
required
Message type discriminator.
string
required
Who is speaking:
web_frontend, mobile_frontend, desktop_frontend, api, or backend. Server-to-client messages are always backend.Connection flow
1
Create a session over REST
GET /api/v1/sessions/from-agent/?agent_key=… or POST /api/v1/sessions/. Keep the returned session_id.2
Open the socket and subscribe
Send
connect with the session_id. The session is validated against your credentials; an unknown or inaccessible session returns invalid_session.3
Send user messages
Send
user_message and read the event stream until ExecutionFinished.4
Answer any approval card
If a
HitlRequired event arrives, the run is suspended until you send hitl_response.Client messages
connect
Subscribe to a session’s event stream.
string
required
The session to subscribe to.
array
default:"[\"*\"]"
Event types to receive.
["*"] subscribes to everything.user_message
Run the agent on a user turn. This is also where variables are supplied.
string | array
required
The user turn. A plain string, or an array of multimodal content blocks (
text, image, file) — the same shapes the REST endpoint accepts.object
Variable values for this execution, keyed by variable name. Readable in prompts as
{{ variables.key }}. See Variables over WebSocket.array
ChatArtifact UUIDs attached to this message. The backend resolves them to presigned URLs and injects them into the agent context.string
Echoed back on every event produced by this turn, so you can attribute events to the request that caused them.
string
IANA timezone of the end user, e.g.
Europe/Berlin. Used to render the agent’s current time. Defaults to Europe/Berlin.string
The end user’s external JWT. Required on every message when the session was created with an external identity.
hitl_response
Answer an open approval card. See Human-in-the-Loop over WebSocket.
cancel_execution
Stop the running execution for this session.
reconnect
Resubscribe after a dropped connection and replay what you missed.
string
required
The
message_id of the last event you processed. Events are replayed from there.disconnect
Unsubscribe gracefully.
Server messages
Three wrappers come back from the server, all withclient_type: "backend".
event
The workhorse. Wraps one agent event.
object
The event itself.
payload.type selects the shape — see Event types.string
Stream entry id, monotonic per session. Use it to deduplicate replayed events after a
reconnect, and as last_message_id on the next reconnect.string
Entry id of the immediately preceding event, so a gap in the stream is detectable precisely.
null for the first event of a turn.error
execution_result
The terminal summary of a turn — the same shape the REST /execute endpoint returns.
Event types
payload.type is one of the following. Every event carries timestamp and an optional correlation_id.
Lifecycle
Lifecycle
ExecutionStarted · ExecutionFinished · ExecutionCancelled · ExecutionError · RunStarted · RunFinished · RunError · StepStarted · StepFinishedExecutionFinished carries finish_reason (stop, length, content_filter, tool_calls, error) and a usage object with token counts and a cost estimate.Assistant text
Assistant text
TextMessageStart → TextMessageContent (repeated) → TextMessageEnd, plus MessageError.Each carries messageId and run_id; TextMessageContent.delta is the chunk to append. Group by messageId, not by arrival order.Reasoning and progress
Reasoning and progress
ThinkingStart · ThinkingContent · ThinkingEnd · ProcessStep · AgentIntroductionStart · AgentIntroductionContent · AgentIntroductionEndTool calls
Tool calls
ToolCallStart · ToolCallArgs · ToolCallEnd · ToolCallResult · ToolCallErrorHuman-in-the-Loop
Human-in-the-Loop
HitlRequired · HitlResolvedKnowledge base and memory
Knowledge base and memory
QueryGenerationStart · QueryGenerationResult · QueryGenerationEnd · QueryGenerationError · KnowledgeBaseCallStart · KnowledgeBaseCallArgs · KnowledgeBaseCallResult · KnowledgeBaseCallEnd · KnowledgeBaseCallError · MemoryCallStart · MemoryCallResult · MemoryCallEnd · MemoryCallErrorLLM and state
LLM and state
LLMCallStarted · LLMCallCompleted · LLMCallError · StateSnapshot · StateDelta · MessagesSnapshot · ConditionChecked · ConditionError · Raw · CustomVariables over WebSocket
Variables work exactly as they do over REST — theinputs object on user_message is the WebSocket equivalent of the REST body’s inputs. Keys must match variable names declared in the agent’s variables block.
Given this configuration:
current_user_id was checkpointed:
inputsoverrides a variable’sdefaultfor that execution.- A variable with
required: truemust arrive on the first execution; it then persists whilepersistent_state: true. - A variable with
require_every_execution: trueignores the checkpoint and must be sent every turn. - Values are coerced to the declared type:
"70.5"for afloatbecomes70.5. An uncoercible value fails the execution with'score' expected float, got str. - Keys not declared in
variablesare ignored.
Variables System
Types, defaults, assignment from structured output, and template syntax
Human-in-the-Loop over WebSocket
WebSocket is the only transport that can answer an approval card. Configure the gate in YAML first — see Human-in-the-Loop.1. The run pauses
AHitlRequired event arrives and the execution suspends. Nothing further happens until you respond.
payload.kind discriminates the pause:
A session holds at most one open pause. Sending a
user_message while a card is open is rejected with hitl_session_busy.2. You respond
string
required
Must match the
tool_call_id from the open HitlRequired payload. A mismatch is rejected with hitl_tool_call_mismatch — this is what stops stale and cross-session resumes.object
required
The typed response, discriminated by
kind.3. The run resumes
AHitlResolved event reports the outcome — accepted, declined, validation_failed or answered — and the stream continues.
Error codes
Returned on theerror message as error_code.
Full example
Related
Human-in-the-Loop
Configure which tools pause for approval
Variables System
Declare and populate variables
Connecting Your Agent
Sessions, credentials and the REST path
Variables in REST API
The same
inputs object over HTTP