diff --git a/docs/01-agent-loop.md b/docs/01-agent-loop.md
index 22066c5c..a550c4b1 100644
--- a/docs/01-agent-loop.md
+++ b/docs/01-agent-loop.md
@@ -278,7 +278,7 @@ flowchart TD
### Phase 6: Response Finalization
-- Run `SanitizeAssistantContent` -- a 7-step cleanup pipeline (see Section 3).
+- Run the 7-step output sanitization pipeline (see Section 3).
- Detect `NO_REPLY` in the final content. If present, suppress message delivery (silent reply).
- Flush all buffered messages atomically to the session (user message, tool messages, assistant message). This prevents concurrent runs from interleaving partial history.
- Update session metadata: model name, provider name, cumulative token counts.
@@ -341,31 +341,31 @@ A 7-step pipeline cleans raw LLM output before delivering it to the user.
```mermaid
flowchart TD
IN[Raw LLM Output] --> S1
- S1["1. stripGarbledToolXML
Remove broken XML tool artifacts
from DeepSeek, GLM, Minimax"] --> S2
- S2["2. stripDowngradedToolCallText
Remove text-format tool calls:
[Tool Call: ...], [Tool Result ...]"] --> S3
- S3["3. stripThinkingTags
Remove reasoning tags:
think, thinking, thought, antThinking"] --> S4
- S4["4. stripFinalTags
Remove final tag wrappers,
preserve inner content"] --> S5
- S5["5. stripEchoedSystemMessages
Remove hallucinated
[System Message] blocks"] --> S6
- S6["6. collapseConsecutiveDuplicateBlocks
Deduplicate repeated paragraphs
caused by model stuttering"] --> S7
- S7["7. stripLeadingBlankLines
Remove leading whitespace lines"] --> TRIM
- TRIM["TrimSpace()"] --> OUT[Clean Output]
+ S1["1. Strip garbled tool XML
Remove broken XML tool artifacts
from DeepSeek, GLM, Minimax"] --> S2
+ S2["2. Strip downgraded tool call text
Remove text-format tool calls:
[Tool Call: ...], [Tool Result ...]"] --> S3
+ S3["3. Strip thinking tags
Remove reasoning tags:
think, thinking, thought, antThinking"] --> S4
+ S4["4. Strip final wrapper tags
Remove final tag wrappers,
preserve inner content"] --> S5
+ S5["5. Strip echoed system messages
Remove hallucinated
[System Message] blocks"] --> S6
+ S6["6. Collapse consecutive duplicates
Deduplicate repeated paragraphs
caused by model stuttering"] --> S7
+ S7["7. Strip leading blank lines
Remove leading whitespace lines"] --> TRIM
+ TRIM["Trim whitespace"] --> OUT[Clean Output]
```
### Step Details
-1. **stripGarbledToolXML** -- Some models (DeepSeek, GLM, Minimax) emit tool-call XML as plain text instead of proper structured tool calls. This step removes tags like ``, ``, ``, ``, and ``. If the entire response consists of garbled XML, an empty string is returned.
+1. **Garbled tool XML** — Some models (DeepSeek, GLM, Minimax) emit tool-call XML as plain text instead of proper structured tool calls. Tags like ``, ``, ``, ``, and `` are stripped. If the entire response consists of garbled XML, an empty string is returned.
-2. **stripDowngradedToolCallText** -- Removes text-format tool calls such as `[Tool Call: ...]`, `[Tool Result ...]`, and `[Historical context: ...]` along with any accompanying JSON arguments and output. Uses line-by-line scanning because Go regex does not support lookahead.
+2. **Downgraded tool call text** — Text-format tool calls such as `[Tool Call: ...]`, `[Tool Result ...]`, and `[Historical context: ...]` are removed along with any accompanying JSON arguments. Scanning is line-by-line.
-3. **stripThinkingTags** -- Removes internal reasoning tags: ``, ``, ``, ``. Case-insensitive, non-greedy matching.
+3. **Thinking tags** — Internal reasoning tags (``, ``, ``, ``) are stripped. Case-insensitive, non-greedy matching.
-4. **stripFinalTags** -- Removes `` and `` wrapper tags but preserves the content inside them.
+4. **Final wrapper tags** — `` and `` wrapper tags are removed while the inner content is preserved.
-5. **stripEchoedSystemMessages** -- Removes `[System Message]` blocks that the LLM hallucinates or echoes in its response. Scans line by line, skipping content until an empty line is reached.
+5. **Echoed system messages** — `[System Message]` blocks that the LLM hallucinates or echoes back are stripped by scanning line by line until an empty line is reached.
-6. **collapseConsecutiveDuplicateBlocks** -- Removes paragraphs that repeat consecutively (a symptom of model stuttering). Splits by `\n\n` and compares each trimmed block against its predecessor.
+6. **Consecutive duplicate blocks** — Paragraphs that repeat back-to-back (model stuttering) are collapsed. Each block is compared against its predecessor after splitting on `\n\n`.
-7. **stripLeadingBlankLines** -- Removes whitespace-only lines at the beginning of the output while preserving indentation in the remaining content.
+7. **Leading blank lines** — Whitespace-only lines at the start of the output are removed while preserving indentation in the remaining content.
---
@@ -571,21 +571,21 @@ flowchart TD
### Cache Invalidation
-`InvalidateAgent(agentID)` removes a specific agent from the cache, forcing the next `Get()` call to re-resolve from the database.
+Invalidating an agent removes it from the cache, forcing the next request to re-resolve from the database.
### Active Run Tracking
-| Method | Behavior |
-|--------|----------|
-| `RegisterRun(runID, sessionKey, agentID, cancel)` | Register a new active run with its cancel function |
-| `AbortRun(runID, sessionKey)` | Cancel a run (verifies sessionKey match before aborting) |
-| `AbortRunsForSession(sessionKey)` | Cancel all active runs belonging to a session |
+| Operation | Behavior |
+|-----------|----------|
+| Register run | Record a new active run with its agent, session, and cancellation handle |
+| Abort run | Cancel a specific run; verifies session key ownership before aborting |
+| Abort session runs | Cancel all active runs belonging to a session |
---
## 10. Resolver
-The `ManagedResolver` lazy-creates Loop instances from PostgreSQL data when the Router encounters a cache miss.
+The Resolver lazy-creates Loop instances from PostgreSQL data when the Router encounters a cache miss.
```mermaid
flowchart TD
@@ -601,11 +601,11 @@ flowchart TD
### Resolved Properties
- **Provider**: looked up by name from the provider registry. Falls back to the first registered provider if not found.
-- **Bootstrap files**: loaded from the workspace directory via `bootstrap.LoadWorkspaceFiles()`. Standard files: AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, BOOTSTRAP.md. Additional files (MEMORY.md, USER_PREDEFINED.md, DELEGATION.md, TEAM.md, AVAILABILITY.md) loaded separately as needed. Per-user files (USER.md) created on first chat via `EnsureUserFilesFunc`.
+- **Bootstrap files**: loaded from the workspace directory. Standard files: AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, BOOTSTRAP.md. Additional files (MEMORY.md, USER_PREDEFINED.md, DELEGATION.md, TEAM.md, AVAILABILITY.md) loaded separately as needed. Per-user files (USER.md) are created on first chat.
- **Agent type**: `open` (per-user context, seeded from template files) or `predefined` (agent-level context plus per-user USER.md overlay).
-- **Per-user seeding**: `EnsureUserFilesFunc` seeds template files on first chat, idempotent (skips files that already exist). Uses PostgreSQL's `xmax` trick in `GetOrCreateUserProfile` to distinguish INSERT from ON CONFLICT UPDATE, triggering seeding only for genuinely new users.
-- **Dynamic context loading**: `ContextFileLoaderFunc` resolves context files based on agent type and request context. Returns a `[]bootstrap.ContextFile` list with truncated content for system prompt injection. For open agents: loads per-user files from workspace. For predefined agents: loads agent-level files plus per-user USER.md.
-- **Custom tools**: `DynamicLoader.LoadForAgent()` clones the global tool registry and adds per-agent custom tools, ensuring each agent gets its own isolated set of dynamic tools.
+- **Per-user seeding**: Template files are seeded on first chat, idempotent — skips files that already exist. A database-level check distinguishes genuine new users from returning ones, triggering seeding only once.
+- **Dynamic context loading**: Context files are resolved based on agent type and request context, with truncated content for system prompt injection. Open agents load per-user workspace files; predefined agents load agent-level files plus per-user USER.md.
+- **Custom tools**: Each agent gets its own isolated clone of the tool registry with any per-agent custom tools appended.
- **Team context**: auto-resolved for agents that belong to a team. Lead agents get the team workspace as default workspace; non-lead members keep their own workspace with team workspace accessible via absolute path tool context.
---
@@ -633,11 +633,11 @@ Agents that belong to a team have access to shared team workspaces for collabora
### Context Variables
-During runs with team context:
-- `WithToolTeamWorkspace(ctx, wsDir)` — absolute path to shared team workspace
-- `WithToolWorkspace(ctx, effectiveWorkspace)` — effective default workspace for file operations
-- `WithToolTeamID(ctx, teamID)` — team UUID string for team-scoped tool operations
-- `WithToolTaskID(ctx, taskID)` — team task ID when executing dispatched team tasks
+During runs with team context, the following values are injected so tools can resolve the correct paths and scopes:
+- Shared team workspace path (absolute, for cross-member file access)
+- Effective default workspace (team or agent workspace depending on role)
+- Team UUID (for team-scoped tool operations)
+- Active task ID (for workspace file auto-linking during dispatched tasks)
---
diff --git a/docs/11-agent-teams.md b/docs/11-agent-teams.md
index 1d6e69d3..4b752126 100644
--- a/docs/11-agent-teams.md
+++ b/docs/11-agent-teams.md
@@ -329,30 +329,13 @@ Without `require_approval`, tasks move directly to `completed` after member call
## 5. Team Mailbox
-The mailbox enables peer-to-peer communication between team members via the `team_message` tool.
+The mailbox enables peer-to-peer communication between team members via the `team_message` tool. Messages flow through the message bus with a `"teammate:"` prefix and are delivered as inbound messages to the target agent's session, routed through the team scheduler lane. The response is published back to the originating channel so the user (and lead) can see it.
-| Action | Description |
-|--------|-------------|
-| `send` | Send a direct message to a specific teammate by agent key |
-| `broadcast` | Send a message to all teammates (except self) |
-| `read` | Read unread messages, automatically marks them as read |
+**Sending a direct message** targets a specific teammate by agent key. The lead uses this to assign tasks by reference, redirect work, or ask clarifying questions. Members use it to report partial progress, flag blockers, or request context from the lead. Cross-coordination between members working on related tasks is also common.
-### Message Format
+**Broadcasting** delivers a message to all teammates except the sender. The lead uses broadcast to share context updates — new requirements, revised scope, or intermediate results — so all members can incorporate them without requiring the lead to message each one individually.
-When a team message is sent, it flows through the message bus with a `"teammate:"` prefix:
-
-```
-[Team message from {sender_key}]: {message text}
-```
-
-The receiving agent processes this as an inbound message, routed through the team scheduler lane. The response is published back to the originating channel so the user (and lead) can see it.
-
-### Use Cases
-
-- **Lead → Member**: "Please claim a task from the board"
-- **Member → Lead**: "Task partially complete, need clarification on requirements"
-- **Member → Member**: Cross-coordination between teammates working on related tasks
-- **Broadcast**: Lead sharing context updates with all members simultaneously
+**Reading** fetches unread messages and automatically marks them as read. Agents check their mailbox as part of their normal turn execution, processing queued messages from peers before continuing with assigned work.
---
@@ -384,17 +367,7 @@ When a member writes a file during task execution, it's automatically:
### WorkspaceDir Context
-During task dispatch, the team workspace directory is injected into tool context:
-
-```go
-WithToolTeamWorkspace(ctx, "/path/to/teams/{teamID}/")
-WithToolTeamID(ctx, "{teamID}")
-WithTeamTaskID(ctx, "{taskID}")
-WithWorkspaceChannel(ctx, task.Channel)
-WithWorkspaceChatID(ctx, task.ChatID)
-```
-
-File tools use this context to resolve workspace paths and auto-link files to tasks.
+During task dispatch, tool context is injected with the team workspace path, team ID, active task ID, and the task's origin channel and chat ID. File tools use this context to resolve workspace paths and auto-link created files to the active task.
### Quota & Limits