Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

fix(chat-harness): stub subagent prompts to stop context overflow

merged#2725CedarCopilot

CedarCopilot wants to merge 1 commit into staging from fix/chat-subagent-prompt-stub

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Sep 8, 2026, 8:39 AM
  2. Sep 8, 2026, 8:44 AM
  3. Merged
    Sep 8, 2026, 11:08 AM
  4. Live on prod
    Sep 8, 2026, 11:08 AM
  5. Observed 2 days
    Sep 8, 2026, 11:08 AM
  6. Pipelines steady after this deploy
    Sep 8, 2026, 11:08 AM
  7. Unobserved

    Live on prod, no production signal yet

    Sep 10, 2026, 9:44 PM

Behaviors Libra is checking

When a native subagent is actually delegated to, its stub instructs it to read the full playbook from `subagent.documentPath` with `document({ action: "read" })` before performing work.Inconclusivehigh confidence

Since 2026-09-08T18:08:15Z, telemetry shows only 1 successful `execute_tool read-document` span (228 ms, trace <id>), with a successful read of `#resources/email-wiki/scheduled-followup.md`; it is not in a trace containing native `invoke_agent` delegation. Native-looking.

prod, checked Sep 10, 2026, 9:44 PM
Configured chat subagents use a short fixed-size prompt stub instead of embedding their full playbook instructions, preventing parent chat turns from exceeding the model context limit and avoiding unnecessary prompt token charges.Inconclusivelow confidence

Verification reached its budget before a verdict.

prod, checked Sep 10, 2026, 9:44 PM

Libra has verdicts on 0 of 2 tracked behaviors on prod; 2 are still being checked. Libra checks hourly for 3 days after each deploy.

Summary

  • The Claude Agent SDK bills the ENTIRE prompt of every configured options.agents entry as input/cache-creation tokens on every parent chat turn, regardless of whether that subagent is ever actually delegated to via Task , confirmed empirically against the real SDK (one dummy subagent with a 189,000-char prompt, a task that never delegates, single turn: the full prompt was still billed).
  • buildSubagentDefinitions (apps/server/src/mastra/workflows/chat/harness/subagents.ts) was inlining each AOP subagent's entire playbook-doc instruction body into prompt , 700 to 24,000+ chars per subagent, 118,786-151,293 chars total across 16-17 subagents on two real accounts. This is the direct, root-caused source of two production "Prompt is too long" / 200K-token context-overflow incidents on accounts with many/large subagents (not a regression , present since the harness's introduction, a4252556a, 2026-07-16).
  • Fix: prompt is now a short, fixed-size stub per subagent that instructs the model to load the real instructions itself via document({ action: "read", read: { path: subagent.documentPath } }) the moment it's actually invoked , mirroring the load-skill progressive-disclosure pattern already used elsewhere in this harness. That cost now lands only in the delegate's own nested context on the turns it's actually used, never on the parent's every turn. description is untouched.

Test plan

  • pnpm --filter @zero/server run types , clean, no errors.
  • pnpm --filter @zero/server exec vitest run src/mastra/workflows/chat/__tests__/agent-bound-chat.test.ts , 16/16 passed (14 pre-existing + 2 new tests, extending the existing buildSubagentDefinitions coverage in that file rather than adding a new test file).
    • New test 1: a subagent with a multi-thousand-char instructions body produces a prompt under 1000 chars that contains documentPath and does NOT contain the raw long body verbatim; description stays exactly the frontmatter description.
    • New test 2: a subagent with no description gets the correct fallback sentence in the stub, while description keeps its own separate (pre-existing) fallback to subagent.name.
  • Ran /thermo-review against the diff (scoped to the two touched files). No šŸ”“ blocking or 🟔 should-fix findings. One 🟢 nit noted and left as-is: a doc comment in services/playbook/subagents.ts (explicitly out of this PR's scope) references buildSubagentDefinitions as an example consumer of the full instruction body , that example is now stale since this fix, though the field itself remains genuinely used by other real callers (orchestrator-dispatch-tools.ts, updateNextStepsAndTasksTool.ts, strategist-updates.ts, daily-agenda.ts), so nothing is dead code. Flagged as a follow-up, not blocking.

šŸ¤– Generated with Claude Code

https://claude.ai/code/session_01BWvDYfrsL4PAK3iqd3AzQU

Greptile Summary

This PR replaces inline subagent playbook instructions with an on-demand document read to reduce parent-chat context usage.

  • Adds compact delegate prompt stubs containing each subagent's document path.
  • Adds tests covering large instruction bodies and missing descriptions.
  • The on-demand read needs an authorization exception for delegates with scoped file grants, and the stub remains unbounded through description metadata.

Confidence Score: 4/5

The PR is not safe to merge until scoped delegates can reliably read their own instruction document and the explicit type-assertion rule violation is removed.

The new mandatory document read is denied for delegates whose scoped file grant omits the separate playbook path, causing those delegates to run without their operating instructions; the prompt-size guarantee also remains incomplete because descriptions are unbounded.

Files Needing Attention: apps/server/src/mastra/workflows/chat/harness/subagents.ts; apps/server/src/ma

Show production surfaces and changed-file mapping

Production surfaces

Libra has not measured any production surfaces for this change yet.

Changed files → surfaces

  • apps/server/src/mastra/workflows/chat/__tests__/agent-bound-chat.test.tsno production surface mapped
  • apps/server/src/mastra/workflows/chat/harness/subagents.tsno production surface mapped