Events and the socket

A turn is a stream of events exactly as the olix core emitted them. Each carries protocol (olix.codeui/1), type, session_id, request_id (the turn id), seq and ts. The last event of a turn is always task_complete, unless the core goes away, in which case an error event says so; the API never invents a completion.

A turn can also emit open_in_editor, answer_verification, auto_verify, plan_ready, inference_progress, compaction, memory_used and jobs. They are passed through unchanged. Clients must ignore event types they do not know.

Server-Sent Events

On POST /v1/turns each event is one SSE message: event: <type> and data: <json>. The turn id is also in the X-Olix-Turn header.

curl
curl -sN http://127.0.0.1:8780/v1/turns \
  -H "Authorization: Bearer $OLIX_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "Say hello in five words.", "cwd": "/tmp/olix-demo/project"}'
Show the real output (20 lines)
Real output
event: accepted
data: {"protocol":"olix.codeui/1","type":"accepted","request_id":"t_abd196b48cf83e93","session_id":"20261106132214-54f2e5"}

event: memory_used
data: {"fact_ids":[],"style":["length"],"ms":0.3,"protocol":"olix.codeui/1","type":"memory_used","session_id":"20261106132214-54f2e5","request_id":"t_abd196b48cf83e93","seq":0,"ts":1793971334.525,"epoch":"cdca17e5-d15b-4dee-b565-34a7f275e474","session_seq":1}

event: assistant_start
data: {"protocol":"olix.codeui/1","type":"assistant_start","session_id":"20261106132214-54f2e5","request_id":"t_abd196b48cf83e93","seq":1,"ts":1793971334.537,"epoch":"cdca17e5-d15b-4dee-b565-34a7f275e474","session_seq":2}

event: assistant_delta
data: {"text":"stand-in reply to: Say hello in five words.","protocol":"olix.codeui/1","type":"assistant_delta","session_id":"20261106132214-54f2e5","request_id":"t_abd196b48cf83e93","seq":2,"ts":1793971334.537,"epoch":"cdca17e5-d15b-4dee-b565-34a7f275e474","session_seq":3}

event: assistant_end
data: {"text":"stand-in reply to: Say hello in five words.","protocol":"olix.codeui/1","type":"assistant_end","session_id":"20261106132214-54f2e5","request_id":"t_abd196b48cf83e93","seq":3,"ts":1793971334.537,"epoch":"cdca17e5-d15b-4dee-b565-34a7f275e474","session_seq":4}

event: usage
data: {"prompt_tokens":5,"cached_tokens":0,"output_tokens":1,"tok_s":0,"context_pct":0,"ttft_ms":1,"pass_id":"call_mw507ouf2","model":"olx-1","kind":"chat","protocol":"olix.codeui/1","type":"usage","session_id":"20261106132214-54f2e5","request_id":"t_abd196b48cf83e93","seq":4,"ts":1793971334.537,"epoch":"cdca17e5-d15b-4dee-b565-34a7f275e474","session_seq":5}

event: task_complete
data: {"outcome":"answered","text":"stand-in reply to: Say hello in five words.","result":{"state":"completed","answer":"stand-in reply to: Say hello in five words.","summary":"stand-in reply to: Say hello in five words."},"protocol":"olix.codeui/1","type":"task_complete","session_id":"20261106132214-54f2e5","request_id":"t_abd196b48cf83e93","seq":5,"ts":1793971334.549,"epoch":"cdca17e5-d15b-4dee-b565-34a7f275e474","session_seq":6}

Event types

accepted

The turn started.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
type"accepted"yes
request_idstringyes
session_idstringyes

steered

The session already had a turn running; the text was queued into it.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
type"steered"yes
request_idstringyes
session_idstringyes
turn_request_idstringyes

alive

Heartbeat every 10 s while a turn runs.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.

assistant_start

A reply is starting.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.

assistant_delta

A piece of reply text.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
textstringyes

thinking_delta

A piece of the model's reasoning, when the model emits one.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
textstringyes

assistant_end

The reply is complete; text is the full reply.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
textstringyes

commentary

A work note written before tool calls. Never the answer.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
textstringyes

tool_begin

The model named a tool and is still writing its arguments.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
idstringyes
toolstringyes
labelstringyes
detailstring
targetstring

tool_start

A tool call started.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
idstringyes
toolstringyes
labelstringyes
detailstring
targetstring

tool_output

Streamed output of a running tool.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
idstringyes
textstringyes
toolstring

tool_complete

A tool call finished; ok says whether it worked and summary is what it reported.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
idstringyes
toolstringyes
labelstring
okbooleanyes
summarystringyes

file_change

A file in the project changed.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
pathstringyes
diffstring

todos

The turn's task list changed.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
itemsarrayyes

question

The turn is waiting. Read-only information for an API client: an approval card goes to the owner. The client may only deny (answer) or wait.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
question_idstringyes
input_typechoice | text | picker
questionstringyes
optionsarrayyes
toolstring
argsobject
riskread | mutate | consequential
hintstring

question_resolved

An open question was answered or denied (by the owner, by this client's deny, or by the wait running out); stop showing it.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
question_idstringyes

usage

Token counts and speed of a model pass.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
prompt_tokensintegeryes
cached_tokensinteger
output_tokensintegeryes
tok_snumber
context_pctnumber
modelstring

warning

Something the owner or developer should know.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
textstringyes

brain

The model answering the rest of the turn changed, and why.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
modelstringyes
namestringyes
whystringyes
escalatedbooleanyes

receipts

Sources behind the final answer.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
itemsarrayyes
unsourcedbooleanyes

task_complete

The turn is over. outcome is one of done, answered, blocked, failed, aborted. Always the last event.

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
typestringyes
session_idstringyes
request_idstringyes
seqinteger (0..)Counts events within the turn, from 0.
tsnumberyes
epochstringIdentifies this core run; it changes if the core restarts.
session_seqintegerPosition of the event in the session's replay buffer.
outcomedone | answered | blocked | failed | abortedyes
textstringyes
resultobjectA structured form of the outcome (state, answer, summary), when the core provides one.

info

Reply to a socket command (sessions, history_*, status, ...).

fieldtyperequiredmeaning
protocol"olix.codeui/1"yes
type"info"yes
commandstringyes
request_idstring
resultany

error

A request failed. code is one of the error codes; the stream or socket stays usable unless code is unauthorized.

fieldtyperequiredmeaning
type"error"yes
codestringyes
messagestringyes
request_idstring

The NDJSON socket

The same API as NDJSON on a mode-0600 unix socket, for local tools that prefer it. The first line must be {"type":"auth","token":"..."}; then each line is one of the client messages below and replies are NDJSON events carrying the same request_id. Socket path: ~/.olx/api/api.sock. The gateway must be running.

Messages the socket accepts:

The events of a turn carry the request_id you sent with the input (letters, digits, . _ -, up to 64). Replies to commands are info messages with the same request_id; failures are error messages. Anything outside this list gets bad_request: the socket is not a door to the rest of the core.

auth

fieldtyperequiredmeaning
type"auth"yes
tokenstring (max 200 chars)yes
request_idstring (max 128 chars)

interrupt

fieldtyperequiredmeaning
type"interrupt"yes
request_idstring (max 128 chars)yes

answer

fieldtyperequiredmeaning
type"answer"yes
request_idstring (max 128 chars)yesThe turn's request_id.
question_idstring (max 200 chars)yes
decision"deny"yes
reasonstring (max 500 chars)

Example

client.py
import json, os, socket, sys
s = socket.socket(socket.AF_UNIX); s.connect(sys.argv[1]); f = s.makefile("rw")
def send(o): f.write(json.dumps(o) + "\n"); f.flush()
send({"type": "auth", "token": os.environ["OLIX_API_TOKEN"]}); print(f.readline().strip())
send({"type": "input", "text": "Say hello in five words.", "cwd": sys.argv[2], "request_id": "r1"})
for line in f:
    ev = json.loads(line)
    if ev["type"] in ("accepted", "assistant_end", "task_complete"): print(line.strip())
    if ev["type"] == "task_complete": break
Real output
{"protocol":"olix.codeui/1","type":"info","command":"auth","result":{"app":"sample-app","scopes":["chat","models"]}}
{"protocol":"olix.codeui/1","type":"accepted","request_id":"r1","session_id":"20261106132216-883a92"}
{"text":"stand-in reply to: Say hello in five words.","protocol":"olix.codeui/1","type":"assistant_end","session_id":"20261106132216-883a92","request_id":"r1","seq":3,"ts":1793971336.587,"epoch":"c2d867b0-1dd2-4891-a4e2-3f5b281f25e0","session_seq":4}
{"outcome":"answered","text":"stand-in reply to: Say hello in five words.","result":{"state":"completed","answer":"stand-in reply to: Say hello in five words.","summary":"stand-in reply to: Say hello in five words."},"protocol":"olix.codeui/1","type":"task_complete","session_id":"20261106132216-883a92","request_id":"r1","seq":5,"ts":1793971336.641,"epoch":"c2d867b0-1dd2-4891-a4e2-3f5b281f25e0","session_seq":6}