---
title: "Sessions"
description: "How sessions are stored, bound to a workspace, and exported."
---

A session keeps a whole working process intact: conversation, tool calls, artifacts and usage stats all belong to one session.

## What a session stores

Each session lives in SQLite (`.bi/bi.db`) in the `user_sessions` table:

- `id` — the session id
- `title` — defaults to "New conversation"; renameable
- `created_at` / `updated_at` — creation and last-update times
- `project_path` — the **session-specific workspace root**
- `pinned` — pinned to the top or not

Messages live in `user_messages`: each row carries the role, text content, tool-call arguments and results, and token usage. **Tool calls and their results are retained** — including file contents read by `read`, content written by `write`, and full `exec` command text.

## The session's workspace

Each session can bind its **own `project_path`**. That means:

- Open a different session per project; the agent only works inside that session's root
- The terminal panel's working directory also comes from the session's `project_path`
- Without one, the session falls back to the global `workspace`

This is "session as project context": one Bi process can push multiple independent projects forward without them interfering.

## Session API

All session endpoints require login:

| Endpoint | Method | Purpose |
| --- | --- | --- |
| `/api/user/sessions` | `GET` | List sessions (with pinned flag, message count, token total) |
| `/api/user/sessions` | `POST` | Create a session (with title and `project_path`) |
| `/api/user/sessions/{id}` | `GET` | Fetch one session |
| `/api/user/sessions/{id}` | `PUT` | Rename / update (also used to truncate or roll back to a step) |
| `/api/user/sessions/{id}` | `DELETE` | Delete a session (cascades to its messages) |
| `/api/user/sessions/{id}/messages` | `POST` | Append messages incrementally |
| `/api/user/sessions/{id}/export` | `POST` | Export to Markdown |

## Export to Markdown

`export` is rendered by the backend (the database is the source of truth) into `对话/<date>-<title>-<first 8 of id>.md` in the workspace:

- Plain Markdown, no HTML — safe for git, readable by AI
- Includes user prompts, assistant text, thinking (collapsed), tool calls and results, permission requests, citations and errors
- The header notes the session id, message count and created/updated times; the footer notes "read-only snapshot, authoritative data is in the database"

## Sessions and context

What the model sees per request is decided by [context management](/en/docs/advanced/context): the recent turns are rebuilt in full, older turns become a rule-based summary. That is not a per-session toggle — it is the uniform behaviour of every pack.
