Chat
Chat is the operator Q&A surface. The TUI and both GUI targets (Desktop and Web) use the same agent API. Chat answers questions, files work, and remembers facts — it never implements code itself.
Work still goes through GitHub issues. When Chat files work, the agent creates the issue, applies pickup labels, and starts task_lifecycle immediately.
Ask a question
Section titled “Ask a question”Send a message to a specific agent. Optional focus (an issue or PR number) scopes retrieve and the answer:
- TUI: the Chat panel.
- GUI: the Chat surface. Focus comes from a Dashboard delivered row.
Endpoints:
| Method | Path | Purpose |
|---|---|---|
POST | /api/operator/chat | Blocking JSON answer |
POST | /api/operator/chat/stream | Server-sent events |
GET | /api/operator/chat | History (?limit= &session=) |
POST | /api/operator/chat/stop | Stop this operator’s in-flight turn |
POST | /api/operator/chat/clear | Clear the conversation |
The SSE stream emits JSON data frames, each with a type:
type | Meaning |
|---|---|
status | Live phase, e.g. retrieve 1/3 · 2 hits |
thinking | Chain-of-thought token |
delta | Assistant reply token |
done | Full ChatResponse (reply, intent, history, retrieve hits) |
error | Turn failed |
The reply is streamed as best-effort Markdown, then replaced by the finalized text on done. A second, grounded draft replaces the first; it is never concatenated.
Thinking and reasoning
Section titled “Thinking and reasoning”When the coding runtime emits reasoning tokens, they arrive as thinking events. The GUI shows them in a collapsed Thinking accordion above the reply; the TUI shows them inline while they stream. The finalized reasoning is persisted with the assistant turn (reasoning, capped at 12,000 characters) and reappears when you reopen the chat.
Retrieve grounding
Section titled “Retrieve grounding”Every Chat turn retrieves session memory in-process — the same cosine path workers use, no HTTP hop. The agent:
- Runs up to 3 retrieve rounds per turn.
- Keeps only semantic hits with a cosine score at or above the Chat floor (a named constant, not a config key).
- Injects the hits as a
Prior Steelframe context:block. If retrieve falls back to recency summaries, it injects(no semantic hits)instead of pretending they were retrieve. - After drafting, checks whether the reply cites a kept hit (
#issue,session_id, or a distinctive token). If not, it widens once and answers again.
The response carries retrieve_hits (injected count) and retrieved (the chunks, with source, score, issue/PR, paths, and a text preview). The GUI shows these in an expandable retrieve N hits row under the reply.
Retrieve errors never fail the turn — Chat still answers from task JSON and the repo checkout.
Sessions
Section titled “Sessions”Chat history is grouped into sessions, one table per operator.
| Method | Path | Purpose |
|---|---|---|
GET | /api/operator/chat/sessions | List sessions, newest activity first |
POST | /api/operator/chat/new | Close the open session and start a fresh one |
GET | /api/operator/chat/session/{session} | Messages + stored summary |
DELETE | /api/operator/chat/session/{session} | Delete a session and its turns |
Starting a new chat summarizes the previous session in the background and titles the new one from your first message (up to 60 characters). Reopening a session pins the next message to it so the conversation continues in place.
Filing issues from Chat
Section titled “Filing issues from Chat”The model replies with a STEELFRAME_META trailer carrying an intent:
| Intent | Effect |
|---|---|
answer / status | No work filed |
file_work, open_issue, create_issue, propose_work | Files a GitHub issue, starts task_lifecycle |
file_memory | Files a committed-memory issue (adds steelframe:memory) |
Filed issues get your configured pickup_labels (default steelframe:work-on-this) plus steelframe:from-tui. The done event includes filed_issue_number, filed_issue_url, and filed_task_started.
Gotchas
Section titled “Gotchas”- Chat works in a checkout of the project repo. Treat it as a shared, read-only cache: Chat is told not to modify, commit, or push.
- Committed memory (
docs/memory/) outranks retrieve. Ask Chat to remember a lasting fact and it files asteelframe:memoryissue; a worker opens the PR. - An empty message is rejected with
400 message is required. - The blocking
POST /api/operator/chatpath has no live status; use the SSE stream forthinking/retrievefeedback. - Stop aborts the in-flight turn; it is not persisted, so the next message starts fresh.