This document describes the Agent component's tool integration system and its implementation of the ReAct (Reasoning + Acting) pattern for multi-step problem solving. The Agent component extends the base LLM component (8.3) to orchestrate iterative workflows where language models reason about tasks, invoke external tools, observe results, and synthesize final answers.
For general information about the Canvas workflow system and component architecture, see Canvas Engine and DSL and Component System Architecture. For details on the base LLM component without tool use, see Built-in Components.
The Agent component is a specialized LLM component that implements ReAct-style tool use. Unlike a standard LLM component that generates text responses, the Agent can:
The Agent component is defined in agent/component/agent_with_tools.py83-428 with parameter configuration in agent/component/agent_with_tools.py38-80
| Feature | LLM Component | Agent Component |
|---|---|---|
| Base class | ComponentBase | LLM + ToolBase |
| Output | Text generation | Text + tool use results |
| Iterations | Single-shot | Multi-turn (max_rounds) |
| Tool access | None | Built-in, MCP, plugins |
| Prompt structure | System + user messages | Task analysis + planning prompts |
| Use case | Direct Q&A | Complex multi-step tasks |
Sources: agent/component/agent_with_tools.py83-118 agent/component/llm.py82-91
Diagram 1: Tool Integration Architecture
Sources: agent/component/agent_with_tools.py86-117 agent/tools/base.py50-75
Built-in tools are RAGFlow components configured as tools. Any component implementing ToolBase can be used as a tool by the Agent. During initialization, the Agent loads tool configurations and instantiates component objects:
The _load_tool_obj() method (agent/component/agent_with_tools.py119-130) creates a unique component ID by appending the agent's ID as a prefix (e.g., agent_0-->wikipedia_search_0), enabling hierarchical tool tracing.
Common Built-in Tools:
Sources: agent/component/agent_with_tools.py119-130
MCP tools are external tools hosted by MCP servers following the Model Context Protocol. The Agent connects to MCP servers and dynamically fetches available tools:
MCP servers can be SSE-based or Streamable HTTP. The MCPToolCallSession (common/mcp_tool_call_conn.py42-226) manages the connection lifecycle and provides a synchronous interface to async MCP operations:
list_tools() to fetch available toolscall_tool(name, arguments) with timeoutSources: agent/component/agent_with_tools.py108-114 common/mcp_tool_call_conn.py42-226
All tools expose metadata in OpenAI function calling format:
Tool parameters are defined via ToolParamBase (agent/tools/base.py77-123) which auto-generates metadata from the meta dictionary:
Sources: agent/tools/base.py77-123
The ReAct (Reasoning + Acting) pattern enables multi-turn problem solving through iterative planning, tool use, and reflection. The Agent component implements this in _react_with_tools_streamly_async_simple() (agent/component/agent_with_tools.py278-419).
Diagram 2: ReAct Loop Flow
Sources: agent/component/agent_with_tools.py278-419
Before entering the ReAct loop, the Agent builds a comprehensive task description that includes:
For multi-turn conversations (history > 3 messages), the Agent optimizes the user request by calling full_question() (rag/prompts/generator.py224-256), which reformulates the latest query considering conversation context.
Sources: agent/component/agent_with_tools.py283-305 rag/prompts/generator.py224-256
The next_step_async() function (rag/prompts/generator.py395-414) is the core planning mechanism. It uses a specialized prompt to ask the LLM: "What's the next tool to call?"
Planning Prompt Structure (NEXT_STEP template):
The LLM responds with a JSON array of tool calls:
If the LLM determines it has sufficient information, it calls the special complete_task function:
Sources: rag/prompts/generator.py395-414 agent/component/agent_with_tools.py376-382
When the LLM selects tools, the Agent executes them in parallel using asyncio.gather():
Each tool is invoked through the LLMToolPluginCallSession (agent/tools/base.py50-75), which:
invoke() or invoke_async() methodThe callback function logs all tool invocations to Redis for tracing:
Sources: agent/component/agent_with_tools.py394-409 agent/tools/base.py50-75 agent/canvas.py779-801
After tools execute, the Agent constructs an "Observation" message summarizing results:
This observation is appended to the conversation history as a user message, allowing the LLM to "see" tool results in the next planning iteration:
Example observation:
Observation:
[retrieval_0 result]
ID: 123
Title: RAGFlow Documentation
Content: RAGFlow is an open-source RAG engine...
[wikipedia_search_0 result]
Docker is a platform for developing...
Sources: agent/component/agent_with_tools.py355-410
When the LLM calls complete_task, the Agent generates the final answer:
If citation is enabled (cite=True) and retrieval chunks exist, the Agent either:
citation_prompt() to system prompt before generation_gen_citations_async() to insert [ID:xxx] referencesSources: agent/component/agent_with_tools.py320-353
Diagram 3: Tool Calling Session Flow
The LLMToolPluginCallSession class (agent/tools/base.py50-75) provides a unified interface for invoking heterogeneous tools:
Key responsibilities:
thread_pool_exec() for non-blocking executionSources: agent/tools/base.py50-75
The Agent maintains conversation state across multiple ReAct iterations through the hist variable, which accumulates:
To prevent context overflow, the Agent implements history truncation strategies:
Strategy 1: Recent message window (agent/component/agent_with_tools.py335-336)
Keeps system message, initial user query, and last 10 messages.
Strategy 2: Multi-turn optimization (agent/component/agent_with_tools.py283-287)
Reformulates the query to be self-contained using full_question() prompt.
The Canvas maintains a memory list (agent/canvas.py316) storing tool call summaries:
Memory summaries are generated by tool_call_summary() (rag/prompts/generator.py448-456):
This creates concise summaries of tool interactions for long-term context.
Sources: agent/component/agent_with_tools.py283-336 agent/canvas.py316-827 rag/prompts/generator.py448-456
The Agent supports real-time streaming of tool use and final answers through async generators:
When connected to the Canvas SSE endpoint (api/apps/canvas_app.py132-186), the Agent emits structured events:
Tool Execution Events:
Message Streaming:
Tool Trace:
The frontend can retrieve full execution traces via /canvas/trace?canvas_id=xxx&message_id=yyy (api/apps/canvas_app.py551-562).
Sources: agent/component/agent_with_tools.py256-276 api/apps/canvas_app.py132-562
The AgentParam class (agent/component/agent_with_tools.py38-80) extends LLMParam with tool-specific configuration:
| Parameter | Type | Description | Default |
|---|---|---|---|
llm_id | string | LLM model identifier | Required |
sys_prompt | string | System-level instructions | "" |
tools | list | Built-in component tool configs | [] |
mcp | list | MCP server configurations | [] |
max_rounds | int | Maximum ReAct iterations | 5 |
cite | bool | Enable citation insertion | true |
max_tokens | int | Max generation length | 0 (unlimited) |
temperature | float | Sampling temperature | 0 |
description | string | Tool description override | "" |
custom_header | dict | Custom HTTP headers for MCP | {} |
Tool Configuration Schema:
MCP Configuration Schema:
Sources: agent/component/agent_with_tools.py38-80
The Agent implements comprehensive error handling at multiple levels:
Tool execution errors are caught and returned as string results:
The Agent treats tool errors as observations and continues the ReAct loop, allowing the LLM to recover by trying alternative tools.
JSON parsing errors during tool selection trigger recovery prompts:
The Agent checks for cancellation at multiple points using check_if_canceled() (agent/component/base.py393-405):
Cancellation is coordinated through Redis flags (agent/canvas.py269-278):
Sources: agent/tools/base.py144-153 agent/component/agent_with_tools.py412-418 agent/component/base.py393-405 agent/canvas.py269-278
Agent components are registered through the component class discovery system. The component_class() function (agent/component/__init__.py) dynamically imports component classes:
This enables dynamic tool loading without hardcoded imports, supporting extensibility through plugins.
For details on component registration and dynamic loading, see Component Dynamic Loading.
Refresh this wiki