Skip to content

Commit 9ebec60

Browse files
author
Pierre
committed
add new workflow for agent delegation
1 parent 585b9e0 commit 9ebec60

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

examples/workflows/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,27 @@ The Chain of Agents pattern is designed for processing long documents or complex
5858

5959
For an implementation example, see [chain_of_agents.py](chain_of_agents.py).
6060

61+
## 7. Agent Delegation
62+
The Agent Delegation pattern enables dynamic and flexible workflows where one agent can invoke other agents through tools. This pattern is particularly useful when you want an agent to dynamically choose which specialized agents to use based on the task at hand, rather than having a fixed sequence or structure.
63+
64+
**Key Features:**
65+
- Dynamic model selection based on task requirements
66+
- Flexible workflow that adapts based on initial responses
67+
- Ability to track which agents were used and why
68+
- Built-in confidence scoring for quality control
69+
70+
**Example:**
71+
- An orchestrator agent receives a complex task (e.g., system architecture design)
72+
- It breaks down the task into smaller components
73+
- For each component, it:
74+
- Chooses the most appropriate model (e.g., GPT-4 for reasoning, Claude for analysis)
75+
- Delegates the work through a tool
76+
- Evaluates the response and confidence level
77+
- Requests additional work if needed
78+
- Finally, it synthesizes all responses into a coherent solution
79+
80+
For an implementation example, see [agent_delegation.py](agent_delegation.py).
81+
6182
---
6283

6384
These patterns were inspired by the workflow patterns described in the [Vercel AI SDK Documentation](https://sdk.vercel.ai/docs/foundations/agents#patterns-with-examples) and research from organizations like [Google Research](https://research.google/blog/chain-of-agents-large-language-models-collaborating-on-long-context-tasks/).
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
"""
2+
This example demonstrates agent delegation, where one agent (the orchestrator) can dynamically
3+
invoke other agents through tools. This pattern is useful when you want to:
4+
5+
1. Let an agent dynamically choose which specialized agents to use
6+
2. Allow the orchestrator to adapt its strategy based on initial responses
7+
3. Enable flexible workflows where the sequence of agent calls isn't fixed
8+
4. Track which agents were used and why
9+
10+
The example shows how to:
11+
1. Set up a tool that allows one agent to call another
12+
2. Structure input/output types for delegation
13+
3. Configure the orchestrator agent with the delegation tool
14+
4. Handle responses and track agent usage
15+
"""
16+
17+
import asyncio
18+
from typing import List, Optional
19+
20+
from pydantic import BaseModel, Field
21+
22+
import workflowai
23+
from workflowai import Model, Run
24+
25+
26+
class DelegateInput(BaseModel):
27+
"""Input for delegating a task to a specialized agent."""
28+
task: str = Field(description="The task to delegate")
29+
model: Model = Field(description="The model to use for this task")
30+
context: Optional[str] = Field(
31+
default=None,
32+
description="Additional context that might help the agent",
33+
)
34+
35+
36+
class DelegateOutput(BaseModel):
37+
"""Output from a delegated task."""
38+
response: str = Field(description="The agent's response to the task")
39+
confidence: float = Field(
40+
description="Confidence score between 0 and 1",
41+
ge=0,
42+
le=1,
43+
)
44+
45+
46+
class WorkerInput(BaseModel):
47+
"""Input for the worker agent."""
48+
task: str = Field(description="The task to perform")
49+
context: Optional[str] = Field(
50+
default=None,
51+
description="Additional context that might help with the task",
52+
)
53+
54+
55+
class WorkerOutput(BaseModel):
56+
"""Output from the worker agent."""
57+
response: str = Field(description="The response to the task")
58+
confidence: float = Field(
59+
description="Confidence score between 0 and 1",
60+
ge=0,
61+
le=1,
62+
)
63+
64+
65+
class OrchestratorInput(BaseModel):
66+
"""Input for the orchestrator agent."""
67+
objective: str = Field(description="The high-level objective to achieve")
68+
requirements: List[str] = Field(
69+
description="List of specific requirements or constraints",
70+
min_items=1,
71+
)
72+
73+
74+
class OrchestratorOutput(BaseModel):
75+
"""Final output from the orchestrator."""
76+
solution: str = Field(description="The final solution that meets the objective")
77+
explanation: str = Field(description="Explanation of how the solution was derived")
78+
agents_used: List[str] = Field(
79+
description="List of agents/models used in the process",
80+
default_factory=list,
81+
)
82+
83+
84+
@workflowai.agent(id="worker")
85+
async def worker_agent(input: WorkerInput, *, model: Model) -> Run[WorkerOutput]:
86+
"""
87+
A specialized worker agent that handles specific tasks.
88+
89+
Make sure to:
90+
1. Focus on the specific task assigned
91+
2. Use the provided context if available
92+
3. Be clear about confidence level
93+
4. Explain any assumptions made
94+
"""
95+
...
96+
97+
98+
async def delegate_task(input: DelegateInput) -> DelegateOutput:
99+
"""Delegate a task to a worker agent with a specific model."""
100+
run = await worker_agent(
101+
WorkerInput(
102+
task=input.task,
103+
context=input.context,
104+
),
105+
model=input.model,
106+
)
107+
return DelegateOutput(
108+
response=run.output.response,
109+
confidence=run.output.confidence,
110+
)
111+
112+
113+
@workflowai.agent(
114+
id="orchestrator",
115+
model=Model.GPT_4O_LATEST,
116+
tools=[delegate_task],
117+
)
118+
async def orchestrator_agent(input: OrchestratorInput) -> Run[OrchestratorOutput]:
119+
"""
120+
You are an expert orchestrator that breaks down complex objectives into smaller tasks
121+
and delegates them to specialized agents. You can use the delegate_task tool to assign
122+
work to other agents.
123+
124+
Your responsibilities:
125+
1. Break down the objective into smaller, focused tasks
126+
2. Choose appropriate models for each task based on its nature:
127+
- GPT-4O for complex reasoning or creative tasks
128+
- Claude for analytical or structured tasks
129+
- Gemini for technical or scientific tasks
130+
3. Use the delegate_task tool to assign work
131+
4. Evaluate responses and confidence levels
132+
5. Request additional work if needed
133+
6. Synthesize all responses into a cohesive solution
134+
7. Track which models were used and why
135+
136+
Make sure the final solution:
137+
- Meets all specified requirements
138+
- Is well-reasoned and explained
139+
- Acknowledges any limitations or uncertainties
140+
- Lists all models/agents used in the process
141+
"""
142+
...
143+
144+
145+
async def main():
146+
# Example: Software architecture task
147+
print("\nExample: Software Architecture Design")
148+
print("-" * 50)
149+
150+
result = await orchestrator_agent(
151+
OrchestratorInput(
152+
objective="Design a scalable microservices architecture for an e-commerce platform",
153+
requirements=[
154+
"Must handle 10,000+ concurrent users",
155+
"Include payment processing and inventory management",
156+
"Ensure data consistency across services",
157+
"Provide real-time order tracking",
158+
],
159+
),
160+
)
161+
162+
print("\nSolution:")
163+
print(result.output.solution)
164+
print("\nExplanation:")
165+
print(result.output.explanation)
166+
print("\nAgents Used:")
167+
for agent in result.output.agents_used:
168+
print(f"- {agent}")
169+
170+
171+
if __name__ == "__main__":
172+
asyncio.run(main())

0 commit comments

Comments
 (0)