Skip to content

Commit 205e83e

Browse files
committed
fix(agents): keep AGENTS.md tool-dispatch guidance inside small-budget head window
Codex review on PR #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 #75187
1 parent b5bdfd1 commit 205e83e

2 files changed

Lines changed: 42 additions & 22 deletions

File tree

docs/reference/templates/AGENTS.md

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,13 @@ If `BOOTSTRAP.md` exists, that's your birth certificate. Follow it, figure out w
1515

1616
## Session Startup
1717

18-
Use runtime-provided startup context first.
18+
Use runtime-provided startup context first. It may already include `AGENTS.md`, `SOUL.md`, `USER.md`, recent `memory/YYYY-MM-DD.md` files, and `MEMORY.md` (main session only). Don't reread startup files unless the user asks, the provided context is missing something you need, or you need a deeper follow-up read.
1919

20-
That context may already include:
21-
22-
- `AGENTS.md`, `SOUL.md`, and `USER.md`
23-
- recent daily memory such as `memory/YYYY-MM-DD.md`
24-
- `MEMORY.md` when this is the main session
20+
## Tools
2521

26-
Do not manually reread startup files unless:
22+
Skills provide your tools. When you need one, read its `SKILL.md`. Keep local notes (cameras, SSH, voice prefs) in `TOOLS.md`.
2723

28-
1. The user explicitly asks
29-
2. The provided context is missing something you need
30-
3. You need a deeper follow-up read beyond the provided startup context
24+
**Tool dispatch:** Emit real structured tool calls — don't describe a tool call in prose. If a tool errors, fix the args; don't repeat the same call.
3125

3226
## Red Lines
3327

@@ -50,18 +44,6 @@ Do not manually reread startup files unless:
5044
- Anything that leaves the machine
5145
- Anything you're uncertain about
5246

53-
## Tools
54-
55-
Skills provide your tools. When you need one, check its `SKILL.md`. Keep local notes (camera names, SSH details, voice preferences) in `TOOLS.md`.
56-
57-
**🎭 Voice Storytelling:** If you have `sag` (ElevenLabs TTS), use voice for stories, movie summaries, and "storytime" moments! Way more engaging than walls of text. Surprise people with funny voices.
58-
59-
**📝 Platform Formatting:**
60-
61-
- **Discord/WhatsApp:** No markdown tables! Use bullet lists instead
62-
- **Discord links:** Wrap multiple links in `<>` to suppress embeds: `<https://example.com>`
63-
- **WhatsApp:** No headers — use **bold** or CAPS for emphasis
64-
6547
## Memory
6648

6749
You wake up fresh each session. These files are your continuity:
@@ -137,6 +119,16 @@ Reactions are lightweight social signals. Humans use them constantly — they sa
137119

138120
**Don't overdo it:** One reaction per message max. Pick the one that fits best.
139121

122+
## Tool Notes
123+
124+
**🎭 Voice Storytelling:** If you have `sag` (ElevenLabs TTS), use voice for stories, movie summaries, and "storytime" moments! Way more engaging than walls of text. Surprise people with funny voices.
125+
126+
**📝 Platform Formatting:**
127+
128+
- **Discord/WhatsApp:** No markdown tables! Use bullet lists instead
129+
- **Discord links:** Wrap multiple links in `<>` to suppress embeds: `<https://example.com>`
130+
- **WhatsApp:** No headers — use **bold** or CAPS for emphasis
131+
140132
## 💓 Heartbeats - Be Proactive!
141133

142134
When you receive a heartbeat poll (message matches the configured heartbeat prompt), don't just reply `HEARTBEAT_OK` every time. Use heartbeats productively!

src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,34 @@ describe("buildBootstrapContextFiles", () => {
190190
expect(result[0]?.content.startsWith("[MISSING]")).toBe(true);
191191
});
192192

193+
it("preserves load-bearing tool-use guidance from the AGENTS.md template at the small-model bootstrap budget", async () => {
194+
// Regression for #75187: at agents.defaults.bootstrapMaxChars=1500 (typical
195+
// small/mid-model trim) the trimmer reserves a marker plus tail, so only the
196+
// first ~1k characters of the template's head survive. The auto-generated
197+
// workspace AGENTS.md must keep tool-dispatch guidance, Red Lines, and
198+
// External vs Internal action policy inside that head window so small models
199+
// get the rules they need to emit structured tool calls.
200+
const templatePath = path.resolve("docs", "reference", "templates", "AGENTS.md");
201+
const raw = await fs.readFile(templatePath, "utf-8");
202+
const stripped = raw.startsWith("---")
203+
? raw.slice(raw.indexOf("\n---", 3) + "\n---".length).replace(/^\s+/, "")
204+
: raw;
205+
206+
const files = [makeFile({ name: DEFAULT_AGENTS_FILENAME, content: stripped })];
207+
const [result] = buildBootstrapContextFiles(files, { maxChars: 1500 });
208+
209+
expect(result?.content).toBeTruthy();
210+
const injected = result?.content ?? "";
211+
// Truncation marker proves we're in the small-budget head/tail path the
212+
// issue describes, not just returning the file untrimmed.
213+
expect(injected).toContain("[...truncated, read AGENTS.md for full content");
214+
// The three load-bearing sections must all survive head-truncation.
215+
expect(injected).toContain("## Tools");
216+
expect(injected).toContain("Tool dispatch:");
217+
expect(injected).toContain("## Red Lines");
218+
expect(injected).toContain("## External vs Internal");
219+
});
220+
193221
it("skips files with missing or invalid paths and emits warnings", () => {
194222
const malformedMissingPath = {
195223
name: "SKILL-SECURITY.md",

0 commit comments

Comments
 (0)