diff --git a/docs/concepts/agent-workspace.md b/docs/concepts/agent-workspace.md index 41e71212e685..ca6eba4d43c5 100644 --- a/docs/concepts/agent-workspace.md +++ b/docs/concepts/agent-workspace.md @@ -99,7 +99,7 @@ These are the standard files OpenClaw expects inside the workspace: -If any bootstrap file is missing, OpenClaw injects a "missing file" marker into the session and continues. Large bootstrap files are truncated when injected; adjust limits with `agents.defaults.bootstrapMaxChars` (default: 12000) and `agents.defaults.bootstrapTotalMaxChars` (default: 60000). `openclaw setup` can recreate missing defaults without overwriting existing files. +If any bootstrap file is missing, OpenClaw injects a "missing file" marker into the session and continues. Large bootstrap files are truncated when injected; adjust limits with `agents.defaults.bootstrapMaxChars` (default: 20000) and `agents.defaults.bootstrapTotalMaxChars` (default: 60000). `openclaw setup` can recreate missing defaults without overwriting existing files. ## What is NOT in the workspace diff --git a/docs/concepts/context.md b/docs/concepts/context.md index 9952a52b29fe..481238ecf759 100644 --- a/docs/concepts/context.md +++ b/docs/concepts/context.md @@ -122,7 +122,7 @@ By default, OpenClaw injects a fixed set of workspace files (if present): - `HEARTBEAT.md` - `BOOTSTRAP.md` (first-run only) -Large files are truncated per-file using `agents.defaults.bootstrapMaxChars` (default `12000` chars). OpenClaw also enforces a total bootstrap injection cap across files with `agents.defaults.bootstrapTotalMaxChars` (default `60000` chars). `/context` shows **raw vs injected** sizes and whether truncation happened. +Large files are truncated per-file using `agents.defaults.bootstrapMaxChars` (default `20000` chars). OpenClaw also enforces a total bootstrap injection cap across files with `agents.defaults.bootstrapTotalMaxChars` (default `60000` chars). `/context` shows **raw vs injected** sizes and whether truncation happened. When truncation occurs, the runtime can inject an in-prompt warning block under Project Context. Configure this with `agents.defaults.bootstrapPromptTruncationWarning` (`off`, `once`, `always`; default `always`). diff --git a/docs/concepts/system-prompt.md b/docs/concepts/system-prompt.md index b512c59e0071..4ec95b201089 100644 --- a/docs/concepts/system-prompt.md +++ b/docs/concepts/system-prompt.md @@ -208,7 +208,7 @@ because of the bootstrap file limits below. Large files are truncated with a marker. The max per-file size is controlled by -`agents.defaults.bootstrapMaxChars` (default: 12000). Total injected bootstrap +`agents.defaults.bootstrapMaxChars` (default: 20000). Total injected bootstrap content across files is capped by `agents.defaults.bootstrapTotalMaxChars` (default: 60000). Missing files inject a short missing-file marker. When truncation occurs, OpenClaw can inject a concise system-prompt warning notice; control this with diff --git a/docs/gateway/config-agents.md b/docs/gateway/config-agents.md index 8ecd9e8a1ff6..d89f49c8f80b 100644 --- a/docs/gateway/config-agents.md +++ b/docs/gateway/config-agents.md @@ -103,11 +103,11 @@ Per-agent override: `agents.list[].contextInjection`. Omitted values inherit ### `agents.defaults.bootstrapMaxChars` -Max characters per workspace bootstrap file before truncation. Default: `12000`. +Max characters per workspace bootstrap file before truncation. Default: `20000`. ```json5 { - agents: { defaults: { bootstrapMaxChars: 12000 } }, + agents: { defaults: { bootstrapMaxChars: 20000 } }, } ``` @@ -138,7 +138,7 @@ injection behavior from the shared defaults. Omitted fields inherit from agents: { defaults: { contextInjection: "continuation-skip", - bootstrapMaxChars: 12000, + bootstrapMaxChars: 20000, bootstrapTotalMaxChars: 60000, }, list: [ diff --git a/docs/help/faq.md b/docs/help/faq.md index 55b1d1fd6ed9..08027bd87917 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -631,6 +631,48 @@ lives on the [First-run FAQ](/help/faq-first-run). + + Yes. `SOUL.md` is one of the workspace bootstrap files injected into the + agent context. The default per-file injection limit is `20000` characters, + and the total bootstrap budget across files is `60000` characters. + + Change the shared defaults in your OpenClaw config: + + ```json5 + { + agents: { + defaults: { + bootstrapMaxChars: 50000, + bootstrapTotalMaxChars: 300000, + }, + }, + } + ``` + + Or override one agent: + + ```json5 + { + agents: { + list: [ + { + id: "main", + bootstrapMaxChars: 50000, + bootstrapTotalMaxChars: 300000, + }, + ], + }, + } + ``` + + Use `/context` to check raw vs injected sizes and whether truncation happened. + Keep `SOUL.md` focused on voice, stance, and personality; put operating rules + in `AGENTS.md` and durable facts in memory. + + See [Context](/concepts/context) and [Agent config](/gateway/config-agents). + + + Put your **agent workspace** in a **private** git repo and back it up somewhere private (for example GitHub private). This captures memory + AGENTS/SOUL/USER diff --git a/docs/reference/token-use.md b/docs/reference/token-use.md index 8d773b7cfc19..37c49da5a12a 100644 --- a/docs/reference/token-use.md +++ b/docs/reference/token-use.md @@ -20,7 +20,7 @@ OpenClaw assembles its own system prompt on every run. It includes: prompt surface. It is bounded by `skills.limits.maxSkillsPromptChars`, with optional per-agent override at `agents.list[].skillsLimits.maxSkillsPromptChars`. - Self-update instructions -- Workspace + bootstrap files (`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md` when new, plus `MEMORY.md` when present). Native Codex turns do not paste raw `MEMORY.md` from the configured agent workspace when memory tools are available for that workspace; they include a small memory pointer in turn-scoped collaboration developer instructions and use memory tools on demand. If tools are disabled, memory search is unavailable, or the active workspace differs from the agent memory workspace, `MEMORY.md` uses the normal bounded turn-context path. Lowercase root `memory.md` is not injected; it is legacy repair input for `openclaw doctor --fix` when paired with `MEMORY.md`. Large injected files are truncated by `agents.defaults.bootstrapMaxChars` (default: 12000), and total bootstrap injection is capped by `agents.defaults.bootstrapTotalMaxChars` (default: 60000). `memory/*.md` daily files are not part of the normal bootstrap prompt; they remain on-demand via memory tools on ordinary turns, but reset/startup model runs can prepend a one-shot startup-context block with recent daily memory for that first turn. Bare chat `/new` and `/reset` commands are acknowledged without invoking the model. The startup prelude is controlled by `agents.defaults.startupContext`. Post-compaction AGENTS.md excerpts are separate and require explicit `agents.defaults.compaction.postCompactionSections` opt-in. +- Workspace + bootstrap files (`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md` when new, plus `MEMORY.md` when present). Native Codex turns do not paste raw `MEMORY.md` from the configured agent workspace when memory tools are available for that workspace; they include a small memory pointer in turn-scoped collaboration developer instructions and use memory tools on demand. If tools are disabled, memory search is unavailable, or the active workspace differs from the agent memory workspace, `MEMORY.md` uses the normal bounded turn-context path. Lowercase root `memory.md` is not injected; it is legacy repair input for `openclaw doctor --fix` when paired with `MEMORY.md`. Large injected files are truncated by `agents.defaults.bootstrapMaxChars` (default: 20000), and total bootstrap injection is capped by `agents.defaults.bootstrapTotalMaxChars` (default: 60000). `memory/*.md` daily files are not part of the normal bootstrap prompt; they remain on-demand via memory tools on ordinary turns, but reset/startup model runs can prepend a one-shot startup-context block with recent daily memory for that first turn. Bare chat `/new` and `/reset` commands are acknowledged without invoking the model. The startup prelude is controlled by `agents.defaults.startupContext`. Post-compaction AGENTS.md excerpts are separate and require explicit `agents.defaults.compaction.postCompactionSections` opt-in. - Time (UTC + user timezone) - Reply tags + heartbeat behavior - Runtime metadata (host/OS/model/thinking) diff --git a/src/agents/bootstrap-files.test.ts b/src/agents/bootstrap-files.test.ts index 42ff73f4adf4..0fc5fe19490a 100644 --- a/src/agents/bootstrap-files.test.ts +++ b/src/agents/bootstrap-files.test.ts @@ -634,11 +634,11 @@ describe("makeBootstrapWarn", () => { warn: (message) => warnings.push(message), }); - warn?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating"); - warn?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating"); + warn?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating"); + warn?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating"); expect(warnings).toEqual([ - "workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating (sessionKey=agent:main:test-session)", + "workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating (sessionKey=agent:main:test-session)", ]); }); @@ -653,12 +653,12 @@ describe("makeBootstrapWarn", () => { warn: (message) => warnings.push(message), }); - first?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating"); - second?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating"); + first?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating"); + second?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating"); expect(warnings).toEqual([ - "workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating (sessionKey=agent:main:first-session)", - "workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating (sessionKey=agent:main:second-session)", + "workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating (sessionKey=agent:main:first-session)", + "workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating (sessionKey=agent:main:second-session)", ]); }); @@ -675,12 +675,12 @@ describe("makeBootstrapWarn", () => { warn: (message) => warnings.push(message), }); - first?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating"); - second?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating"); + first?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating"); + second?.("workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating"); expect(warnings).toEqual([ - "workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating (sessionKey=agent:main:shared-session)", - "workspace bootstrap file MEMORY.md is 36697 chars (limit 12000); truncating (sessionKey=agent:main:shared-session)", + "workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating (sessionKey=agent:main:shared-session)", + "workspace bootstrap file MEMORY.md is 36697 chars (limit 20000); truncating (sessionKey=agent:main:shared-session)", ]); }); }); diff --git a/src/agents/embedded-agent-helpers/bootstrap.ts b/src/agents/embedded-agent-helpers/bootstrap.ts index eaa9f6163606..400966b9d34a 100644 --- a/src/agents/embedded-agent-helpers/bootstrap.ts +++ b/src/agents/embedded-agent-helpers/bootstrap.ts @@ -85,7 +85,7 @@ export function stripThoughtSignatures( }) as T; } -export const DEFAULT_BOOTSTRAP_MAX_CHARS = 12_000; +export const DEFAULT_BOOTSTRAP_MAX_CHARS = 20_000; export const DEFAULT_BOOTSTRAP_TOTAL_MAX_CHARS = 60_000; export const DEFAULT_BOOTSTRAP_PROMPT_TRUNCATION_WARNING_MODE = "always"; const MIN_BOOTSTRAP_FILE_BUDGET_CHARS = 64; diff --git a/src/auto-reply/reply/commands-context-report.test.ts b/src/auto-reply/reply/commands-context-report.test.ts index 2246d007a274..d4b03fd43cfd 100644 --- a/src/auto-reply/reply/commands-context-report.test.ts +++ b/src/auto-reply/reply/commands-context-report.test.ts @@ -101,7 +101,7 @@ describe("buildContextReply", () => { omitBootstrapLimits: true, }), ); - expect(result.text).toContain("Bootstrap max/file: 12,000 chars"); + expect(result.text).toContain("Bootstrap max/file: 20,000 chars"); expect(result.text).toContain("Bootstrap max/total: 60,000 chars"); expect(result.text).not.toContain("Bootstrap max/file: ? chars"); }); diff --git a/src/config/schema.help.ts b/src/config/schema.help.ts index 1c25660c46b3..c0178e8215d5 100644 --- a/src/config/schema.help.ts +++ b/src/config/schema.help.ts @@ -1121,7 +1121,7 @@ export const FIELD_HELP: Record = { "agents.defaults.contextInjection": 'Controls when workspace bootstrap files are injected into the system prompt: "always" (default) or "continuation-skip" for safe continuation turns after a completed assistant response.', "agents.defaults.bootstrapMaxChars": - "Max characters of each workspace bootstrap file injected into the system prompt before truncation (default: 12000).", + "Max characters of each workspace bootstrap file injected into the system prompt before truncation (default: 20000).", "agents.defaults.bootstrapTotalMaxChars": "Max total characters across all injected workspace bootstrap files (default: 60000).", "agents.defaults.experimental": diff --git a/ui/src/ui/views/config-quick.test.ts b/ui/src/ui/views/config-quick.test.ts index 2370db983e15..426f89f916b3 100644 --- a/ui/src/ui/views/config-quick.test.ts +++ b/ui/src/ui/views/config-quick.test.ts @@ -133,6 +133,21 @@ describe("renderQuickSettings", () => { expect(container.querySelectorAll(".qs-card--span-all")).toHaveLength(1); }); + it("shows the current bootstrap default when config omits the explicit limit", () => { + const container = document.createElement("div"); + + render(renderQuickSettings(createProps({ configObject: {} })), container); + + const stat = Array.from(container.querySelectorAll(".qs-profile-stat")).find( + (candidate) => + candidate.querySelector(".qs-profile-stat__label")?.textContent?.trim() === + "Bootstrap Per File", + ); + expect(stat?.querySelector(".qs-profile-stat__value")?.textContent?.trim()).toBe( + "20,000 chars", + ); + }); + it("lets operators change browser and tool profile from Security quick settings", () => { const onBrowserEnabledToggle = vi.fn(); const onToolProfileChange = vi.fn(); diff --git a/ui/src/ui/views/config-quick.ts b/ui/src/ui/views/config-quick.ts index 62ed1792b02c..95adbfbaebfc 100644 --- a/ui/src/ui/views/config-quick.ts +++ b/ui/src/ui/views/config-quick.ts @@ -327,7 +327,7 @@ type ProfileSettings = { }; const DEFAULT_PROFILE_SETTINGS: ProfileSettings = { - bootstrapMaxChars: 12_000, + bootstrapMaxChars: 20_000, bootstrapTotalMaxChars: 60_000, contextInjection: "always", };