Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
e9a40cd
feature:my test
yuehua-s Jul 11, 2025
2bf8fe2
Merge branch 'main' of https://github.com/yuehua-s/deer-flow into fea…
yuehua-s Jul 15, 2025
b868081
feature:my test
yuehua-s Jul 17, 2025
937e905
Merge branch 'main' of https://github.com/yuehua-s/deer-flow into fea…
yuehua-s Jul 17, 2025
66a189e
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
31e4d37
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
c05ad84
Merge branch 'main' of https://github.com/yuehua-s/deer-flow into fea…
yuehua-s Jul 20, 2025
ff36d14
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
d2b209f
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
cf0774c
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
dc00098
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
64662f4
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
77e3634
feature:support planner get mcp-tools.
yuehua-s Jul 20, 2025
89c7d72
feature:support planner get mcp-tools.
yuehua-s Jul 21, 2025
f091fae
feature:support planner get mcp-tools.
yuehua-s Jul 21, 2025
c0c63ef
feature:support planner get mcp-tools.
yuehua-s Jul 21, 2025
7165a70
feature:support planner get mcp-tools.
yuehua-s Jul 21, 2025
3d6b6fb
feature:support planner get mcp-tools.
yuehua-s Jul 21, 2025
4931447
feature:support planner get mcp-tools.
yuehua-s Jul 21, 2025
e2d05f0
feature:support planner get mcp-tools.
yuehua-s Jul 22, 2025
6365554
Merge branches 'feature/tke' and 'main' of https://github.com/yuehua-…
yuehua-s Jul 22, 2025
a2adaa0
feature:tke
yuehua-s Jul 22, 2025
fd76014
feature:support planner get mcp-tools.
yuehua-s Jul 22, 2025
cf3188f
fix:ui
yuehua-s Jul 22, 2025
ab0eccd
fix:ui bug
yuehua-s Jul 22, 2025
6b9013c
Merge branch 'main' of https://github.com/yuehua-s/deer-flow into fea…
yuehua-s Jul 23, 2025
bd5992f
feature:docker
yuehua-s Jul 27, 2025
fc00470
Merge branch 'main' of https://github.com/yuehua-s/deer-flow into fea…
yuehua-s Jul 27, 2025
54b9f3f
feature:dockerfile add amd64
yuehua-s Jul 29, 2025
943ddaf
Merge branch 'main' of https://github.com/yuehua-s/deer-flow into fea…
yuehua-s Jul 29, 2025
1ed8109
feature:merge main
yuehua-s Aug 4, 2025
6793cfc
feature:remove kiro
yuehua-s Aug 4, 2025
70ef5bf
feature:remove kiro
yuehua-s Aug 4, 2025
5806a28
feature:remove kiro
yuehua-s Aug 4, 2025
be7255c
Merge branch 'main' into feature/tke
yuehua-s Aug 7, 2025
8f1ee57
Merge branch 'main' of https://github.com/yuehua-s/deer-flow into fea…
yuehua-s Aug 7, 2025
bdd43c1
Merge branch 'feature/tke' of https://github.com/yuehua-s/deer-flow i…
yuehua-s Aug 7, 2025
ce6b7fd
Merge branch 'main' into feature/tke
yuehua-s Aug 11, 2025
b02f556
Merge branch 'main' into feature/tke
WillemJiang Aug 17, 2025
66bc19b
feature:update pkg
yuehua-s Aug 26, 2025
2846027
feature:update pkg
yuehua-s Aug 26, 2025
ed4f57a
feature:remove unused code.
yuehua-s Aug 26, 2025
ed21468
feature:update some notes
yuehua-s Aug 27, 2025
da55278
feature:update some notes
yuehua-s Aug 27, 2025
ce77033
fix:test code
yuehua-s Aug 28, 2025
b9631b4
Merge branch 'main' into feature/tke
yuehua-s Sep 5, 2025
e8b114e
Merge branch 'main' into feature/tke
WillemJiang Sep 10, 2025
817fbb2
Merge branch 'main' into feature/tke
yuehua-s Sep 11, 2025
573b7a2
Merge branch 'main' into feature/tke
yuehua-s Sep 15, 2025
2215fc7
Merge branch 'main' into feature/tke
yuehua-s Sep 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ conf.yaml

# coverage report
coverage.xml
coverage/
coverage/
7 changes: 7 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ FROM ghcr.io/astral-sh/uv:python3.12-bookworm
# Install uv.
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

# Install Node.js, npm and Docker CLI for MCP tools
RUN apt-get update && apt-get install -y \
nodejs \
npm \
docker.io \
&& rm -rf /var/lib/apt/lists/*

# Install system dependencies including libpq
RUN apt-get update && apt-get install -y \
libpq-dev \
Expand Down
186 changes: 137 additions & 49 deletions src/graph/nodes.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
# SPDX-License-Identifier: MIT

import copy
import json
import logging
import os
from typing import Annotated, Literal

from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.runnables import RunnableConfig
from langchain_core.tools import tool
from langchain_core.tools import tool, BaseTool
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.types import Command, interrupt

from src.agents import create_agent
from src.config.agents import AGENT_LLM_MAP
from src.config.configuration import Configuration
from src.config.configuration import Configuration, get_bool_env
from src.llms.llm import get_llm_by_type
from src.prompts.planner_model import Plan
from src.prompts.template import apply_prompt_template
Expand All @@ -33,6 +33,94 @@
logger = logging.getLogger(__name__)


def get_mcp_servers(config: RunnableConfig, agent_type: str = None) -> tuple[dict, dict]:
"""Get information about available MCP server configurations and enabled tools.

Args:
config: Runtime configuration
agent_type: Agent type, used to filter applicable tools

Returns:
A tuple containing the MCP server configurations and enabled tools (mcp_servers, enabled_tools).
"""
try:
configurable = Configuration.from_runnable_config(config)
mcp_servers = {}
enabled_tools = {}

# Check if MCP is set
if not configurable.mcp_settings:
logger.debug("No MCP settings found in configuration")
return {}, {}

servers = configurable.mcp_settings.get("servers", {})
if not servers:
logger.debug("No MCP servers configured")
return {}, {}

# Extract MCP server configuration
for server_name, server_config in servers.items():
if not server_config.get("enabled_tools"):
continue

# todo: refine, filter by specific agent type
# if agent_type and server_config.get("add_to_agents"):
# if agent_type not in server_config["add_to_agents"]:
# continue

mcp_servers[server_name] = {
k: v
for k, v in server_config.items()
if k in ("transport", "command", "args", "url", "env")
}
for tool_name in server_config["enabled_tools"]:
prefixed_name = f"{server_name}_{tool_name}"
enabled_tools[prefixed_name] = server_name

return mcp_servers, enabled_tools

except Exception as e:
logger.error(f"Failed to collect MCP servers info: {e}")
return {}, {}


async def get_mcp_tools_info(config: RunnableConfig) -> list[BaseTool]:
"""Get information about all available MCP tools.

Args:
config: Runtime configuration

Returns:
A list containing tool names and descriptions.
"""
try:
tools = []
mcp_servers, enabled_tools = get_mcp_servers(config)
# Get MCP tools if available
if mcp_servers:
client = MultiServerMCPClient(mcp_servers)
m_tools = await client.get_tools()
for tool in m_tools:
for server_name in mcp_servers:
prefixed_name = f"{server_name}_{tool.name}"
if prefixed_name in enabled_tools:
# Create a copy of the tool for this specific server
import copy
tool_copy = copy.deepcopy(tool)
tool_copy.name = prefixed_name
tool_copy.description = (
f"Powered by mcp-server:'{server_name}'. Useful when you need to {tool.description}"
)
tools.append(tool_copy)
else:
logger.debug(f"Tool {prefixed_name} NOT found in enabled_tools")
logger.info(f"Successfully collected {len(tools)} MCP tools")
return tools
except Exception as e:
logger.error(f"Failed to collect MCP tools info: {e}")
return []


@tool
def handoff_to_planner(
research_topic: Annotated[str, "The topic of the research task to be handed off."],
Expand Down Expand Up @@ -80,13 +168,24 @@ def background_investigation_node(state: State, config: RunnableConfig):
}


def planner_node(
async def planner_node(
state: State, config: RunnableConfig
) -> Command[Literal["human_feedback", "reporter"]]:
"""Planner node that generate the full plan."""
logger.info("Planner generating full plan")

configurable = Configuration.from_runnable_config(config)
plan_iterations = state["plan_iterations"] if state.get("plan_iterations", 0) else 0

#Decide whether to collect MCP tool information based on configuration
mcp_enabled = get_bool_env("ENABLE_MCP_SERVER_CONFIGURATION", False)
if mcp_enabled:
logger.info("MCP planner integration is enabled, collecting tool information")
state["mcp_tools_info"] = await get_mcp_tools_info(config)
else:
logger.info("MCP planner integration is disabled")
state["mcp_tools_info"] = []

messages = apply_prompt_template("planner", state, configurable)

if state.get("enable_background_investigation") and state.get(
Expand Down Expand Up @@ -130,29 +229,29 @@ def planner_node(

try:
curr_plan = json.loads(repair_json_output(full_response))
except json.JSONDecodeError:
logger.warning("Planner response is not a valid JSON")
if plan_iterations > 0:
return Command(goto="reporter")
else:
return Command(goto="__end__")
if isinstance(curr_plan, dict) and curr_plan.get("has_enough_context"):
logger.info("Planner response has enough context.")
new_plan = Plan.model_validate(curr_plan)
if isinstance(curr_plan, dict) and curr_plan.get("has_enough_context"):
logger.info("Planner response has enough context.")
new_plan = Plan.model_validate(curr_plan)
return Command(
update={
"messages": [AIMessage(content=full_response, name="planner")],
"current_plan": new_plan,
},
goto="reporter",
)
# Plan requires further execution
return Command(
update={
"messages": [AIMessage(content=full_response, name="planner")],
"current_plan": new_plan,
"current_plan": full_response,
},
goto="reporter",
goto="human_feedback",
)
return Command(
update={
"messages": [AIMessage(content=full_response, name="planner")],
"current_plan": full_response,
},
goto="human_feedback",
)
except (json.JSONDecodeError, ValueError) as e:
logger.warning(f"Planner response parsing failed: {e}")
# If there is a historical iteration, generate a report directly; otherwise terminate
goto_target = "reporter" if plan_iterations > 0 else "__end__"
return Command(goto=goto_target)


def human_feedback_node(
Expand Down Expand Up @@ -439,36 +538,25 @@ async def _setup_and_execute_agent_step(
Returns:
Command to update state and go to research_team
"""
configurable = Configuration.from_runnable_config(config)
mcp_servers = {}
enabled_tools = {}

# Extract MCP server configuration for this agent type
if configurable.mcp_settings:
for server_name, server_config in configurable.mcp_settings["servers"].items():
if (
server_config["enabled_tools"]
and agent_type in server_config["add_to_agents"]
):
mcp_servers[server_name] = {
k: v
for k, v in server_config.items()
if k in ("transport", "command", "args", "url", "env", "headers")
}
for tool_name in server_config["enabled_tools"]:
enabled_tools[tool_name] = server_name

# Create and execute agent with MCP tools if available
loaded_tools = default_tools[:]
mcp_servers, enabled_tools = get_mcp_servers(config)
if mcp_servers:
client = MultiServerMCPClient(mcp_servers)
loaded_tools = default_tools[:]
all_tools = await client.get_tools()
for tool in all_tools:
if tool.name in enabled_tools:
tool.description = (
f"Powered by '{enabled_tools[tool.name]}'.\n{tool.description}"
)
loaded_tools.append(tool)
tools = await client.get_tools()
for tool in tools:
for server_name in mcp_servers:
prefixed_name = f"{server_name}_{tool.name}"
if prefixed_name in enabled_tools:
# Create a copy of the tool for this specific server
import copy
tool_copy = copy.deepcopy(tool)
tool_copy.name = prefixed_name
tool_copy.description = (
f"Powered by mcp-server:'{server_name}'. Useful when you need to {tool.description}"
)
loaded_tools.append(tool_copy)
logger.info(f"{agent_type} successfully collected {len(loaded_tools)} MCP tools")
agent = create_agent(agent_type, agent_type, loaded_tools, agent_type)
return await _execute_agent_step(state, agent, agent_type)
else:
Expand Down
1 change: 1 addition & 0 deletions src/graph/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ class State(MessagesState):
auto_accepted_plan: bool = False
enable_background_investigation: bool = True
background_investigation_results: str = None
mcp_tools_info: list = []
99 changes: 69 additions & 30 deletions src/prompts/coder.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,72 @@
CURRENT_TIME: {{ CURRENT_TIME }}
---

You are `coder` agent that is managed by `supervisor` agent.
You are a professional software engineer proficient in Python scripting. Your task is to analyze requirements, implement efficient solutions using Python, and provide clear documentation of your methodology and results.

# Steps

1. **Analyze Requirements**: Carefully review the task description to understand the objectives, constraints, and expected outcomes.
2. **Plan the Solution**: Determine whether the task requires Python. Outline the steps needed to achieve the solution.
3. **Implement the Solution**:
- Use Python for data analysis, algorithm implementation, or problem-solving.
- Print outputs using `print(...)` in Python to display results or debug values.
4. **Test the Solution**: Verify the implementation to ensure it meets the requirements and handles edge cases.
5. **Document the Methodology**: Provide a clear explanation of your approach, including the reasoning behind your choices and any assumptions made.
6. **Present Results**: Clearly display the final output and any intermediate results if necessary.

# Notes

- Always ensure the solution is efficient and adheres to best practices.
- Handle edge cases, such as empty files or missing inputs, gracefully.
- Use comments in code to improve readability and maintainability.
- If you want to see the output of a value, you MUST print it out with `print(...)`.
- Always and only use Python to do the math.
- Always use `yfinance` for financial market data:
- Get historical data with `yf.download()`
- Access company info with `Ticker` objects
- Use appropriate date ranges for data retrieval
- Required Python packages are pre-installed:
- `pandas` for data manipulation
- `numpy` for numerical operations
- `yfinance` for financial market data
- Always output in the locale of **{{ locale }}**.
You are a `coder` agent managed by `supervisor`. You are a professional software engineer who analyzes requirements and implements efficient solutions using the most appropriate tools available.

# Tool Selection Priority

**CRITICAL**: Always examine your available tools first and choose the most appropriate one:

1. **First Priority**: Use specialized MCP tools when available for the specific task
2. **Data Analysis/Computation**: Use `python_repl_tool` for data processing, calculations, analysis when no specialized MCP tool exists
3. **General Tasks**: Use built-in tools (web search, crawling, local search, etc.) for information gathering

# Execution Steps

1. **Analyze Requirements**: Review task objectives, constraints, and expected outcomes
2. **Inventory Available Tools**: Check what specialized tools you have access to
3. **Select Approach**:
- **Specialized MCP tools**: Use directly when available for the specific task
- **Data/Analysis tasks**: Use `python_repl_tool` for calculations, data processing, analysis
- **Information gathering**: Use built-in tools (search, crawling, etc.)
- **Hybrid**: Combine multiple tools as needed
4. **Implement Solution**: Execute using chosen tools/approach
5. **Verify & Debug**: Test solution, fix any issues, ensure successful execution
6. **Document**: Explain tool selection reasoning and methodology
7. **Present Results**: Display final output clearly

# Python REPL Guidelines

**Use `python_repl_tool` for**:

- Data analysis, processing, and calculations
- Mathematical computations and statistical analysis
- When no specialized MCP tool exists for the specific data task

**Before using `python_repl_tool`**:

- Check if specialized MCP tool can accomplish the task better
- Review pre-installed packages: `pandas`, `numpy`, `yfinance`, `matplotlib`, `requests`

**When using `python_repl_tool`**:

- Use `yfinance` for financial data (`yf.download()`, `Ticker` objects)
- Always `print(...)` outputs you want to see
- Add comments for code clarity
- Handle edge cases gracefully
- **Auto-fix bugs**: If code fails due to syntax/runtime errors, debug and fix automatically
- Ensure code executes successfully before proceeding

# Error Handling & Retry Strategy

**Tool Call Failures**:

- **Parameter Errors**: When tool fails due to incorrect parameters, analyze the error message and reconstruct parameters correctly
- **Retry Logic**: Attempt to fix parameter issues and retry tool calls to ensure successful execution
- **Alternative Approaches**: If tool continues to fail, consider alternative tools or approaches
- **Persistence**: Make multiple attempts to complete the task successfully

**Python Code Failures**:

- **Auto-fix bugs**: Debug and fix syntax/runtime errors automatically
- **Iterative improvement**: Refine code until it executes successfully
- **Error analysis**: Understand error messages and apply appropriate fixes

# Best Practices

- **Efficiency**: Choose the most direct solution path
- **Tool Priority**: Specialized MCP tools > Task-appropriate tools (Python for data/analysis, built-in for info gathering)
- **Resilience**: Persist through errors by fixing parameters and retrying tool calls
- **Documentation**: Explain tool choices, error fixes, and approach clearly

# Always output in locale: **{{ locale }}**
Loading