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",
};