llamaIndex - ✅(Solved) Fix [Bug]: ReActAgent not including system_prompt in ReActChatFormatter [1 pull requests, 2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
run-llama/llama_index#20872Fetched 2026-04-08 00:30:30
View on GitHub
Comments
2
Participants
3
Timeline
10
Reactions
1
Author
Timeline (top)
commented ×2labeled ×2referenced ×2closed ×1

Fix Action

Fix / Workaround

A very easy workaround we found for this was extending the ReActAgent and simply setting the formatter again after calling super.init:

PR fix notes

PR #20873: fix(react): pass system_prompt to ReActChatFormatter template

Description (problem / solution / changelog)

Summary

Fixes #20872

When creating a ReActAgent with system_prompt, the existing model_validator correctly sets formatter.context to the system prompt value. However, ReActChatFormatter.from_defaults() (called without context during default construction) selects REACT_CHAT_SYSTEM_HEADER -- a template that does not contain the {context} placeholder. As a result, even though formatter.context is set, it is never rendered into the final system prompt sent to the LLM.

Root cause

ReActChatFormatter has two header templates:

  • REACT_CHAT_SYSTEM_HEADER -- no {context} placeholder (used when no context is provided)
  • CONTEXT_REACT_CHAT_SYSTEM_HEADER -- includes {context} placeholder

The default_formatter() factory creates a formatter without context, so REACT_CHAT_SYSTEM_HEADER is selected. The validate_formatter model validator then sets formatter.context, but never switches the system_header template to the context-aware variant.

Fix

Added a check at the end of validate_formatter: when formatter.context is non-empty but system_header does not contain {context}, switch to CONTEXT_REACT_CHAT_SYSTEM_HEADER.

Changes

  • llama-index-core/llama_index/core/agent/workflow/react_agent.py: Import CONTEXT_REACT_CHAT_SYSTEM_HEADER and add template switch logic in validate_formatter
  • llama-index-core/tests/agent/react/test_prompt_customization.py: Add three test cases covering system_prompt propagation, default behavior without system_prompt, and system_prompt combined with custom formatter context

Test plan

  • test_system_prompt_passed_to_formatter -- verifies system_prompt is set as context, the context-aware template is used, and the prompt appears in formatted output
  • test_no_system_prompt_uses_default_template -- verifies default behavior is unchanged when no system_prompt is provided
  • test_system_prompt_with_custom_formatter_context -- verifies system_prompt is prepended to existing formatter context and template is switched
  • All 19 existing tests in tests/agent/react/ pass
  • test_react_agent_prompts in tests/agent/workflow/ passes

Changed files

  • llama-index-core/llama_index/core/agent/workflow/react_agent.py (modified, +4/-0)
  • llama-index-core/tests/agent/react/test_prompt_customization.py (modified, +40/-0)

Code Example

from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.agent.react.formatter import ReActChatFormatter


class ReActAgent(ReActAgent):
    """Custom wrapper around LlamaIndex's ReActAgent."""

    def __init__(
        self,
        system_prompt: str | None = None,
        *args,
        **kwargs
    ):
        super().__init__(*args, **kwargs)
        self.formatter = ReActChatFormatter.from_defaults(context=system_prompt)    # system_prompt is now actually being used

---
RAW_BUFFERClick to expand / collapse

Bug Description

When creating an instance of ReActAgent with system_prompt included in the constructor, the class variable formatter in ReActAgent is created without using the system_prompt, preventing the system_prompt from being injected as context into ReActChatFormatter.

On line 44, the default_formatter method is set for the formatter but the system_prompt is not passed.

https://github.com/run-llama/llama_index/blob/eda20206a2750d76cd37428d5df9570a6cc5f301/llama-index-core/llama_index/core/agent/workflow/react_agent.py#L30C1-L45C20

As a result when the ReActChatFormatter is created using from_defaults, context is None, removing the {context_prompt} from the system_header_template.

Version

0.14.15

Steps to Reproduce

  1. Initialize a ReActAgent with system_prompt included in the constructor.
  2. Notice the system prompt is not included in the ReActAgent's internal prompting

A very easy workaround we found for this was extending the ReActAgent and simply setting the formatter again after calling super.init:

from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.agent.react.formatter import ReActChatFormatter


class ReActAgent(ReActAgent):
    """Custom wrapper around LlamaIndex's ReActAgent."""

    def __init__(
        self,
        system_prompt: str | None = None,
        *args,
        **kwargs
    ):
        super().__init__(*args, **kwargs)
        self.formatter = ReActChatFormatter.from_defaults(context=system_prompt)    # system_prompt is now actually being used

Relevant Logs/Tracbacks

extent analysis

Fix Plan

Fix Name

Customize ReActAgent to pass system_prompt to formatter

Steps to Fix

  1. Extend ReActAgent: Create a new class that inherits from ReActAgent.
  2. Override init method: Define the __init__ method in the new class to call the parent class's __init__ method using super().__init__(*args, **kwargs).
  3. Set formatter with system_prompt: Set the formatter attribute of the new class to ReActChatFormatter.from_defaults(context=system_prompt).

Example Code

from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.agent.react.formatter import ReActChatFormatter

class CustomReActAgent(ReActAgent):
    def __init__(
        self,
        system_prompt: str | None = None,
        *args,
        **kwargs
    ):
        super().__init__(*args, **kwargs)
        self.formatter = ReActChatFormatter.from_defaults(context=system_prompt)

Verification

  1. Create an instance of CustomReActAgent with a system prompt.
  2. Check that the formatter attribute is set correctly with the system prompt.
  3. Verify that the system prompt is injected as context into ReActChatFormatter.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

llamaIndex - ✅(Solved) Fix [Bug]: ReActAgent not including system_prompt in ReActChatFormatter [1 pull requests, 2 comments, 3 participants]