Files
Tutorial-Codebase-Knowledge/docs/CrewAI/05_process.md
zachary62 2ebad5e5f2 init push
2025-04-04 13:03:54 -04:00

297 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Chapter 5: Process - Orchestrating the Workflow
In [Chapter 4: Tool](04_tool.md), we learned how to give our [Agent](02_agent.md)s special abilities using `Tool`s, like searching the web. Now we have specialized agents, defined tasks, and equipped agents. But how do they actually *work together*? Does Agent 1 finish its work before Agent 2 starts? Or is there a manager overseeing everything?
This coordination is handled by the **`Process`**.
## Why Do We Need a Process?
Think back to our trip planning [Crew](01_crew.md). We have a 'Travel Researcher' agent and an 'Activity Planner' agent.
* **Scenario 1:** Maybe the Researcher needs to find the city *first*, and *then* the Planner creates the itinerary for that specific city. The work happens in a specific order.
* **Scenario 2:** Maybe we have a more complex project with many agents (Researcher, Planner, Booker, Budgeter). Perhaps we want a 'Project Manager' agent to receive the main goal, decide which agent needs to do what first, review their work, and then assign the next step.
The way the agents collaborate and the order in which [Task](03_task.md)s are executed is crucial for success. A well-defined `Process` ensures work flows smoothly and efficiently.
**Problem Solved:** `Process` defines the strategy or workflow the [Crew](01_crew.md) uses to execute its [Task](03_task.md)s. It dictates how [Agent](02_agent.md)s collaborate and how information moves between them.
## What is a Process?
Think of the `Process` as the **project management style** for your [Crew](01_crew.md). It determines the overall flow of work. CrewAI primarily supports two types of processes:
1. **`Process.sequential`**:
* **Analogy:** Like following a recipe or a checklist.
* **How it works:** Tasks are executed one after another, in the exact order you list them in the `Crew` definition. The output of the first task automatically becomes available as context for the second task, the output of the second for the third, and so on.
* **Best for:** Simple, linear workflows where each step clearly follows the previous one.
2. **`Process.hierarchical`**:
* **Analogy:** Like a traditional company structure with a manager.
* **How it works:** You designate a "manager" [Agent](02_agent.md) (usually by providing a specific `manager_llm` or a custom `manager_agent` to the `Crew`). This manager receives the overall goal and the list of tasks. It then analyzes the tasks and decides which *worker* agent should perform which task, potentially breaking them down or reordering them. The manager delegates work, reviews results, and coordinates the team until the goal is achieved.
* **Best for:** More complex projects where task order might change, delegation is needed, or a central coordinator can optimize the workflow.
Choosing the right `Process` is key to structuring how your agents interact.
## How to Use Process
You define the process when you create your `Crew`, using the `process` parameter.
### Sequential Process
This is the default and simplest process. We already used it in [Chapter 1](01_crew.md)!
```python
# Assuming 'researcher' and 'planner' agents are defined (from Chapter 2)
# Assuming 'task1' (find cities) and 'task2' (create itinerary) are defined (from Chapter 3)
# task1 assigned to researcher, task2 assigned to planner
from crewai import Crew, Process
# Define the crew with a sequential process
trip_crew = Crew(
agents=[researcher, planner],
tasks=[task1, task2],
process=Process.sequential # Explicitly setting the sequential process
# verbose=2 # Optional verbosity
)
# Start the work
# result = trip_crew.kickoff()
# print(result)
```
**Explanation:**
* We import `Crew` and `Process`.
* When creating the `trip_crew`, we pass our list of `agents` and `tasks`.
* We set `process=Process.sequential`.
* When `kickoff()` is called:
1. `task1` (Find Cities) is executed by the `researcher`.
2. The output of `task1` (the list of cities) is automatically passed as context.
3. `task2` (Create Itinerary) is executed by the `planner`, using the cities list from `task1`.
4. The final output of `task2` is returned.
It's simple and predictable: Task 1 -> Task 2 -> Done.
### Hierarchical Process
For this process, the `Crew` needs a manager. You usually specify the language model the manager should use (`manager_llm`). The manager agent is created internally by CrewAI using this LLM.
```python
# Assuming 'researcher' and 'planner' agents are defined
# Assuming 'task1' and 'task2' are defined (WITHOUT necessarily assigning agents initially)
# You need an LLM configured (e.g., from OpenAI, Ollama - see Chapter 6)
# from langchain_openai import ChatOpenAI # Example LLM
from crewai import Crew, Process, Task
# Example tasks (agent assignment might be handled by the manager)
task1 = Task(description='Find top 3 European cities for a sunny May birthday trip.', expected_output='List of 3 cities with justifications.')
task2 = Task(description='Create a 3-day itinerary for the best city found.', expected_output='Detailed 3-day plan.')
# Define the crew with a hierarchical process and a manager LLM
hierarchical_crew = Crew(
agents=[researcher, planner], # The worker agents
tasks=[task1, task2], # The tasks to be managed
process=Process.hierarchical, # Set the process to hierarchical
manager_llm=ChatOpenAI(model="gpt-4") # Specify the LLM for the manager agent
# You could also provide a pre-configured manager_agent instance instead of manager_llm
)
# Start the work
# result = hierarchical_crew.kickoff()
# print(result)
```
**Explanation:**
* We set `process=Process.hierarchical`.
* We provide a list of worker `agents` (`researcher`, `planner`).
* We provide the `tasks` that need to be accomplished. Note that for the hierarchical process, you *might* not need to assign agents directly to tasks, as the manager can decide who is best suited. However, assigning them can still provide hints to the manager.
* Crucially, we provide `manager_llm`. CrewAI will use this LLM to create an internal 'Manager Agent'. This agent's implicit goal is to orchestrate the `agents` to complete the `tasks`.
* When `kickoff()` is called:
1. The internal Manager Agent analyzes `task1` and `task2` and the available agents (`researcher`, `planner`).
2. It decides which agent should do `task1` (likely the `researcher`). It delegates the task using internal tools (like `AgentTools`).
3. It receives the result from the `researcher`.
4. It analyzes the result and decides the next step likely delegating `task2` to the `planner`, providing the context from `task1`.
5. It receives the result from the `planner`.
6. Once all tasks are deemed complete by the manager, it compiles and returns the final result.
This process is more dynamic, allowing the manager to adapt the workflow.
## How Process Works "Under the Hood"
When you call `crew.kickoff()`, the first thing the `Crew` does is check its `process` attribute to determine the execution strategy.
1. **Input & Setup:** `kickoff()` prepares the agents and tasks, interpolating any initial inputs.
2. **Process Check:** It looks at `crew.process`.
3. **Execution Path:**
* If `Process.sequential`, it calls an internal method like `_run_sequential_process()`.
* If `Process.hierarchical`, it first ensures a manager agent exists (creating one if `manager_llm` was provided) and then calls a method like `_run_hierarchical_process()`.
4. **Task Loop (Sequential):** `_run_sequential_process()` iterates through the `tasks` list in order. For each task, it finds the assigned agent, gathers context from the *previous* task's output, and asks the agent to execute the task.
5. **Managed Execution (Hierarchical):** `_run_hierarchical_process()` delegates control to the manager agent. The manager agent, using its LLM and specialized delegation tools (like `AgentTools`), decides which task to tackle next and which worker agent to assign it to. It manages the flow until all tasks are completed.
6. **Output:** The final result (usually the output of the last task) is packaged and returned.
### Visualization
Let's visualize the difference:
**Sequential Process:**
```mermaid
sequenceDiagram
participant User
participant MyCrew as Crew (Sequential)
participant ResearcherAgent as Researcher
participant PlannerAgent as Planner
User->>MyCrew: kickoff()
MyCrew->>ResearcherAgent: Execute Task 1 ("Find cities")
ResearcherAgent-->>MyCrew: Task 1 Output (Cities List)
MyCrew->>PlannerAgent: Execute Task 2 ("Create itinerary")\nwith Task 1 Output context
PlannerAgent-->>MyCrew: Task 2 Output (Itinerary)
MyCrew-->>User: Final Result (Task 2 Output)
```
**Hierarchical Process:**
```mermaid
sequenceDiagram
participant User
participant MyCrew as Crew (Hierarchical)
participant ManagerAgent as Manager
participant ResearcherAgent as Researcher
participant PlannerAgent as Planner
User->>MyCrew: kickoff()
MyCrew->>ManagerAgent: Goal: Plan Trip (Tasks: Find Cities, Create Itinerary)
ManagerAgent->>ManagerAgent: Decide: Researcher should do Task 1
ManagerAgent->>ResearcherAgent: Delegate: Execute Task 1 ("Find cities")
ResearcherAgent-->>ManagerAgent: Task 1 Output (Cities List)
ManagerAgent->>ManagerAgent: Decide: Planner should do Task 2 with context
ManagerAgent->>PlannerAgent: Delegate: Execute Task 2 ("Create itinerary", Cities List)
PlannerAgent-->>ManagerAgent: Task 2 Output (Itinerary)
ManagerAgent->>MyCrew: Report Final Result (Itinerary)
MyCrew-->>User: Final Result (Itinerary)
```
### Diving into the Code (`crew.py`)
The `Crew` class in `crewai/crew.py` holds the logic.
```python
# Simplified view from crewai/crew.py
from crewai.process import Process
from crewai.task import Task
from crewai.agents.agent_builder.base_agent import BaseAgent
# ... other imports
class Crew(BaseModel):
# ... other fields like agents, tasks ...
process: Process = Field(default=Process.sequential)
manager_llm: Optional[Any] = Field(default=None)
manager_agent: Optional[BaseAgent] = Field(default=None)
# ... other fields ...
@model_validator(mode="after")
def check_manager_llm(self):
# Ensures manager_llm or manager_agent is set for hierarchical process
if self.process == Process.hierarchical:
if not self.manager_llm and not self.manager_agent:
raise PydanticCustomError(
"missing_manager_llm_or_manager_agent",
"Attribute `manager_llm` or `manager_agent` is required when using hierarchical process.",
{},
)
return self
def kickoff(self, inputs: Optional[Dict[str, Any]] = None) -> CrewOutput:
# ... setup, input interpolation, callback setup ...
# THE CORE DECISION BASED ON PROCESS:
if self.process == Process.sequential:
result = self._run_sequential_process()
elif self.process == Process.hierarchical:
# Ensure manager is ready before running
self._create_manager_agent() # Creates manager if needed
result = self._run_hierarchical_process()
else:
raise NotImplementedError(f"Process '{self.process}' not implemented.")
# ... calculate usage metrics, final formatting ...
return result
def _run_sequential_process(self) -> CrewOutput:
task_outputs = []
for task_index, task in enumerate(self.tasks):
agent = task.agent # Get assigned agent
# ... handle conditional tasks, async tasks ...
context = self._get_context(task, task_outputs) # Get previous output
output = task.execute_sync(agent=agent, context=context) # Run task
task_outputs.append(output)
# ... logging/callbacks ...
return self._create_crew_output(task_outputs)
def _run_hierarchical_process(self) -> CrewOutput:
# This actually delegates the orchestration to the manager agent.
# The manager agent uses its LLM and tools (AgentTools)
# to call the worker agents sequentially or in parallel as it sees fit.
manager = self.manager_agent
# Simplified concept: Manager executes a "meta-task"
# whose goal is to complete the crew's tasks using available agents.
# The actual implementation involves the manager agent's execution loop.
return self._execute_tasks(self.tasks) # The manager guides this execution internally
def _create_manager_agent(self):
# Logic to setup the self.manager_agent instance, either using
# the provided self.manager_agent or creating a default one
# using self.manager_llm and AgentTools(agents=self.agents).
if self.manager_agent is None and self.manager_llm:
# Simplified: Create a default manager agent here
# It gets tools to delegate work to self.agents
self.manager_agent = Agent(
role="Crew Manager",
goal="Coordinate the crew to achieve their goals.",
backstory="An expert project manager.",
llm=self.manager_llm,
tools=AgentTools(agents=self.agents).tools(), # Gives it delegation capability
allow_delegation=True, # Must be true for manager
verbose=self.verbose
)
self.manager_agent.crew = self # Link back to crew
# Ensure manager has necessary setup...
pass
def _execute_tasks(self, tasks: List[Task], ...) -> CrewOutput:
"""Internal method used by both sequential and hierarchical processes
to iterate through tasks. In hierarchical, the manager agent influences
which agent runs which task via delegation tools."""
# ... loops through tasks, gets agent (directly for seq, via manager for hier), executes ...
pass
# ... other helper methods like _get_context, _create_crew_output ...
```
Key takeaways from the code:
* The `Crew` stores the `process` type (`sequential` or `hierarchical`).
* A validation (`check_manager_llm`) ensures a manager (`manager_llm` or `manager_agent`) is provided if `process` is `hierarchical`.
* The `kickoff` method explicitly checks `self.process` to decide which internal execution method (`_run_sequential_process` or `_run_hierarchical_process`) to call.
* `_run_sequential_process` iterates through tasks in order.
* `_run_hierarchical_process` relies on the `manager_agent` (created by `_create_manager_agent` if needed) to manage the task execution flow, often using delegation tools.
## Conclusion
You've now learned about the `Process` - the crucial setting that defines *how* your [Crew](01_crew.md) collaborates.
* **`Sequential`** is like a checklist: tasks run one by one, in order, with outputs flowing directly to the next task. Simple and predictable.
* **`Hierarchical`** is like having a manager: a dedicated manager [Agent](02_agent.md) coordinates the worker agents, deciding who does what and when. More flexible for complex workflows.
Choosing the right process helps structure your agent interactions effectively.
So far, we've built the team ([Agent](02_agent.md)), defined the work ([Task](03_task.md)), given them abilities ([Tool](04_tool.md)), and decided on the workflow ([Process](05_process.md)). But what powers the "thinking" part of each agent? What is the "brain" that understands roles, goals, backstories, and uses tools? That's the Large Language Model, or [LLM](06_llm.md). Let's dive into that next!
**Next:** [Chapter 6: LLM - The Agent's Brain](06_llm.md)
---
Generated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge)