Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
45 changes: 23 additions & 22 deletions samples/multi-agent-supervisor-researcher-coder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,37 @@ graph TD;
__start__([<p>__start__</p>]):::first
input(input)
supervisor(supervisor)
__end__([<p>__end__</p>]):::last
__start__ --> input;
coder\3a__end__ -.-> supervisor;
input --> supervisor;
supervisor -.-> researcher___start__;
supervisor -.-> coder___start__;
researcher___end__ -.-> supervisor;
coder___end__ -.-> supervisor;
researcher\3a__end__ -.-> supervisor;
supervisor -.-> coder\3a__start__;
supervisor -.-> researcher\3a__start__;
supervisor -.-> __end__;
subgraph researcher
researcher___start__(<p>__start__</p>)
researcher_agent(agent)
researcher_tools(tools)
researcher___end__(<p>__end__</p>)
researcher___start__ --> researcher_agent;
researcher_tools --> researcher_agent;
researcher_agent -.-> researcher_tools;
researcher_agent -.-> researcher___end__;
researcher\3a__start__(<p>__start__</p>)
researcher\3aagent(agent)
researcher\3atools(tools)
researcher\3a__end__(<p>__end__</p>)
researcher\3a__start__ --> researcher\3aagent;
researcher\3aagent -.-> researcher\3a__end__;
researcher\3aagent -.-> researcher\3atools;
researcher\3atools --> researcher\3aagent;
end
subgraph coder
coder___start__(<p>__start__</p>)
coder_agent(agent)
coder_tools(tools)
coder___end__(<p>__end__</p>)
coder___start__ --> coder_agent;
coder_tools --> coder_agent;
coder_agent -.-> coder_tools;
coder_agent -.-> coder___end__;
coder\3a__start__(<p>__start__</p>)
coder\3aagent(agent)
coder\3atools(tools)
coder\3a__end__(<p>__end__</p>)
coder\3a__start__ --> coder\3aagent;
coder\3aagent -.-> coder\3a__end__;
coder\3aagent -.-> coder\3atools;
coder\3atools --> coder\3aagent;
end
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc

```

## How It Works
Expand All @@ -68,7 +69,7 @@ graph TD;

## Requirements

- Python 3.10+
- Python 3.11+
- LangGraph
- Anthropic API key (for Claude)
- Tavily API key (for web search)
Expand Down
42 changes: 22 additions & 20 deletions samples/multi-agent-supervisor-researcher-coder/agent.mermaid
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,33 @@ graph TD;
__start__([<p>__start__</p>]):::first
input(input)
supervisor(supervisor)
__end__([<p>__end__</p>]):::last
__start__ --> input;
coder\3a__end__ -.-> supervisor;
input --> supervisor;
supervisor -.-> researcher___start__;
supervisor -.-> coder___start__;
researcher___end__ -.-> supervisor;
coder___end__ -.-> supervisor;
researcher\3a__end__ -.-> supervisor;
supervisor -.-> coder\3a__start__;
supervisor -.-> researcher\3a__start__;
supervisor -.-> __end__;
subgraph researcher
researcher___start__(<p>__start__</p>)
researcher_agent(agent)
researcher_tools(tools)
researcher___end__(<p>__end__</p>)
researcher___start__ --> researcher_agent;
researcher_tools --> researcher_agent;
researcher_agent -.-> researcher_tools;
researcher_agent -.-> researcher___end__;
researcher\3a__start__(<p>__start__</p>)
researcher\3aagent(agent)
researcher\3atools(tools)
researcher\3a__end__(<p>__end__</p>)
researcher\3a__start__ --> researcher\3aagent;
researcher\3aagent -.-> researcher\3a__end__;
researcher\3aagent -.-> researcher\3atools;
researcher\3atools --> researcher\3aagent;
end
subgraph coder
coder___start__(<p>__start__</p>)
coder_agent(agent)
coder_tools(tools)
coder___end__(<p>__end__</p>)
coder___start__ --> coder_agent;
coder_tools --> coder_agent;
coder_agent -.-> coder_tools;
coder_agent -.-> coder___end__;
coder\3a__start__(<p>__start__</p>)
coder\3aagent(agent)
coder\3atools(tools)
coder\3a__end__(<p>__end__</p>)
coder\3a__start__ --> coder\3aagent;
coder\3aagent -.-> coder\3a__end__;
coder\3aagent -.-> coder\3atools;
coder\3atools --> coder\3aagent;
end
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
Expand Down
21 changes: 16 additions & 5 deletions samples/multi-agent-supervisor-researcher-coder/graph.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import Annotated, Literal

from langchain_anthropic import ChatAnthropic
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_tavily import TavilySearch
from langchain_core.messages import HumanMessage, SystemMessage, BaseMessage
from langchain_core.tools import tool
from langchain_experimental.utilities import PythonREPL
from langgraph.graph import END, START, MessagesState, StateGraph
Expand All @@ -11,7 +11,8 @@
from pydantic import BaseModel
from typing_extensions import TypedDict

tavily_tool = TavilySearchResults(max_results=5)

tavily_tool = TavilySearch(max_results=5)

# This executes code locally, which can be unsafe
repl = PythonREPL()
Expand All @@ -28,7 +29,7 @@ def python_repl_tool(
result = repl.run(code)
except BaseException as e:
return f"Failed to execute. Error: {repr(e)}"
result_str = f"Successfully executed:\n\`\`\`python\n{code}\n\`\`\`\nStdout: {result}"
result_str = f"Successfully executed:\n```python\n{code}\n```\nStdout: {result}"
return result_str

members = ["researcher", "coder"]
Expand Down Expand Up @@ -62,6 +63,16 @@ class GraphOutput(BaseModel):
class State(MessagesState):
next: str

def get_message_text(msg: BaseMessage) -> str:
"""LangChain-style safe message text extractor."""
if isinstance(msg.content, str):
return msg.content
if isinstance(msg.content, list):
return "".join(
block.get("text", "") for block in msg.content if block.get("type") == "text"
)
return ""

def input(state: GraphInput):
return {
"messages": [
Expand All @@ -75,7 +86,7 @@ async def supervisor_node(state: State) -> Command[Literal[*members]] | GraphOut
response = await llm.with_structured_output(Router).ainvoke(state["messages"])
goto = response["next"]
if goto == "FINISH":
return GraphOutput(answer=state["messages"][-1].content)
return GraphOutput(answer=get_message_text(state["messages"][-1]))
else:
return Command(goto=goto, update={"next": goto})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ description = "Multi-agent system where a supervisor coordinates between a resea
authors = [{ name = "John Doe", email = "john.doe@myemail.com" }]
requires-python = ">=3.10"
dependencies = [
"langgraph>=0.2.55",
"langchain-anthropic>=0.3.8",
"langgraph>=0.6.11",
"langchain-anthropic>=0.3.22",
"langchain-experimental>=0.3.4",
"tavily-python>=0.5.0",
"uipath-langchain==0.0.124"
"tavily-python>=0.7.12",
"uipath-langchain==0.0.141",
"langchain-tavily>=0.2.12",
]

[project.optional-dependencies]
Expand Down
Loading