-
Notifications
You must be signed in to change notification settings - Fork 278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is this the correct approach to building a multi-agent application using Pydantic AI? #300
Comments
Thanks so much for this, this is really interesting, Yes this is roughly what we're thinking of, you might also be interested in #120. There are a few things I think we can do to make this even simpler:
|
Looks solid. No better idea currently on how to build multi-agents. And thanks for sharing this. I am also currently working on a kind of multi-agent system. But I tried to use just tools so far. What I'm currently struggling with is getting the agent to always think before deciding to use a tool to answer the user's message. I haven't found a way to add a rule so the agent does this consistently. But I think your approach with the multi-agent could work for me. I could create a thinking/planning agent and use it as a dependency. |
@ishswar really cool example! I think there are (at least) two different types of multi-agent systems. (I'm making up terms on the spot):
The example above uses the Orchestrator approach. I have a gut feeling that this is a serious limitation for more complex systems. How about this instead: # --- Result Model ---
class AgentResult(BaseModel):
response: str = Field(description="Response to the customer")
target_agent: Optional[str] = Field(description="Agent to hand over to", default=None)
# --- Dependencies ---
@dataclass
class AgentDependencies:
conversation_id: str
user_id: str
# --- Agents ---
triage_agent = Agent(
"openai:gpt-4o",
deps_type=AgentDependencies,
result_type=AgentResult,
system_prompt="""You are a triage agent that directs customers to the right department.
For technical issues (internet, service outages, connection problems), set target_agent to 'tech_support'.
For billing issues (payments, charges, invoices), set target_agent to 'billing'.
For general inquiries, handle them yourself without setting a target_agent.
"""
)
tech_support = Agent(
"openai:gpt-4o",
deps_type=AgentDependencies,
result_type=AgentResult,
system_prompt="""You are a technical support agent. Handle technical issues.
If a billing question comes up, set target_agent to 'billing' in your response.
"""
)
billing_agent = Agent(
"openai:gpt-4o",
deps_type=AgentDependencies,
result_type=AgentResult,
system_prompt="""You are a billing support agent. Handle billing issues.
If a technical question comes up, set target_agent to 'tech_support' in your response.
"""
)
# --- Router ---
class AgentRouter:
def __init__(self):
self.agents = {
"triage": triage_agent,
"tech_support": tech_support,
"billing": billing_agent
}
async def handle_conversation(self, prompt: str, deps: AgentDependencies) -> str:
current_agent = self.agents["triage"]
while True:
# Run current agent
result = await current_agent.run(prompt, deps=deps)
# Check for handover
if result.data.target_agent:
print(f"Handing over to {result.data.target_agent}")
current_agent = self.agents[result.data.target_agent]
continue
# No handover needed, return response
return result.data.response |
@pietz this is an elegant approach, thanks. I will try it. |
See also:
|
I implemented my agents using an Orchestrator approach last week, and I found it to be more effective than the router method. In this setup, the first agent has a comprehensive view of the overall process, utilizing all other agents as tools to achieve the desired outcome. This is analogous to a manager who assigns tasks to different team members and reviews the results before presenting them to the boss. |
I have a question regarding agents being used as dependencies for other agents. In what scenarios do we actually need this? For example, in @ishswar's example, the triage agent has dependencies on the support and loan agents. Why can't we directly use the support and loan agents instead of passing them as dependencies to the triage agent? |
I think there's no reason to make an agent a dependency, agents are generally global and immutable, so you can use them without making them deps. |
Hi Team,
I have been working on extending the sample provided at Pydantic AI Bank Support Example, and I’ve added a multi-agent system that includes several agents interacting with each other. Here’s an overview of what I’ve implemented:
Multi-Agent System Breakdown:
Each agent is called via Tools and utilizes RunContext to pass dependencies. The tools
call_support_agent
andcall_loan_agent
are used by the Triage Agent to forward the query to the appropriate agent based on the customer’s request.Sample Output:
Here is an example of what the output looks like for various queries:
Prompt: What is my balance?
Response: Hello John, your current account balance is $123.45.
Prompt: My card is lost. Please help!
Response: I'm sorry to hear that, John. We are temporarily blocking your card to prevent unauthorized transactions. Please confirm if you need further assistance or would like to request a new card.
Prompt: What is the status of my loan?
Response: Your loan status is currently 'Active' and the remaining balance is $5000.
Prompt: How tall is the Eiffel Tower?
Response: I'm sorry, but I cannot answer questions that don't relate to loans or support. Please let me know if you have any queries regarding loans or bank support!
My Questions:
I’m looking for feedback on whether the way I’ve implemented these agents and their interaction is aligned with best practices for multi-agent systems in Pydantic AI. Any suggestions or improvements would be greatly appreciated.
Thanks for your help!
logFire Debug lines ( nicely indented - Thanks to whoever coded that! 🙏)
Full Code
The text was updated successfully, but these errors were encountered: