Skip to content

Conversations

NimbleBrain automatically persists every conversation. Each conversation is stored as a JSONL file owned by the user who created it, and you can resume, rename, fork, and delete conversations through the web UI or CLI.

Conversations are partitioned by workspace and authorized by their owner. Every conversation lives under the workspace it ran in and the user who created it, keyed by its ID:

~/.nimblebrain/workspaces/ws_3f9a1c7e0b2d4856/conversations/user_abc123/conv_a1b2c3d4e5f67890.jsonl

The path is the authority: workspaces/<wsId>/conversations/<ownerId>/<convId>.jsonl. The owner (ownerId) is the single authorization principal — only they can read or resume the conversation — while the workspace (workspaceId) is where it is stored and which tools the agent could reach when a turn ran.

Conversations are stored as append-only JSONL (JSON Lines) files using event sourcing:

  • Line 1 — immutable conversation metadata (written once, never rewritten)
  • Lines 2+ — append-only conversation events
{
"id": "conv_a1b2c3d4e5f67890",
"createdAt": "2026-03-25T10:30:00.000Z",
"updatedAt": "2026-03-25T10:42:00.000Z",
"title": "Weekly meeting summary",
"lastModel": "anthropic:claude-sonnet-4-6",
"ownerId": "user_abc123",
"workspaceId": "ws_3f9a1c7e0b2d4856",
"format": "events"
}

Each conversation has exactly one owner (ownerId), the single authorization principal. Token totals and cost are not stored in line 1 — they are derived at read time by scanning llm.response events, which avoids drift between a cached total and what re-aggregating the events would produce.

Events are appended chronologically. Key event types:

EventDescription
user.messageA user sent a message
run.startThe agent engine started processing
llm.responseThe model returned a response (token counts, model, content)
tool.startA tool call began
tool.doneA tool call completed (result, latency)
run.doneThe agent engine finished processing
run.errorThe agent engine encountered an error

Example user message event:

{
"ts": "2026-03-25T10:30:00.000Z",
"type": "user.message",
"content": [{"type": "text", "text": "Summarize my meetings from this week"}]
}

Open Conversations from the sidebar to see your history. Each conversation shows:

  • Title — auto-generated from your first message
  • Timestamp — when the conversation last had activity

Click any conversation to load it in the chat panel and continue where you left off. The agent has the full context of everything discussed previously.

The list and the search box both show the workspace you are currently in, and only that one. Switch workspaces to see another workspace’s history. The same holds when you ask the agent — conversations__list and conversations__search resolve to your current workspace and take no workspace argument, so the agent cannot search across your workspaces in one pass. A conversation opened by a direct link still loads from whichever workspace it lives in.

Select a conversation from the sidebar list in the web UI. The full message history loads, and new messages continue the conversation. Through the API, pass conversationId in the chat request body to continue an existing conversation.

A conversation always resumes in its own workspace — the one it was born in — no matter which workspace you are viewing when you send. That workspace is fixed for the conversation’s whole life and decides which tools and context the agent reaches. In the web UI, if you switch to a different workspace the chat panel starts a fresh conversation in the workspace you are now viewing rather than continuing one from another workspace (the earlier conversation stays saved in its own workspace’s list).

NimbleBrain generates a conversation title automatically after the first assistant response. The title is stored in the metadata line of the JSONL file and shown in the web UI sidebar and conversation list.

Click New conversation in the chat panel header, or type /clear in the input. Your previous conversation is saved — you can always return to it.

For long-running conversations, NimbleBrain compacts older history to keep the context window manageable. It’s on by default. Turn it off with the compaction feature flag in nimblebrain.json:

nimblebrain.json
{
"features": {
"compaction": false
}
}

The runtime summarizes earlier turns once a conversation grows large, preserving the gist while freeing room for new context. Set the flag to false and the full event history is replayed every turn instead.

Your own messages are kept verbatim through compaction, not folded into the summary. Instructions and corrections you give (“use this format, not that one”) are the highest-value part of a long conversation, so they survive every compaction — including repeated ones — for the life of the conversation. The summary compacts the assistant and tool activity around them. Retention is bounded, so it never undoes the compaction; on an unusually long steering session the oldest of your messages may be elided (a marker shows when this happens), keeping the most recent guidance intact. The full, un-summarized history is always available in the conversation export and fork.

By default the CLI uses event-sourced JSONL storage under the work directory. You can point storage elsewhere in nimblebrain.json:

{
"store": {
"type": "jsonl",
"dir": "/custom/path/to/conversations"
}
}

For ephemeral, in-memory storage with no persistence:

{
"store": {
"type": "memory"
}
}
  • Chat — how conversations are created during chat
  • Multi-Agent Delegation — child agents run in their own conversations
  • Automations — scheduled agent runs that produce deliverables