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 (note: ReAct has its own prompt format)
Files for tools requiring file access
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
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.
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)
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)
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
- Transparency: See the agent’s reasoning process
- Debugging: Easier to understand why certain tools are called
- Interpretability: Clear step-by-step problem solving
- Educational: Good for understanding agent behavior
Limitations
- Verbosity: More output tokens consumed
- Speed: Slightly slower due to explicit reasoning
- 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
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