feat(prompt_builder): add GROK_EXECUTION_GUIDANCE to suppress narration without tool calls - #7138
Conversation
Grok reasoning models have a failure mode where they describe planned
actions in text ("I will check X", "Je vais lancer Y") without
actually calling the corresponding tools. The existing
TOOL_USE_ENFORCEMENT_GUIDANCE mitigates the "action reflex" trait
(NousResearch#5595) but doesn't address the narration-vs-execution split that is
specific to reasoning architectures.
Add GROK_EXECUTION_GUIDANCE — a targeted system prompt block injected
alongside TOOL_USE_ENFORCEMENT_GUIDANCE when the model name contains
"grok". Three XML-tagged sections:
- <no_intent_phrases>: explicit list of forbidden phrases in English
and French ("I will...", "Let me...", "Je vais...", etc.) with
the rule: if you need to act, call the tool now; do not narrate
the intent.
- <execute_first>: mandate that the first response to any work-implying
request contain a tool call, not a plan. Chain multiple tool calls
in the same turn without intermediate prose.
- <no_analysis_hallucination>: forbid structured analyses, diagnosis
lists, or recommendations produced from pure reasoning without tool
calls to verify the claims.
Injected in run_agent.py next to the existing provider-specific guidance
blocks (OPENAI_MODEL_EXECUTION_GUIDANCE, GOOGLE_MODEL_OPERATIONAL_GUIDANCE).
Tests (6 new in TestGrokExecutionGuidance):
- Verifies XML tag structure
- Asserts intent-phrase examples are present in both English and French
- Asserts the execute-first mandate is documented
- Asserts the no-analysis-hallucination rule is present
- Size and type checks
124 passed, 1 skipped in tests/agent/test_prompt_builder.py (no regression).
NOT YET PUSHED as a PR. To be dogfooded on the author's production
instance on xAI before upstream submission, given the precedent of
'behavioral' patches being classified as prostheses in prior work.
Closing this PR — diagnostic was incompleteAfter a full day of dogfooding on my own instance, I'm closing this. The patch targets a symptom, not the root cause, and I'd rather pull it than let upstream merge something I no longer stand behind. What I saw todayI ran a proper audit of seven production sessions (a mix of Grok 4.20-reasoning, Opus 4.6, and GLM 5.1), tracing user → tool calls → tool results → final text chronologically. The data contradicts my original framing:
This pattern — synthesizing a confident completion claim that the recent tool results do not support — is what's actually hurting reliability. And it's not Grok-exclusive: in another session the same day, Opus 4.6 produced a multi-paragraph audit of a client instance without running a single tool, admitting when confronted: "Rien. Je n'ai lancé aucun tool, aucun grep sur ses sessions JSONL, aucun comptage de tool calls, aucune analyse de compression." A prompt block that forbids Why the "A/B evidence" in the original PR body was misleadingThe session I referenced ( What I'm pursuing insteadA model-agnostic guard that runs at the tail of the openai_chat / anthropic_messages loop: when the assistant produces a final response without tool calls, check whether the text makes completion claims ( This fixes the same class of bug for Grok, Opus, GLM, and Sonnet all at once, which matches what the empirical data shows. I'll prototype it on my fork first, dogfood against real sessions from today, then open a new PR if it holds up. For reviewers who already started lookingSorry for the churn. Keeping the other xAI-support work on track:
Those are plumbing — they improve xAI integration for any future model using that endpoint, and they're independent of whether Grok itself is the right agent model. Happy to keep iterating on those. Closing with thanks for the consideration. |
Problem
Grok reasoning models (
grok-4.20-*,grok-4-1-fast-*,grok-4-fast-*) have a narration-vs-execution failure mode that is not addressed by the existingTOOL_USE_ENFORCEMENT_GUIDANCE(added to cover Grok in #5595).Because Grok's reasoning happens internally and the final response is a separate pass, Grok tends to output intent phrases describing planned actions without actually calling the corresponding tools:
Then the assistant turn ends. The user sees a plan, no execution. When corrected, Grok says "You're right, let me do it now" — and again produces no tool call. I had a 10+ minute session this morning correcting this exact pattern three consecutive times on a remote-audit task before Grok finally chained the real tool calls.
TOOL_USE_ENFORCEMENT_GUIDANCE("use tools when taking an action") is interpreted by Grok as "use tools when you are taking an action" rather than "don't describe actions, execute them" — a subtle but critical difference for multi-turn agent workloads.A related symptom: Grok produces structured analyses from pure reasoning (lists of "possible causes", "things to check", diagnostics) without calling a single tool to verify the underlying claims. The output looks credible because reasoning models are good at structured prose — but the grounding is absent.
Solution
Add
GROK_EXECUTION_GUIDANCE— a Grok-specific system prompt block injected alongsideTOOL_USE_ENFORCEMENT_GUIDANCEwhen the model name contains "grok". Three XML-tagged sections (same style as the existingOPENAI_MODEL_EXECUTION_GUIDANCEadded in a prior PR):Injected in
run_agent.pynext to the existing provider-specific guidance blocks (OPENAI_MODEL_EXECUTION_GUIDANCE,GOOGLE_MODEL_OPERATIONAL_GUIDANCE), behind the sameTOOL_USE_ENFORCEMENT_MODELSgate.Production A/B evidence (same-day, same-session, same task)
This PR was written and tested in response to a production failure. I kept the broken session around and re-ran the exact same task after applying the patch. Result:
Before the patch (this morning, Grok 4.20-0309-reasoning, session
20260410_102501_800b5bd8.jsonl)After the patch (same session, same task, ~2h later)
Only variable: presence of
GROK_EXECUTION_GUIDANCEin the system prompt. Same session file (assistant had the previous chaotic history in context, yet behaved correctly once the guidance was active — which also validates that the guidance survives session pollution).The session file is available in the commit history of the author's fork if the maintainers want to inspect the raw JSONL before/after.
Testing
Added
TestGrokExecutionGuidance(6 tests) intests/agent/test_prompt_builder.pyfollowing the exact pattern ofTestOpenAIModelExecutionGuidance:test_guidance_forbids_intent_phrases— asserts the<no_intent_phrases>section is present with English and French examplestest_guidance_mandates_execute_first— asserts the execute-first mandatetest_guidance_blocks_analysis_hallucination— asserts the<no_analysis_hallucination>sectiontest_guidance_uses_xml_tags— asserts all three XML blocks are present with open and close tagstest_guidance_mentions_french_phrases— asserts multilingual coveragetest_guidance_is_string— type and size checksNo regression on the existing
TestToolUseEnforcementModelsorTestOpenAIModelExecutionGuidanceclasses.Why not just extend
TOOL_USE_ENFORCEMENT_GUIDANCE?I considered it. Three reasons for a separate block instead:
OPENAI_MODEL_EXECUTION_GUIDANCEandGOOGLE_MODEL_OPERATIONAL_GUIDANCEalready exist as separate provider-specific blocks injected alongside the general enforcement guidance. This PR follows the same pattern — no new architectural precedent.TOOL_USE_ENFORCEMENT_GUIDANCEstill runs for Grok (I'm the author of the PR that added Grok to the tuple, feat: add grok to TOOL_USE_ENFORCEMENT_MODELS for direct xAI usage #5595). This block adds on top of it, not instead.Impact
x-grok-conv-idprompt caching inrun_agent.py(feat: add xAI prompt caching via x-grok-conv-id header #5604)"grok"inTOOL_USE_ENFORCEMENT_MODELS(feat: add grok to TOOL_USE_ENFORCEMENT_MODELS for direct xAI usage #5595)DEFAULT_CONTEXT_LENGTHSGrok fallbacks (fix(model_metadata): add xAI Grok context length fallbacks #7093, merged earlier today)Related