fix(buzz-acp): deliver standing context once per session; use claude-agent-acp's system prompt route - #4183
Open
sumit-m wants to merge 3 commits into
Open
fix(buzz-acp): deliver standing context once per session; use claude-agent-acp's system prompt route#4183sumit-m wants to merge 3 commits into
sumit-m wants to merge 3 commits into
Conversation
Protocol-v1 agents received base prompt, persona, team instructions, core memory and canvas on every turn. Deliver them in the session's first message only; both legacy paths now render through a shared StandingContext. Signed-off-by: sumit-m <33051892+sumit-m@users.noreply.github.com>
The adapter has read _meta.systemPrompt since v0.6.0 and reports its version in initialize, so the capability is knowable without a probe. Replaces the protocol-version proxy with a per-adapter delivery decision; anything below the floor falls back to the user-message path. Signed-off-by: sumit-m <33051892+sumit-m@users.noreply.github.com>
…ity log The transcript read only session/new's top-level systemPrompt, so agents whose adapter takes it through _meta.systemPrompt rendered no System prompt card and their standing context was invisible. Signed-off-by: sumit-m <33051892+sumit-m@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Agents whose adapter reports
protocolVersion: 1— Claude and Codex — have no system role, sobase_prompt, the persona, team instructions, core memory and the canvas ride in the user message.format_promptre-sent all of it on every turn.That is roughly 9 KB of
base_prompt.mdalone, repeated per turn, plus persona and core. It makes the standing framing both the largest and the most recent text in the window, so it outweighs the conversation it exists to frame and evicts real channel history sooner. Related: #3126, #3242.Change
1. Deliver standing context once per session
New
queue::StandingContextholds base prompt, persona, team instructions, core and canvas, and renders them in one place. Both legacy dispatch paths — the initial message and the batch flush — go through it, so their section set and ordering cannot drift apart.run_prompt_tasktracks delivery with astanding_context_sentflag derived fromis_new_session, andformat_promptgates on it.is_new_sessioncomes from the session registry, which is cleared on every invalidation path, so a replacement session re-delivers rather than leaving the agent unbriefed.2. Give
claude-agent-acpa real system promptsystemPromptonsession/newis not part of ACP — it appears in neither the v1 nor the v2 schema — so gating it onprotocol_version >= 2is a proxy rather than a capability check.has_system_prompt_supportalready had to special-case goose for exactly this reason.claude-agent-acpdoes accept a system prompt, via_meta.systemPrompt, and has since v0.6.0 (2025-10-15, agentclientprotocol/claude-agent-acp#91). The object form merges over the adapter's ownclaude_codepreset withtype/presetlocked, so{ append }extends Claude Code's built-in prompt rather than replacing it — the same semantics as goose'smode: "append".standing_delivery()replaces the version proxy with a per-adapter decision, consulted by bothsession/newconstruction andformat_promptso the two cannot disagree:buzz-agentsystemPromptparamclaude-agent-acp>= 0.6.0_meta.systemPrompt = { append }No version probe was needed. The adapter reports
agentInfo.versionin theinitializeresponse the harness already makes and already parses for.name, so this is one extra field read rather than a subprocess spawn with its own timeout and failure mode. An absent or unparseable version is treated as unsupported: an unrecognised_metakey is silently ignored, and the failure mode there is an agent running with no Buzz instructions at all.3. Show the delivered prompt in the activity log
The transcript built its "System prompt" card from the top-level
params.systemPromptonly, so an agent taking the_metaroute would have rendered no card and its standing context would have been invisible. A newsessionNewSystemPrompthelper reads either route and feeds both through the existingparseSystemPromptSections, so one card renders whichever delivered it.Behaviour changes worth calling out
[Base]and the canvas. Currently a legacy agent takes its first action with no persona and no memory.[Base]. This is the most separable part of the change; happy to drop it if you would rather keep heartbeats as they are.prepend_canvas_for_legacyis removed andprepend_base_for_legacybecomesprepend_standing_for_legacy. Its doc comment already noted that the gate lived in one place "so the heartbeat and initial-message dispatch paths can't drift apart again"; this extends that to the section set itself.has_system_prompt_supportshort-circuits before the new gate is consulted.initializestill requestsprotocolVersion: 2, and the in-tree comment describing that as squatting ahead of the ACP RFD is unchanged. This only stops that number from standing in for a capability it does not describe.Codex
codex-acpreportsprotocolVersion: 1too and would benefit from the same treatment if it exposes an equivalent route. We have no access to Codex models, so we could not check the adapter's behaviour or test a change, and have left it on the user-message path — which this PR at least makes considerably cheaper.Verification
Tested live on Windows against a local relay, both paths in order:
[Base],[System]and[Agent Memory — core]; turn 2 opened at[Context]with none of them._metapath — a new session showed no standing sections in the user message at all, and the agent then reproducedbase_prompt.md's mentions guidance verbatim (the@Will Pflegerexample, partial names failing silently, no formatting on mentions,--mentionrepeatable, the CLI stopping before send on a non-member), stating it was replying from memory.cargo test -p buzz-acp --lib— 667 passing. The three failures on this machine are pre-existing onmain:keepalive_resets_idle_past_deadline(timing) and twosteertests that fail on Windows because of an unquoted temp path (#3733).pnpm test3886 passing,pnpm typecheckandbiome checkclean.New coverage: exactly-once delivery across turns, the version floor and both published adapter package names, the wire shape of
_meta.systemPromptasserted on the bytes sent,agentInfo.versionparsing, and the activity-log card rendering identically from either route.