Skip to content

Chat

Chat is the live half of the harness. You talk to a coding agent in a conversation, and every turn the agent decides what happens next: answer, call a tool, read a file, propose a change. That open-endedness is the point, and it is the exact complement of a workflow, where a YAML file fixes what runs. The two share one agent and one tool registry; chat leaves the control flow with the model, a workflow takes it away.

A bare agent SDK already gives you a chat loop. What the harness adds around it is the rest of this page: a system prompt built from your own state, a tool set drawn from installed ribs, a provider you choose per turn, and a governance layer that gates every tool call. None of it changes the model; all of it shapes the turn.

Each message you send runs the same sequence on the server:

StepWhat happens
Resolve the providerThe message names a provider and model; the server looks it up in the registry and constructs it. An unknown provider is rejected before the turn starts.
Assemble the system promptSeveral sections compose in a fixed order: the project notebook, memory recall, a conversation seed, workflow guidance, and tool-conditional guidance for canvas artifacts and the docs tool (the last two ride the turn’s tool list, so normally on).
Project the toolsThe registered tools, the built-in workflow tools plus whatever ribs have added, are filtered by policy into the set this turn may see.
Stream the turnThe provider runs the turn and streams chunks back over the WebSocket, text, tool calls, and results, as they happen.
Gate each tool callBefore any projected tool executes, it passes an args-aware policy check; a denied call returns an error result instead of running.
PersistThe conversation and its messages are saved to SQLite, and the provider session id is recorded so the next turn can continue the same thread.

The system prompt’s sections are the subject of Memory and state; the short version is that everything the agent knows across turns arrives through one of them, and the ones that carry your own state (notebook, recall, seed) are files or rows you can read.

Keelson ships no domain tools. Out of the box the agent has the harness-native tools and nothing more: it can run and check workflows and author new ones, read Keelson’s and its ribs’ documentation with keelson_docs, publish a canvas artifact with canvas_publish, and append to the project notebook with note_project. What it cannot do is anything domain-specific. Every such capability, from reading a cluster to opening an issue to querying a dataset, reaches the agent because a rib registered it. A rib’s registerTools puts its tools in the shared registry, and from that moment they are on tap in chat with no further wiring, the same tools a workflow prompt node opts into by name.

A conversation records which provider it runs on and, when the provider supports it, the backend session id for that thread. You can change the provider on the next message; the picker just preselects your configured default. Switching providers starts a fresh session rather than resuming the old one, because a session id from one agent means nothing to another.

Session resume is what lets a provider keep multi-turn context server-side instead of replaying the whole transcript every turn. It holds for the life of the server process: a restart does not resume a mid-conversation provider session, though the conversation and its messages stay durable in the store either way.

A conversation can open pre-seeded. A surface panel’s “explore in chat” handoff, or a rib-contributed named agent you pick from the composer, hands the new chat a write-once seed system prompt: a directive the turn carries ahead of your first message. Because the seed is set once at creation and never mutated, it stays provenance you can read rather than hidden instruction, one of the ordered sections above. Such a seed may also pin its own provider and model, so entering a named agent runs the agent’s configured model instead of the surface’s session default. Where the seed comes from is the rib model; how a panel hands one off is snapshots and surfaces.

Chat, workflow prompt nodes, and a rib’s own agent turns are the three places an agent runs, and they pass through one governance layer. For chat that means two checks. Policy first decides which tools are even visible this turn (the projection), then re-checks each individual call against its arguments before it runs (the gate). Above both sits the operator’s tool denylist, a floor no turn can rise over. The allow-or-deny decision is the same engine a workflow uses, so a tool you have forbidden is forbidden everywhere, not just on one surface.

Two further phases sit dormant by default: a policy (a rib’s, say) can redact a tool’s result before the model reads it, and gate a whole turn on the session’s accumulated token spend before it runs. Neither fires unless a policy opts into it, so the default path pays for neither.

Tools are not the only thing a rib adds to chat. A rib can register slash-commands that surface in the composer’s slash menu alongside the built-in ones (workflow, project, session). Typing one runs it server-side and returns a closed effect the surface performs, opening a seeded chat, say, rather than streaming a model turn. The menu aggregates every installed rib’s commands, drops any name a surface reserves for its own, and dedupes across ribs so the first registered wins. A command reaches only its own rib’s agents; it cannot open another rib’s.

The composer carries a small usage chip, and it reports two distinct measures without conflating them. When the provider reports a context window, the chip is a fill gauge: what percent of the window this conversation currently occupies, the how-close-to-the-edge number. When there is no window, it falls back to the session’s up and down token totals, how much was spent across the thread. When a turn reports neither, it renders nothing rather than a fabricated ↑ 0 ↓ 0. The popover behind it breaks the numbers out by context, last turn, and session, with cache read and write when the provider supplies them. The counts are always tokens, never dollars; Usage is where the ledger lives.

  • Workflows is the deterministic complement: the same agent and tools, with the control flow moved into a file.
  • The rib model is where chat’s tools come from, and how a rib registers them.
  • Providers is the swappable agent behind every turn.
  • Memory and state details the system prompt’s sections and what the store keeps.