Skip to content

fix(agents): reorder workspace AGENTS.md template to put load-bearing rules first#75248

Open
lonexreb wants to merge 4 commits intoopenclaw:mainfrom
lonexreb:fix/75187-agents-md-template-priority
Open

fix(agents): reorder workspace AGENTS.md template to put load-bearing rules first#75248
lonexreb wants to merge 4 commits intoopenclaw:mainfrom
lonexreb:fix/75187-agents-md-template-priority

Conversation

@lonexreb
Copy link
Copy Markdown
Contributor

Bug being fixed

Closes #75187

The auto-generated docs/reference/templates/AGENTS.md (used by the workspace bootstrap to seed ~/.openclaw/workspace/AGENTS.md) ordered content with personality/onboarding guidance at the top and the load-bearing ## Red Lines, ## External vs Internal, and ## Tools guidance at the bottom.

When a user lowers agents.defaults.bootstrapMaxChars (typical for small/mid local models — Hermes-3 8B, Qwen3 8B — to fit a tight context budget), bootstrap-budget head-truncates the file. With the old order, that stripped exactly the safety + tool-dispatch rules the model needed, while preserving the less operationally-critical Memory/Group Chats/Heartbeats sections. The reporter's vLLM repro showed 0 structured tool_call events vs. 1 successful structured tool call after manually rewriting AGENTS.md to put tool-use guidance at the top — same model, same parser, same bootstrapMaxChars, content order was the only difference.

Fix

Reorder docs/reference/templates/AGENTS.md so the section sequence is:

  1. First Run
  2. Session Startup
  3. Red Lines (was Images not passed to Claude CLI - only path reference in text #4)
  4. External vs Internal (was CLI: add Opencode integration #5)
  5. Tools (was WhatsApp voice notes fail without explicit "audio/ogg; codecs=opus" mimetype #7)
  6. Memory (was WA business, groups & office hours  #3)
  7. Group Chats (was Clarification for clawd.md #6)
  8. Heartbeats (was Track and persist Claude's returned session ID for conversation continuity #8)
  9. Make It Yours

Section content is unchanged byte-for-byte — only the H2 ordering moves. Path #1 ("Quickest win — reorder the auto-generated AGENTS.md template content") in the issue's recommended resolution order.

This aligns the seeded workspace template with the existing post-compaction priority contract: agents.defaults.compactionAgentsMdReinjectionSections already names Session Startup and Red Lines as the priority sections to re-inject after compaction. Putting them at the top of the seeded file means head-truncation now matches that same priority instead of fighting it.

Why this is the best fix

Test plan

  • pnpm test src/agents/workspace-templates.test.ts — 4 new regression tests pass (Red Lines / External vs Internal / Tools all assert ahead of Memory + Group Chats; First Run / Session Startup stay at the top).
  • pnpm test src/agents/workspace.test.ts src/agents/system-prompt-stability.test.ts — 25 + 4 existing tests pass.
  • pnpm exec oxfmt --check — clean.
  • pnpm tsgo:core + pnpm tsgo:core:test — clean.
  • Lint (pnpm lint:core) failure on oxlint config is pre-existing on origin/main (Rule 'no-underscore-dangle' not found in plugin 'eslint'), unrelated to this PR.

#75187

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation agents Agent runtime and tooling size: S labels Apr 30, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 30, 2026

Codex review: needs changes before merge.

Summary
The PR reorders and condenses the seeded workspace AGENTS.md template so tool dispatch, external-action policy, and red-line guidance survive small bootstrap budgets, and adds focused regression tests for template order and 1500-character trimming.

Reproducibility: yes. Current main reproduces by stripping docs/reference/templates/AGENTS.md front matter and applying the current maxChars=1500 bootstrap trim: the 1044-char head drops Tools, Red Lines, and External vs Internal.

Next step before merge
A safe repair lane can add the missing changelog bullet without changing the already-focused template/test fix.

Security
Cleared: The diff only changes a packaged Markdown workspace template and focused tests; it adds no dependencies, workflows, permissions, secrets handling, install scripts, downloads, or code execution path.

Review findings

  • [P2] Add the required changelog entry — docs/reference/templates/AGENTS.md:20-24
Review details

Best possible solution:

Land this narrow template-ordering fix after adding the required changelog bullet, leaving broader tiered or priority-aware bootstrap loading to #22438 and #22439.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main reproduces by stripping docs/reference/templates/AGENTS.md front matter and applying the current maxChars=1500 bootstrap trim: the 1044-char head drops Tools, Red Lines, and External vs Internal.

Is this the best way to solve the issue?

No, not as currently submitted. The template reorder plus body-text regression test is the narrow maintainable fix for #75187, but the PR still needs the required Unreleased changelog entry before merge.

Full review comments:

  • [P2] Add the required changelog entry — docs/reference/templates/AGENTS.md:20-24
    This changes the generated AGENTS.md template that OpenClaw seeds into user workspaces, so repo policy treats it as a user-facing agents fix. Add a single-line Unreleased Fixes entry in CHANGELOG.md; the latest PR diff still changes only the template and tests.
    Confidence: 0.94

Overall correctness: patch is incorrect
Overall confidence: 0.9

Acceptance criteria:

  • git diff --check
  • pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/reference/templates/AGENTS.md src/agents/workspace-templates.test.ts src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts
  • pnpm test src/agents/workspace-templates.test.ts src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts

What I checked:

  • Current main reproduces the small-budget loss: On current main, the stripped AGENTS.md template is 7775 chars; the maxChars=1500 trim keeps a 1044-char head, while Red Lines starts at char 2048, External vs Internal at 2223, and Tools at 4294, so none of those sections are injected. Public docs: docs/reference/templates/AGENTS.md. (docs/reference/templates/AGENTS.md:60, d583662fd905)
  • Runtime seeding uses the docs template: ensureAgentWorkspace loads DEFAULT_AGENTS_FILENAME from docs/reference/templates and writes it when AGENTS.md is missing, so this Markdown template is runtime seed material, not only reference documentation. (src/agents/workspace.ts:529, d583662fd905)
  • Bootstrap trimming preserves a fixed head slice: buildBootstrapContextFiles uses trimBootstrapContent with BOOTSTRAP_HEAD_RATIO=0.75 and per-file maxChars, matching the reported head-truncation failure mode. (src/agents/pi-embedded-helpers/bootstrap.ts:95, d583662fd905)
  • PR head keeps body text inside the head window: At PR head 913398a, Tools starts at char 476, Tool dispatch at 588, External vs Internal at 737, and Red Lines at 998; the same maxChars=1500 trim includes the asserted body text for structured tool calls, safe/ask policy, and private-data red lines. Public docs: docs/reference/templates/AGENTS.md. (docs/reference/templates/AGENTS.md:20, 913398a8c272)
  • PR adds regression coverage for the real trim path: The new regression reads the actual AGENTS.md template, strips front matter, runs buildBootstrapContextFiles({ maxChars: 1500 }), asserts truncation occurred, and checks body text rather than headings only. (src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts:193, 913398a8c272)
  • Prior lint blocker is fixed but changelog is still absent: The PR diff now uses line.startsWith for the H2 parser and latest check-lint is successful, but the latest diff still changes only docs/reference/templates/AGENTS.md and two tests; CHANGELOG.md at PR head has no new entry for this user-facing fix. (CHANGELOG.md:20, 913398a8c272)

Likely related people:

  • Takhoffman: Authored recent workspace bootstrap/session-startup routing work, including moving session startup context into runtime and workspace bootstrap prompt routing, which directly intersects the AGENTS.md template and bootstrap prompt path. (role: introduced behavior and adjacent owner; confidence: high; commits: 94340b959830, 62703d84308a; files: docs/reference/templates/AGENTS.md, src/agents/workspace.ts)
  • BKF-Gitty: Authored the recent bootstrap trim-ratio fix that makes the 0.75 head window and marker reservation central to this bug's reproduction. (role: introduced relevant trim behavior; confidence: high; commits: 4b4631cd4859; files: src/agents/pi-embedded-helpers/bootstrap.ts, src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts)
  • gumadeiras: Authored earlier bootstrap truncation warning handling work in the same helper/test surface that this PR extends. (role: adjacent bootstrap truncation maintainer; confidence: medium; commits: e4b4486a96a9; files: src/agents/pi-embedded-helpers/bootstrap.ts, src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts)
  • steipete: Recent commits touched the AGENTS.md template and agent workspace/bootstrap files, including silent reply prompt guidance and workspace import trimming near the affected surfaces. (role: recent maintainer; confidence: medium; commits: 496a5eb56f46, 3db60f7eab84; files: docs/reference/templates/AGENTS.md, src/agents/workspace.ts)

Remaining risk / open question:

  • CHANGELOG.md still lacks the required Unreleased Fixes entry for this user-facing agents bootstrap fix.
  • At review time, two exact-head CI checks were still in progress, though check-lint and the relevant docs/security/type gates visible through the public checks API were green.

Codex review notes: model gpt-5.5, reasoning high; reviewed against d583662fd905.

lonexreb added a commit to lonexreb/paloa-claw that referenced this pull request Apr 30, 2026
…t head window

Codex review on PR openclaw#75248 noted that the prior reorder still left `## Tools`
starting at char ~1110 in the stripped template, outside the bootstrap
trimmer's effective ~1044-char head window at agents.defaults.bootstrapMaxChars=1500
(0.75 head ratio of contentBudget after marker reservation). The injected
content kept `Red Lines` and `External vs Internal` but dropped `Tools`
along with the tool-dispatch guidance, so the issue's small-model failure
mode would persist.

Restructure the workspace AGENTS.md template:

- Move `## Tools` directly after `## Session Startup` so its body appears
  in the head window. Add an explicit `Tool dispatch:` rule (emit real
  structured tool calls, fix args on error rather than repeating).
- Condense `## Session Startup` from a multi-list block into a single
  paragraph, freeing room before `## Tools` without losing semantics.
- Split the secondary `Voice Storytelling` and `Platform Formatting`
  bullets out into a new `## Tool Notes` section lower in the file. They
  remain available in the full file but no longer crowd the head budget.

Section starts (post-frontmatter): First Run @72, Session Startup @220,
Tools @555, Red Lines @846, External vs Internal @1021. All four
load-bearing sections now sit inside the 1044-char head budget.

Add a regression in pi-embedded-helpers.buildbootstrapcontextfiles.test.ts
that runs the actual stripped template through buildBootstrapContextFiles
with maxChars=1500 and asserts the truncation marker fires and the injected
content contains `## Tools`, `Tool dispatch:`, `## Red Lines`, and
`## External vs Internal`. This covers the real bootstrap injection path
the prior section-order tests did not exercise.

Refs openclaw#75187
@lonexreb
Copy link
Copy Markdown
Contributor Author

Thanks for the review — that was the bug. Force-pushed 205e83e which addresses the trimmer head-budget gap directly.

What changed:

  • Moved ## Tools directly after ## Session Startup and added an explicit Tool dispatch: rule (emit real structured tool calls, fix args on error rather than repeating). Tool-use guidance now lands at char ~555 (post-frontmatter), well inside the ~1044-char head window at bootstrapMaxChars: 1500.
  • Condensed ## Session Startup from a multi-list block into a single paragraph so the subsequent sections all sit inside the head window.
  • Split the secondary Voice Storytelling and Platform Formatting bullets out into a new ## Tool Notes section lower in the file — kept in the full template but no longer pushing critical content out of the head budget.

New section starts (post-frontmatter): First Run @72, Session Startup @220, Tools @555, Red Lines @846, External vs Internal @1021. All four load-bearing sections now sit inside the 1044-char head budget.

New regression test in src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts runs the actual stripped template through buildBootstrapContextFiles({ maxChars: 1500 }) and asserts:

  • the truncation marker fires (proving we are in the small-budget head/tail path)
  • the injected content contains ## Tools, Tool dispatch:, ## Red Lines, and ## External vs Internal

Acceptance criteria checked locally:

  • pnpm test src/agents/workspace-templates.test.ts — 6/6 pass
  • pnpm test src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts — 21/21 pass
  • pnpm exec oxfmt --check --threads=1 docs/reference/templates/AGENTS.md src/agents/workspace-templates.test.ts src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts — clean
  • git diff --check — clean

PTAL.

lonexreb added a commit to lonexreb/paloa-claw that referenced this pull request Apr 30, 2026
…head window

Codex round-2 review on PR openclaw#75248 noted that even after moving `## Tools`
into the head, `## External vs Internal` heading landed at char 1018 but
its safe/ask body bullets started at char 1067 — outside the trimmer's
~1044-char head window at `bootstrapMaxChars: 1500`. The injected content
kept the heading but lost the safe/ask policy bullets the issue explicitly
needs preserved, and the regression test only checked headings.

Restructure further:

- Reorder so `## External vs Internal` comes immediately after `## Tools`
  (before `## Red Lines`). With its smaller body, External vs Internal now
  sits entirely below the head boundary.
- Condense External vs Internal from per-bullet lists to inline paragraphs.
  The "safe / ask first" semantics are unchanged but the section is ~100
  chars shorter.
- Condense `## Session Startup` and the lead-in for `## Tools` so the
  cumulative chars before Red Lines drop low enough to keep its first
  rule ("Don't exfiltrate private data") in head as well.

New section starts (post-frontmatter): First Run @72, Session Startup @220,
Tools @477, External vs Internal @742 (Safe body @767, Ask body @879),
Red Lines @1003 (first bullet @1017). Tools dispatch rule, External vs
Internal safe + ask bullets, and the first Red Lines rule all fit inside
the 1044-char head window.

Tighten the regression in pi-embedded-helpers.buildbootstrapcontextfiles
test from heading-only assertions to body-text assertions: `structured
tool calls`, `Safe to do freely:`, `search the web`, `Ask first:`,
`anything that leaves the machine`, and `exfiltrate private data` must
all survive injection at `maxChars: 1500`. This catches the exact failure
mode the round-2 review highlighted.

Refs openclaw#75187
@lonexreb
Copy link
Copy Markdown
Contributor Author

Round-2 review addressed in 1e5fc71.

The bot was right — ## External vs Internal heading landed inside the head window but its safe/ask body bullets started at char 1067, outside the ~1044-char head, and my regression only asserted headings.

Changes:

  • Reordered so ## External vs Internal comes immediately after ## Tools (before ## Red Lines), and condensed from per-bullet lists into two inline paragraphs (**Safe to do freely:** ... / **Ask first:** ...). Same semantics, ~100 chars shorter.
  • Trimmed the lead-in sentence in ## Tools and a few words in ## Session Startup so cumulative chars before Red Lines drop low enough to keep Don't exfiltrate private data in head as well.

New section starts (post-frontmatter):

Section Char In head (≤1044)?
First Run 72
Session Startup 220
Tools 477
→ Tool dispatch rule ~620
External vs Internal 742
→ Safe body 767
→ Ask body 879
Red Lines 1003
→ first bullet (exfiltrate private data) 1017

Tightened the regression in pi-embedded-helpers.buildbootstrapcontextfiles.test.ts from heading-only checks to body-text assertions:

  • structured tool calls
  • Safe to do freely:
  • search the web
  • Ask first:
  • anything that leaves the machine
  • exfiltrate private data

All must survive buildBootstrapContextFiles({ maxChars: 1500 }) injection.

Acceptance criteria checked locally:

  • pnpm test src/agents/workspace-templates.test.ts src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts — 27/27 pass
  • pnpm exec oxfmt --check --threads=1 docs/reference/templates/AGENTS.md src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts — clean
  • git diff --check — clean

PTAL.

lonexreb added 4 commits May 3, 2026 03:07
… rules first

The auto-generated AGENTS.md template wrote less critical content (Memory,
Group Chats, Heartbeats) ahead of the load-bearing safety and tool-use
guidance (Red Lines, External vs Internal, Tools). Users lowering
agents.defaults.bootstrapMaxChars to fit small/mid model context budgets got
head-truncation that stripped exactly the rules small models need to
reliably emit structured tool calls.

Reorder so First Run -> Session Startup -> Red Lines -> External vs Internal
-> Tools come ahead of Memory/Group Chats/Heartbeats. The post-compaction
config already names 'Session Startup' and 'Red Lines' as the priority
sections to re-inject, so this reordering aligns the freshly seeded
workspace template with the existing post-compaction priority contract.

Refs openclaw#75187
…t head window

Codex review on PR openclaw#75248 noted that the prior reorder still left `## Tools`
starting at char ~1110 in the stripped template, outside the bootstrap
trimmer's effective ~1044-char head window at agents.defaults.bootstrapMaxChars=1500
(0.75 head ratio of contentBudget after marker reservation). The injected
content kept `Red Lines` and `External vs Internal` but dropped `Tools`
along with the tool-dispatch guidance, so the issue's small-model failure
mode would persist.

Restructure the workspace AGENTS.md template:

- Move `## Tools` directly after `## Session Startup` so its body appears
  in the head window. Add an explicit `Tool dispatch:` rule (emit real
  structured tool calls, fix args on error rather than repeating).
- Condense `## Session Startup` from a multi-list block into a single
  paragraph, freeing room before `## Tools` without losing semantics.
- Split the secondary `Voice Storytelling` and `Platform Formatting`
  bullets out into a new `## Tool Notes` section lower in the file. They
  remain available in the full file but no longer crowd the head budget.

Section starts (post-frontmatter): First Run @72, Session Startup @220,
Tools @555, Red Lines @846, External vs Internal @1021. All four
load-bearing sections now sit inside the 1044-char head budget.

Add a regression in pi-embedded-helpers.buildbootstrapcontextfiles.test.ts
that runs the actual stripped template through buildBootstrapContextFiles
with maxChars=1500 and asserts the truncation marker fires and the injected
content contains `## Tools`, `Tool dispatch:`, `## Red Lines`, and
`## External vs Internal`. This covers the real bootstrap injection path
the prior section-order tests did not exercise.

Refs openclaw#75187
…head window

Codex round-2 review on PR openclaw#75248 noted that even after moving `## Tools`
into the head, `## External vs Internal` heading landed at char 1018 but
its safe/ask body bullets started at char 1067 — outside the trimmer's
~1044-char head window at `bootstrapMaxChars: 1500`. The injected content
kept the heading but lost the safe/ask policy bullets the issue explicitly
needs preserved, and the regression test only checked headings.

Restructure further:

- Reorder so `## External vs Internal` comes immediately after `## Tools`
  (before `## Red Lines`). With its smaller body, External vs Internal now
  sits entirely below the head boundary.
- Condense External vs Internal from per-bullet lists to inline paragraphs.
  The "safe / ask first" semantics are unchanged but the section is ~100
  chars shorter.
- Condense `## Session Startup` and the lead-in for `## Tools` so the
  cumulative chars before Red Lines drop low enough to keep its first
  rule ("Don't exfiltrate private data") in head as well.

New section starts (post-frontmatter): First Run @72, Session Startup @220,
Tools @477, External vs Internal @742 (Safe body @767, Ask body @879),
Red Lines @1003 (first bullet @1017). Tools dispatch rule, External vs
Internal safe + ask bullets, and the first Red Lines rule all fit inside
the 1044-char head window.

Tighten the regression in pi-embedded-helpers.buildbootstrapcontextfiles
test from heading-only assertions to body-text assertions: `structured
tool calls`, `Safe to do freely:`, `search the web`, `Ask first:`,
`anything that leaves the machine`, and `exfiltrate private data` must
all survive injection at `maxChars: 1500`. This catches the exact failure
mode the round-2 review highlighted.

Refs openclaw#75187
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Auto-generated AGENTS.md puts load-bearing tool-use rules at the bottom; head-truncation by bootstrapMaxChars strips them

1 participant