Two kinds of record, one timeline
KAOP keeps two session-like records, and they answer different questions:
History presents both in one ledger, newest first. A chat row resumes the conversation; a run row
opens the evidence.
Chatting with an agent
The responses in a chat come from an agent’s worker — the same worker that would serve any other invocation — so an agent answers in chat with the tools, permissions, knowledge, and skills it has everywhere else. The built-in chat assistant is available from the start, and any agent you register joins the chat picker by advertising chat capability on its agent card:What a turn actually does
Sending a message is not a shortcut around the platform — it goes through it:1
Your message is persisted
Before anything is invoked, so a refresh mid-answer never loses what you asked.
2
The session's agent is invoked, as a run
The turn creates an ordinary run against that agent, marked as a chat turn and carrying the
session it belongs to.
3
The reply streams back as it is produced
Incremental text, including for agents that are only reachable over their live worker
connection.
4
The assistant message is persisted, and the run keeps its evidence
The conversation is resumable, and the turn’s traces, logs, and tool calls are available exactly
as they would be for any other invocation.
Tool calls and evidence in the transcript
The transcript is the primary object, not a chrome-free chat box. As an agent works, what it does appears inline:- Tool calls render as their own rows — which tool, with what arguments, and what came back — interleaved with the agent’s narration in the order they happened.
- Consecutive tool calls are grouped into rounds, so parallel calls issued in one model turn read as one round of work rather than a flat list, and each result stays with the call it answers.
- Data the agent pulled and drafts it produced appear as their own transcript entries rather than being flattened into prose.
- Timestamps are stamped when an event is emitted, not when it reaches the control plane, so the order and spacing you read is the order and spacing that happened.
Resumable sessions
Sessions are addressable, so you can bookmark one or send someone a link to it:
Resuming is not a replay: the transcript is loaded from the control plane with each message’s
status, so a session reopens in the state it was actually left in — complete, errored, or
interrupted. You can rename a session, change its model, or delete it.
Waiting for a worker
A turn’s run is created queued and claimed by a worker, which means a chat can be waiting on capacity rather than on the model. That wait is stated rather than shown as a frozen cursor, and it travels on the stream as its own frames. The streaming endpoints emittext/event-stream frames:
queued_behindis a queue position, not a duration — the number of runs for the same agent that a worker would claim before this one.0therefore means nothing is ahead of it: the wait is for a worker to come free or come online, not for a queue to drain.- The frame is resent whenever that position changes, so a client can count it down. A queue that is not moving sends nothing.
- Nothing is sent for the wait’s first look at the run. Every run starts out queued, so reporting the first look would put a queue notice in front of the reader on every single message. The trade-off is deliberate: the notice appears one poll into a real wait rather than instantly.
dequeuedmarks the end of the wait, sent when a worker claims the run. A claimed run is still silent while it starts up and thinks, so the end of the wait has to be announced or the notice outlives the queue.- A queued run that never reaches a worker sends no
dequeued. Cancelled or failed outright, there was no handoff to report, and the terminal frame that follows carries its own content.
{"type":"error","message":"…"} in place of the terminal message frame.
When an agent cannot answer
A failure is shown, not swallowed. When a turn cannot produce an answer — a model-provider billing, credential, or rate-limit problem, or a worker runtime failure — the transcript renders an error card explaining what went wrong and who can fix it, instead of an empty reply. The underlying run keeps its classified failure alongside whatever evidence it collected first.Continuing from a run
A finished run’s page carries a composer beneath its output: Continue this investigation. You type a follow-up, pick who answers, and pick where it continues.- In KAOP chat. The new session opens as a real transcript rather than one machine-formatted prompt: the run’s own input becomes the prior user turn, its output — or, for a failed run, its failure reason — becomes the prior assistant turn, and your follow-up is the next message. A trailing line names the run so the agent can fetch its full transcript, logs, and trace rather than working from an excerpt.
- By re-running the agent. When the run saved a session snapshot it is revivable: Re-run the agent re-executes it with its tools and the earlier context, producing a new run in the same thread. That is different from talking about the run, and it is the right choice when you want the work redone rather than explained.
- By handing it to a local coding agent. Claude Code or Codex, or the prompt copied to your clipboard. These handoffs carry only your follow-up, the run id, and the run’s URL — never the evidence itself. The coding agent fetches the run over the KAOP MCP server under your own permissions, so nothing sensitive lands in shell history or a clipboard manager. See Connect coding agents.
The History ledger
History combines chat sessions and runs, newest first, and filters by type (all, chats, runs), run status, agent, and free-text search. Two behaviors to know:- Chat rows absorb their turns. The per-turn runs behind a conversation are folded into the session’s row rather than listed a second time, so a long chat does not bury everything else.
- The list is capped, and says so. When a page comes back full, the table prints a truncation notice rather than implying you are looking at everything. Search is evaluated on the server — over run and session ids, a row’s title, and the agent’s display name or slug — so looking for something older than the current page finds it.
Chat API
Chat endpoints live under/api/v1/chat:
You can pass a friendly agent slug wherever an
agent_id is expected — KAOP resolves it to the
agent’s stable id.
Next steps
Runs & evidence
The evidence behind every chat turn.
Build from scratch
Make your own agent chat-capable.
Channels
The same conversational pattern, in Slack.
Connect coding agents
Hand a run to Claude Code or Codex with your own permissions.