Skip to main content

Overview

ReActChat is an agent that uses the ReAct (Reasoning and Acting) format for tool calling. It explicitly shows the agent’s thought process, actions, and observations in a structured format.

Class Signature

from qwen_agent.agents import ReActChat

class ReActChat(FnCallAgent):
    def __init__(
        self,
        function_list: Optional[List[Union[str, Dict, BaseTool]]] = None,
        llm: Optional[Union[Dict, BaseChatModel]] = None,
        system_message: Optional[str] = DEFAULT_SYSTEM_MESSAGE,
        name: Optional[str] = None,
        description: Optional[str] = None,
        files: Optional[List[str]] = None,
        **kwargs
    )

Constructor Parameters

function_list
List[Union[str, Dict, BaseTool]]
List of tools available to the agent
llm
Union[Dict, BaseChatModel]
LLM configuration or instance
system_message
str
System message (note: ReAct has its own prompt format)
name
str
Agent name
description
str
Agent description
files
List[str]
Files for tools requiring file access

ReAct Format

The agent uses the following structured format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [tool_names]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Methods

run

def run(
    self,
    messages: List[Union[Dict, Message]],
    lang: str = 'en',
    **kwargs
) -> Iterator[List[Message]]
Runs the agent using ReAct format.
messages
List[Union[Dict, Message]]
required
Conversation messages
lang
str
default:"en"
Language: ‘en’ or ‘zh’
return
Iterator[List[Message]]
Streaming response showing thought process

Usage Examples

Basic ReAct

from qwen_agent.agents import ReActChat
from qwen_agent.llm.schema import Message

agent = ReActChat(
    function_list=['code_interpreter'],
    llm={'model': 'qwen-max', 'api_key': 'your-api-key'}
)

messages = [
    Message(
        role='user',
        content='Calculate the sum of numbers from 1 to 100'
    )
]

for response in agent.run(messages):
    print(response[-1].content)

# Output shows ReAct format:
# Thought: I need to write code to calculate the sum
# Action: code_interpreter
# Action Input: sum(range(1, 101))
# Observation: 5050
# Thought: I now know the final answer
# Final Answer: The sum of numbers from 1 to 100 is 5050.

Multiple Tool Usage

agent = ReActChat(
    function_list=['web_extractor', 'code_interpreter'],
    llm={'model': 'qwen-max'}
)

messages = [
    Message(
        role='user',
        content='Find the population of Tokyo and calculate what 10% of it would be'
    )
]

for response in agent.run(messages):
    print(response[-1].content)

# Example output:
# Thought: I need to first find Tokyo's population
# Action: web_extractor
# Action Input: {"url": "https://en.wikipedia.org/wiki/Tokyo"}
# Observation: [web content about Tokyo]
# Thought: I found the population is about 14 million. Now I need to calculate 10%
# Action: code_interpreter
# Action Input: 14000000 * 0.1
# Observation: 1400000.0
# Thought: I now know the final answer
# Final Answer: 10% of Tokyo's population (14 million) is 1.4 million.

With File Processing

agent = ReActChat(
    function_list=['code_interpreter'],
    llm={'model': 'qwen-max'},
    files=['sales_data.csv']
)

messages = [
    Message(
        role='user',
        content='Analyze sales_data.csv and find the average sales'
    )
]

for response in agent.run(messages):
    print(response[-1].content)

Custom Tools with ReAct

from qwen_agent.tools.base import BaseTool, register_tool

@register_tool('database_query')
class DatabaseQuery(BaseTool):
    description = 'Query the customer database'
    parameters = {
        'type': 'object',
        'properties': {
            'query': {
                'type': 'string',
                'description': 'SQL query to execute'
            }
        },
        'required': ['query']
    }
    
    def call(self, params, **kwargs):
        params = self._verify_json_format_args(params)
        # Simulate database query
        return "Found 3 customers matching criteria"

agent = ReActChat(
    function_list=[DatabaseQuery(), 'code_interpreter'],
    llm={'model': 'qwen-max'}
)

messages = [
    Message(
        role='user',
        content='Find all customers from New York and count them'
    )
]

for response in agent.run(messages):
    print(response[-1].content)

Debugging Tool Calls

agent = ReActChat(
    function_list=['code_interpreter'],
    llm={'model': 'qwen-max'}
)

messages = [Message(role='user', content='Generate 5 random numbers')]

for response in agent.run(messages):
    content = response[-1].content
    print(content)
    print("-" * 50)
    
    # You can see each step:
    # - Thought process
    # - Which action is chosen
    # - Input parameters
    # - Tool results
    # - Final reasoning

Multi-turn Conversation

agent = ReActChat(
    function_list=['code_interpreter'],
    llm={'model': 'qwen-max'}
)

messages = []

# First question
messages.append(Message(role='user', content='Create a list [1,2,3,4,5]'))
for response in agent.run(messages):
    pass
messages.extend(response)

# Follow-up using previous context
messages.append(Message(role='user', content='Now square each number'))
for response in agent.run(messages):
    pass
messages.extend(response)

print(messages[-1].content)

ReAct vs Standard Function Calling

Standard FnCallAgent

from qwen_agent.agents import FnCallAgent

agent = FnCallAgent(function_list=['code_interpreter'], llm={'model': 'qwen-max'})
# Output: Clean final answer without explicit reasoning steps

ReActChat

from qwen_agent.agents import ReActChat

agent = ReActChat(function_list=['code_interpreter'], llm={'model': 'qwen-max'})
# Output: Shows Thought -> Action -> Observation -> Final Answer

Advantages of ReAct

  1. Transparency: See the agent’s reasoning process
  2. Debugging: Easier to understand why certain tools are called
  3. Interpretability: Clear step-by-step problem solving
  4. Educational: Good for understanding agent behavior

Limitations

  1. Verbosity: More output tokens consumed
  2. Speed: Slightly slower due to explicit reasoning
  3. Format strict: Requires LLM to follow specific format

Configuration

Stop Words

ReActChat automatically configures stop words:
# Stops at 'Observation:' to insert tool results
stop_words = ['Observation:', 'Observation:\n']

Custom System Message

# Note: ReAct prompt is automatically prepended
agent = ReActChat(
    function_list=['code_interpreter'],
    llm={'model': 'qwen-max'},
    system_message='Additional instructions here'
)

Prompt Template

The agent automatically constructs prompts like:
Answer the following questions as best you can. You have access to the following tools:

code_interpreter: Call this tool to interact with the code_interpreter API.
What is the code_interpreter API useful for? Python code sandbox...
Parameters: {...}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [code_interpreter]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {user_query}
Thought:

Advanced Usage

Extracting Reasoning Steps

agent = ReActChat(
    function_list=['code_interpreter'],
    llm={'model': 'qwen-max'}
)

messages = [Message(role='user', content='Calculate fibonacci(10)')]

steps = []
for response in agent.run(messages):
    content = response[-1].content
    
    # Parse ReAct steps
    if 'Thought:' in content:
        thoughts = content.split('Thought:')[1:]
        steps.extend(['Thought: ' + t.split('\n')[0] for t in thoughts])
    if 'Action:' in content:
        actions = content.split('Action:')[1:]
        steps.extend(['Action: ' + a.split('\n')[0] for a in actions])

print("Reasoning steps:")
for step in steps:
    print(f"  - {step}")

Error Handling

agent = ReActChat(
    function_list=['code_interpreter'],
    llm={'model': 'qwen-max'}
)

messages = [Message(role='user', content='Run: print(undefined)')]

for response in agent.run(messages):
    content = response[-1].content
    if 'Observation:' in content and 'Error' in content:
        print("Tool execution error detected in observation")
    print(content)

See Also

Build docs developers (and LLMs) love