refactor(steer): simplify injection marker to 'User guidance:' prefix (#13340)

The mid-run steer marker was '[USER STEER (injected mid-run, not tool
output): <text>]'. Replaced with a plain two-newline-prefixed
'User guidance: <text>' suffix.

Rationale: the marker lives inside the tool result's content string
regardless of whether the tool returned JSON, plain text, an MCP
result, or a plugin result. The bracketed tag read like structured
metadata that some tools (terminal, execute_code) could confuse with
their own output formatting. A plain labelled suffix works uniformly
across every content shape we produce.

Behavior unchanged:
- Still injected into the last tool-role message's content.
- Still preserves multimodal (Anthropic) content-block lists by
  appending a text block.
- Still drained at both sites added in #12959 and #13205 — per-tool
  drain between individual calls, and pre-API-call drain at the top
  of each main-loop iteration.

Checked Codex's equivalent (pending_input / inject_user_message_without_turn
in codex-rs/core): they record mid-turn user input as a real role:user
message via record_user_prompt_and_emit_turn_item(). That's cleaner for
their Responses-API model but not portable to Chat Completions where
role alternation after tool_calls is strict. Embedding the guidance in
the last tool result remains the correct placement for us.

Validation: all 21 tests in tests/run_agent/test_steer.py pass.
This commit is contained in:
Teknium
2026-04-20 22:18:49 -07:00
committed by GitHub
parent dbb7e00e7e
commit 70d7f79bef
2 changed files with 13 additions and 12 deletions

View File

@@ -3683,7 +3683,7 @@ class AIAgent:
existing = getattr(self, "_pending_steer", None)
self._pending_steer = (existing + "\n" + steer_text) if existing else steer_text
return
marker = f"\n\n[USER STEER (injected mid-run, not tool output): {steer_text}]"
marker = f"\n\nUser guidance: {steer_text}"
existing_content = messages[target_idx].get("content", "")
if not isinstance(existing_content, str):
# Anthropic multimodal content blocks — preserve them and append
@@ -8979,7 +8979,7 @@ class AIAgent:
for _si in range(len(messages) - 1, -1, -1):
_sm = messages[_si]
if isinstance(_sm, dict) and _sm.get("role") == "tool":
marker = f"\n\n[USER STEER (injected mid-run, not tool output): {_pre_api_steer}]"
marker = f"\n\nUser guidance: {_pre_api_steer}"
existing = _sm.get("content", "")
if isinstance(existing, str):
_sm["content"] = existing + marker