> ## Documentation Index
> Fetch the complete documentation index at: https://docs.komodor.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat & history

> Work conversationally with your agents in resumable sessions, and read every run and chat in one ledger.

Not all agent work is triggered and structured — a lot of it starts as a question. Chat in the
Komodor Agentic Operation Platform (KAOP) is a conversation with a real agent, not a generic model
wrapper, and every turn is recorded with the same evidence as any other run. This page covers how
chat works, what the transcript shows you, and how History ties conversations and runs into one
timeline.

## Two kinds of record, one timeline

KAOP keeps two session-like records, and they answer different questions:

| Record           | What it is                                              | What you do with it            |
| ---------------- | ------------------------------------------------------- | ------------------------------ |
| **Run**          | One execution of an agent, with its full evidence trail | Open it and read what happened |
| **Chat session** | A saved conversation with a chat-capable agent          | Resume it and keep going       |

**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:

```json theme={null}
{
  "capabilities": {
    "chat": true,
    "streaming": true
  }
}
```

In Fleet, a chat-capable agent gets chat actions alongside **Run**; an agent that does not advertise
chat keeps the structured run-and-evidence flow. The capability is checked on every send, not only
when a session is created, so an agent that stops advertising chat also stops serving sessions that
already exist.

You can switch the model for a session from the chat header. The list is curated by the control
plane rather than free text, and every requested model is validated.

## What a turn actually does

Sending a message is not a shortcut around the platform — it goes through it:

<Steps>
  <Step title="Your message is persisted">
    Before anything is invoked, so a refresh mid-answer never loses what you asked.
  </Step>

  <Step title="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.
  </Step>

  <Step title="The reply streams back as it is produced">
    Incremental text, including for agents that are only reachable over their live worker
    connection.
  </Step>

  <Step title="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.
  </Step>
</Steps>

The consequence worth internalising: **a chat answer is as auditable as a scheduled one.** There is
no lower-fidelity path for conversational work.

## 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.

History's own list shows a per-run tool-call count alongside each row, counted once per tool call.

For the full trace tree, the logs, and the artifacts behind a turn, open its run — see
[Runs & evidence](/manage-your-agents/run/runs-evidence).

## Resumable sessions

Sessions are addressable, so you can bookmark one or send someone a link to it:

| URL                                           | Opens                                                         |
| --------------------------------------------- | ------------------------------------------------------------- |
| `/chat`                                       | The built-in chat assistant, or your first chat-capable agent |
| `/chat?agent=<agent_id>`                      | The session list scoped to one agent                          |
| `/chat?agent=<agent_id>&session=<session_id>` | That exact saved session, resumed                             |

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 emit `text/event-stream` frames:

```text theme={null}
data: {"type":"queued","queued_behind":2}
data: {"type":"dequeued"}
data: {"type":"text-delta","delta":"Checking the latest deploy…"}
data: {"type":"message","message_id":"msg_…"}
data: [DONE]
```

The two transport frames behave in ways worth knowing if you are building against the API:

* **`queued_behind` is a queue position**, not a duration — the number of runs for the same agent
  that a worker would claim before this one. `0` therefore 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.
* **`dequeued` marks 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.

<Warning>
  Neither frame carries assistant text. Render both as transport state — a status line, a spinner
  label — and never as part of the reply. Folding them into the message persists them into the
  transcript, where they get replayed on every reload.
</Warning>

Errors arrive as `{"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](/developer-tools/connect-coding-agents).

Any chat-capable agent may answer, defaulting to the run's own agent when it can chat. When a
different agent has to answer instead, the composer says so inline — the substitution is never
silent.

## 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`:

| Endpoint                                            | Purpose                                                       |
| --------------------------------------------------- | ------------------------------------------------------------- |
| `GET /api/v1/chat/models`                           | The curated model list                                        |
| `GET /api/v1/chat/sessions`                         | List sessions, optionally `?agent_id=` or `?q=`               |
| `POST /api/v1/chat/sessions`                        | Create an empty session for an agent and model                |
| `POST /api/v1/chat/sessions/start`                  | Create a session and persist its opening messages in one step |
| `GET /api/v1/chat/sessions/{session_id}`            | Load a session and its messages                               |
| `PATCH /api/v1/chat/sessions/{session_id}`          | Rename it, or change its model                                |
| `DELETE /api/v1/chat/sessions/{session_id}`         | Delete it                                                     |
| `POST /api/v1/chat/sessions/{session_id}/messages`  | Send a message and stream the reply                           |
| `POST /api/v1/chat/sessions/{session_id}/responses` | Stream a reply for an already-persisted message               |
| `POST /api/v1/chat`                                 | One-shot streaming chat with no persisted session             |

You can pass a friendly agent slug wherever an `agent_id` is expected — KAOP resolves it to the
agent's stable id.

## Next steps

<CardGroup cols={2}>
  <Card title="Runs & evidence" href="/manage-your-agents/run/runs-evidence">
    The evidence behind every chat turn.
  </Card>

  <Card title="Build from scratch" href="/manage-your-agents/build/build-from-scratch">
    Make your own agent chat-capable.
  </Card>

  <Card title="Channels" href="/manage-your-agents/run/channels">
    The same conversational pattern, in Slack.
  </Card>

  <Card title="Connect coding agents" href="/developer-tools/connect-coding-agents">
    Hand a run to Claude Code or Codex with your own permissions.
  </Card>
</CardGroup>


## Related topics

- [Build from scratch](/manage-your-agents/build/build-from-scratch.md)
- [Runs & evidence](/manage-your-agents/run/runs-evidence.md)
- [How Run works](/manage-your-agents/run/how-it-works.md)
- [Data handling & redaction](/security-and-governance/architecture-considerations/data-handling-redaction.md)
- [Fleet health](/manage-your-agents/optimize/fleet-health.md)
