fix(agent): preserve agent-owned state in project workspaces (#4945)

This commit is contained in:
chengyongru
2026-07-22 17:25:22 +08:00
committed by GitHub
parent 4cd6eb6c38
commit b189a37648
23 changed files with 560 additions and 89 deletions
+18
View File
@@ -149,6 +149,24 @@ Defaults:
The schema accepts both camelCase and snake_case keys, but saves config with camelCase aliases.
### Agent-Owned State vs Effective Project Context
Runtime code distinguishes the configured agent workspace from the effective
project workspace carried by a session scope. They are often the same path, but
a WebUI chat may select a separate project:
| Concern | Path owner |
|---|---|
| Sessions, `SOUL.md`, `USER.md`, memory, and custom skills | Configured agent workspace |
| Project `AGENTS.md`, relative tool paths, and shell working directory | Effective project workspace |
| Workspace access mode and project metadata | Session workspace scope |
`ContextBuilder` combines project instructions with agent-owned profile and
memory. Filesystem and search tools use the project as their ordinary boundary
and receive only capability-specific read access to built-in/agent skills and
the exact agent history file. Keep those cross-root capabilities read-only and
explicit; do not treat the entire agent workspace as an allowed root.
## Memory and Sessions
Session history is the near-term conversation replay. Memory is the longer-term workspace state.
+18 -1
View File
@@ -38,6 +38,23 @@ nanobot gateway --config ./bot-a/config.json --workspace ./bot-a/workspace
The config file controls what nanobot may use. The workspace is where nanobot keeps state for that instance.
### Agent Workspace and Project Workspace
The configured workspace is the **agent workspace**. A WebUI chat can also select
a different **project workspace** for repository-specific work without moving the
agent's identity or durable state.
| Resource | Owner when a project is selected |
|---|---|
| Project instructions | `AGENTS.md` from the selected project; there is no fallback to the agent workspace's `AGENTS.md` |
| Agent profile | `SOUL.md` and `USER.md` from the agent workspace; project-local files with those names are ignored |
| Memory and custom skills | `memory/` and `skills/` from the agent workspace |
| Relative file paths and shell working directory | The selected project workspace |
When no separate project is selected, one directory normally serves both roles.
Selecting a project changes the working context for that chat; it does not create
a second agent or relocate the configured agent workspace.
## Config Format
`config.json` accepts both camelCase and snake_case keys. The docs use camelCase because nanobot writes config back to disk with camelCase aliases, for example `apiKey`, `modelPresets`, `intervalS`, and `maxToolResultChars`.
@@ -49,7 +66,7 @@ Most examples are partial snippets. Merge them into the existing file created by
A normal turn follows this flow:
1. A channel receives a user message and publishes it to the message bus.
2. The agent loop chooses a session key and builds context from the workspace, skills, memory, recent messages, channel metadata, and runtime settings.
2. The agent loop chooses a session key and builds context from the effective project workspace, agent-owned profile/skills/memory, recent messages, channel metadata, and runtime settings.
3. The provider receives the model request.
4. If the model asks for tools, the runner executes them and feeds results back to the model.
5. The final reply is saved to the session and sent back through the channel.
+10
View File
@@ -1930,6 +1930,16 @@ MCP tools are automatically discovered and registered on startup. The LLM can us
For API keys, tokens, and other secrets, see [Environment Variables for Secrets](#environment-variables-for-secrets) — avoid storing them directly in `config.json`.
> [!NOTE]
> When a restricted WebUI chat selects a project outside the configured agent
> workspace, that project becomes the normal file and shell boundary. Nanobot
> adds capability-specific, read-only access for built-in skills, the agent
> workspace's `skills/` directory, and the exact agent
> `memory/history.jsonl` file. Neighboring memory/profile files and all
> cross-workspace writes remain denied. Agent-owned `SOUL.md` and `USER.md` are
> assembled into model context directly; this does not grant file tools broader
> access to the agent workspace.
| Option | Default | Description |
|--------|---------|-------------|
| `tools.restrictToWorkspace` | `false` | When `true`, enables nanobot's application-level workspace guards for workspace-aware tools. File tools resolve paths under the active workspace; selected internal roots can be added as read-only or explicitly write-enabled roots, and media uploads are read-only by default. Shell execution rejects workspace-external `working_dir` values and applies best-effort command path checks, but this is not an OS sandbox. |
+10
View File
@@ -64,6 +64,11 @@ This is why nanobot's memory is not just archival. It is interpretive.
## The Files
In this page, `workspace` means the configured **agent workspace** (the default
is `~/.nanobot/workspace/`, or the path passed with `--workspace`). Selecting a
different project in the WebUI changes that chat's project context and tool
working directory; it does not relocate the files below.
```text
workspace/
├── SOUL.md # The bot's long-term voice and communication style
@@ -79,6 +84,11 @@ workspace/
└── .git/ # Version history for long-term memory files
```
A selected project may provide its own `AGENTS.md`, but project-local `SOUL.md`,
`USER.md`, and `memory/` do not replace the agent-owned files above. This keeps
one agent's profile and memory continuous while it works across projects. Use a
separate configured agent workspace when identity or memory must be isolated.
These files play different roles:
- `SOUL.md` remembers how nanobot should sound.
+22
View File
@@ -106,11 +106,33 @@ Use the workspace picker before starting project-specific work. This gives the
agent the right project context for file paths, shell commands, and session
metadata.
Selecting a project does not replace the configured agent workspace. The two
paths have different responsibilities:
| Selected project provides | Agent workspace continues to provide |
|---|---|
| Project `AGENTS.md` | `SOUL.md` and `USER.md` |
| Relative file paths and shell working directory | Long-term memory and history |
| The normal read/write boundary in Restricted mode | Custom skills and instance state |
Project-local `SOUL.md` and `USER.md` files are ignored, and the agent workspace's
`AGENTS.md` is not inherited by a separately selected project. When the selected
project is the configured agent workspace, both roles naturally use the same
directory.
The access control in the composer controls the local capability level for the
chat. It does not bypass your gateway, provider, shell sandbox, or operating
system configuration; it only selects among the capabilities that are already
available to this WebUI session.
In Restricted mode, ordinary file and shell work stays inside the selected
project. To preserve agent continuity, filesystem/search tools receive narrow,
read-only access to built-in skills, custom skills in the agent workspace, and
the exact agent `memory/history.jsonl` file. This does not grant access to
neighboring memory or profile files, and it does not allow writes outside the
selected project. These tool exceptions do not broaden the browser's file
preview boundary.
Remote WebUI sessions may reduce access for the current workspace. Selecting a
different workspace or enabling Full Access remains limited to local and native
clients.