diff --git a/docs/en/guides/concepts/evaluating-use-cases.mdx b/docs/en/guides/concepts/evaluating-use-cases.mdx
index f7895deec6..96dfb86f8b 100644
--- a/docs/en/guides/concepts/evaluating-use-cases.mdx
+++ b/docs/en/guides/concepts/evaluating-use-cases.mdx
@@ -174,7 +174,6 @@ Flows are ideal when:
# Example: Customer Support Flow with structured processing
from crewai.flow.flow import Flow, listen, router, start
from pydantic import BaseModel
-from typing import List, Dict
# Define structured state
class SupportTicketState(BaseModel):
@@ -262,7 +261,6 @@ The most sophisticated applications often benefit from combining Crews and Flows
from crewai.flow.flow import Flow, listen, start
from crewai import Agent, Crew, Process, Task
from pydantic import BaseModel
-from typing import List, Dict
class ContentState(BaseModel):
topic: str = ""
diff --git a/docs/en/guides/crews/first-crew.mdx b/docs/en/guides/crews/first-crew.mdx
index 22495f34da..2c524450a8 100644
--- a/docs/en/guides/crews/first-crew.mdx
+++ b/docs/en/guides/crews/first-crew.mdx
@@ -58,7 +58,6 @@ This will generate a project with the basic structure needed for your crew. The
-
## Step 2: Explore the Project Structure
Let's take a moment to understand the project structure created by the CLI. CrewAI follows best practices for Python projects, making it easy to maintain and extend your code as your crews become more complex.
@@ -187,14 +186,13 @@ from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai_tools import SerperDevTool
from crewai.agents.agent_builder.base_agent import BaseAgent
-from typing import List
@CrewBase
class ResearchCrew():
"""Research crew for comprehensive topic analysis and reporting"""
- agents: List[BaseAgent]
- tasks: List[Task]
+ agents: list[BaseAgent]
+ tasks: list[Task]
@agent
def researcher(self) -> Agent:
diff --git a/docs/en/guides/flows/first-flow.mdx b/docs/en/guides/flows/first-flow.mdx
index a5b8c347ce..f6a335bd33 100644
--- a/docs/en/guides/flows/first-flow.mdx
+++ b/docs/en/guides/flows/first-flow.mdx
@@ -206,14 +206,13 @@ These task definitions provide detailed instructions to our agents, ensuring the
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai.agents.agent_builder.base_agent import BaseAgent
-from typing import List
@CrewBase
class ContentCrew():
"""Content writing crew"""
- agents: List[BaseAgent]
- tasks: List[Task]
+ agents: list[BaseAgent]
+ tasks: list[Task]
@agent
def content_writer(self) -> Agent:
@@ -271,7 +270,7 @@ Let's create our flow in the `main.py` file:
#!/usr/bin/env python
import json
import os
-from typing import List, Dict
+
from pydantic import BaseModel, Field
from crewai import LLM
from crewai.flow.flow import Flow, listen, start
@@ -286,7 +285,7 @@ class GuideOutline(BaseModel):
title: str = Field(description="Title of the guide")
introduction: str = Field(description="Introduction to the topic")
target_audience: str = Field(description="Description of the target audience")
- sections: List[Section] = Field(description="List of sections in the guide")
+ sections: list[Section] = Field(description="List of sections in the guide")
conclusion: str = Field(description="Conclusion or summary of the guide")
# Define our flow state
@@ -294,7 +293,7 @@ class GuideCreatorState(BaseModel):
topic: str = ""
audience_level: str = ""
guide_outline: GuideOutline = None
- sections_content: Dict[str, str] = {}
+ sections_content: dict[str, str] = {}
class GuideCreatorFlow(Flow[GuideCreatorState]):
"""Flow for creating a comprehensive guide on any topic"""
@@ -590,7 +589,7 @@ class GuideCreatorState(BaseModel):
topic: str = ""
audience_level: str = ""
guide_outline: GuideOutline = None
- sections_content: Dict[str, str] = {}
+ sections_content: dict[str, str] = {}
```
This provides a type-safe way to track and transform data throughout your flow.
diff --git a/docs/en/guides/flows/mastering-flow-state.mdx b/docs/en/guides/flows/mastering-flow-state.mdx
index 68a8212464..6deb530008 100644
--- a/docs/en/guides/flows/mastering-flow-state.mdx
+++ b/docs/en/guides/flows/mastering-flow-state.mdx
@@ -149,7 +149,6 @@ Here's how to implement structured state management:
```python
from crewai.flow.flow import Flow, listen, start
from pydantic import BaseModel, Field
-from typing import List, Dict, Optional
# Define your state model
class UserPreferences(BaseModel):
@@ -159,7 +158,7 @@ class UserPreferences(BaseModel):
class AppState(BaseModel):
user_name: str = ""
preferences: UserPreferences = UserPreferences()
- items: List[str] = []
+ items: list[str] = []
processed: bool = False
completion_percentage: float = 0.0
@@ -388,7 +387,6 @@ Behavior notes:
- `restore_from_state_id=None` (default) is byte-identical to a kickoff without the parameter.
- Pinning `inputs["id"]` while forking means the new run shares a persistence key with another flow — usually you want only `restore_from_state_id`.
-
## Advanced State Patterns
### Conditional starts and resumable execution
@@ -469,7 +467,6 @@ For complex state transformations, you can create dedicated methods:
```python
from crewai.flow.flow import Flow, listen, start
from pydantic import BaseModel
-from typing import List, Dict
class UserData(BaseModel):
name: str
@@ -477,7 +474,7 @@ class UserData(BaseModel):
login_count: int = 0
class ComplexState(BaseModel):
- users: Dict[str, UserData] = {}
+ users: dict[str, UserData] = {}
active_user_count: int = 0
class TransformationFlow(Flow[ComplexState]):
@@ -641,8 +638,8 @@ class BloatedState(BaseModel):
# Better: Focused state
class FocusedState(BaseModel):
user_id: str
- preferences: Dict[str, str]
- completion_status: Dict[str, bool]
+ preferences: dict[str, str]
+ completion_status: dict[str, bool]
```
### 2. Use Structured State for Complex Flows
@@ -663,7 +660,7 @@ class UserRegistrationState(BaseModel):
email: str
verification_status: bool = False
registration_date: datetime = Field(default_factory=datetime.now)
- last_login: Optional[datetime] = None
+ last_login: datetime | None = None
class RegistrationFlow(Flow[UserRegistrationState]):
# Methods with strongly-typed state access
@@ -748,10 +745,9 @@ self.state.items.append(new_item) # Mutable operation
# Consider creating new state:
from pydantic import BaseModel
-from typing import List
class ItemState(BaseModel):
- items: List[str] = []
+ items: list[str] = []
class ImmutableFlow(Flow[ItemState]):
@start()
diff --git a/docs/en/learn/bring-your-own-agent.mdx b/docs/en/learn/bring-your-own-agent.mdx
index fb7b22dc21..c9d74a62c7 100644
--- a/docs/en/learn/bring-your-own-agent.mdx
+++ b/docs/en/learn/bring-your-own-agent.mdx
@@ -7,7 +7,6 @@ mode: "wide"
Interoperability is a core concept in CrewAI. This guide will show you how to bring your own agents that work within a Crew.
-
## Adapter Guide for Bringing your own agents (Langgraph Agents, OpenAI Agents, etc...)
We require 3 adapters to turn any agent from different frameworks to work within crew.
@@ -15,7 +14,6 @@ We require 3 adapters to turn any agent from different frameworks to work within
2. BaseToolAdapter
3. BaseConverter
-
## BaseAgentAdapter
This abstract class defines the common interface and functionality that all
agent adapters must implement. It extends BaseAgent to maintain compatibility
@@ -35,7 +33,7 @@ Here's how you implement your custom adapter:
```python
from crewai.agents.agent_adapters.base_agent_adapter import BaseAgentAdapter
from crewai.tools import BaseTool
- from typing import List, Optional, Any, Dict
+ from typing import Any
class MyCustomAgentAdapter(BaseAgentAdapter):
# ... implementation details ...
@@ -45,7 +43,7 @@ Here's how you implement your custom adapter:
The constructor should call the parent class constructor `super().__init__(**kwargs)` and perform any initialization specific to your external agent. You can use the optional `agent_config` dictionary passed during CrewAI's `Agent` initialization to configure your adapter and the underlying agent.
```python
- def __init__(self, agent_config: Optional[Dict[str, Any]] = None, **kwargs: Any):
+ def __init__(self, agent_config: dict[str, Any] | None = None, **kwargs: Any):
super().__init__(agent_config=agent_config, **kwargs)
# Initialize your external agent here, possibly using agent_config
# Example: self.external_agent = initialize_my_agent(agent_config)
@@ -56,7 +54,7 @@ Here's how you implement your custom adapter:
This abstract method is crucial. It receives a list of CrewAI `BaseTool` instances. Your implementation must convert or adapt these tools into the format expected by your external agent framework. This might involve wrapping them, extracting specific attributes, or registering them with the external agent instance.
```python
- def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None:
+ def configure_tools(self, tools: list[BaseTool] | None = None) -> None:
if tools:
adapted_tools = []
for tool in tools:
@@ -96,7 +94,7 @@ Here's how you implement your custom tool adapter:
```python
from crewai.agents.agent_adapters.base_tool_adapter import BaseToolAdapter
from crewai.tools import BaseTool
- from typing import List, Any
+ from typing import Any
class MyCustomToolAdapter(BaseToolAdapter):
# ... implementation details ...
@@ -106,7 +104,7 @@ Here's how you implement your custom tool adapter:
This is the core abstract method you must implement. It receives a list of CrewAI `BaseTool` instances provided to the agent. Your task is to iterate through this list, adapt each `BaseTool` into the format expected by your external framework, and store the converted tools in the `self.converted_tools` list (which is initialized in the base class constructor).
```python
- def configure_tools(self, tools: List[BaseTool]) -> None:
+ def configure_tools(self, tools: list[BaseTool]) -> None:
"""Configure and convert CrewAI tools for the specific implementation."""
self.converted_tools = [] # Reset in case it's called multiple times
for tool in tools:
@@ -175,7 +173,7 @@ Here's how you implement your custom tool adapter:
```python
# Inside MyCustomAgentAdapter.configure_tools
- def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None:
+ def configure_tools(self, tools: list[BaseTool] | None = None) -> None:
if tools:
tool_adapter = MyCustomToolAdapter() # Instantiate your tool adapter
tool_adapter.configure_tools(tools) # Convert the tools
@@ -328,7 +326,6 @@ We provide out of the box adapters for the following frameworks:
```python
import json
import os
-from typing import List
from crewai_tools import SerperDevTool
from src.crewai import Agent, Crew, Task
@@ -368,11 +365,9 @@ reporter_agent = LangGraphAgentAdapter(
verbose=True,
)
-
class Code(BaseModel):
code: str
-
task = Task(
description="Give an answer to the coding question: {task}",
expected_output="A thorough answer to the coding question: {task}",
@@ -385,11 +380,9 @@ task2 = Task(
agent=link_finder_agent,
)
-
class Report(BaseModel):
code: str
- links: List[str]
-
+ links: list[str]
task3 = Task(
description="Report the results of the tasks.",
diff --git a/docs/en/learn/conditional-tasks.mdx b/docs/en/learn/conditional-tasks.mdx
index 5c7914fae2..a95ff2c1a7 100644
--- a/docs/en/learn/conditional-tasks.mdx
+++ b/docs/en/learn/conditional-tasks.mdx
@@ -13,7 +13,7 @@ This powerful feature enables crews to make decisions and execute tasks selectiv
## Example Usage
```python Code
-from typing import List
+
from pydantic import BaseModel
from crewai import Agent, Crew
from crewai.tasks.conditional_task import ConditionalTask
@@ -50,7 +50,7 @@ summary_generator_agent = Agent(
)
class EventOutput(BaseModel):
- events: List[str]
+ events: list[str]
task1 = Task(
description="Fetch data about events in San Francisco using Serper tool",
diff --git a/docs/en/learn/custom-llm.mdx b/docs/en/learn/custom-llm.mdx
index 0eee2387a9..71f27ed0f6 100644
--- a/docs/en/learn/custom-llm.mdx
+++ b/docs/en/learn/custom-llm.mdx
@@ -15,11 +15,11 @@ Here's a minimal custom LLM implementation:
```python
from crewai import BaseLLM
-from typing import Any, Dict, List, Optional, Union
+from typing import Any
import requests
class CustomLLM(BaseLLM):
- def __init__(self, model: str, api_key: str, endpoint: str, temperature: Optional[float] = None):
+ def __init__(self, model: str, api_key: str, endpoint: str, temperature: float | None = None):
# IMPORTANT: Call super().__init__() with required parameters
super().__init__(model=model, temperature=temperature)
@@ -28,11 +28,11 @@ class CustomLLM(BaseLLM):
def call(
self,
- messages: Union[str, List[Dict[str, str]]],
- tools: Optional[List[dict]] = None,
- callbacks: Optional[List[Any]] = None,
- available_functions: Optional[Dict[str, Any]] = None,
- ) -> Union[str, Any]:
+ messages: str | list[dict[str, str]],
+ tools: list[dict] | None = None,
+ callbacks: list[Any] | None = None,
+ available_functions: dict[str, Any] | None = None,
+ ) -> str | Any:
"""Call the LLM with the given messages."""
# Convert string to message format if needed
if isinstance(messages, str):
@@ -113,7 +113,7 @@ result = crew.kickoff()
**Critical**: You must call `super().__init__(model, temperature)` with the required parameters:
```python
-def __init__(self, model: str, api_key: str, temperature: Optional[float] = None):
+def __init__(self, model: str, api_key: str, temperature: float | None = None):
# REQUIRED: Call parent constructor with model and temperature
super().__init__(model=model, temperature=temperature)
@@ -176,10 +176,9 @@ def call(self, messages, tools=None, callbacks=None, available_functions=None):
```python
from crewai import BaseLLM
-from typing import Optional
class CustomAuthLLM(BaseLLM):
- def __init__(self, model: str, auth_token: str, endpoint: str, temperature: Optional[float] = None):
+ def __init__(self, model: str, auth_token: str, endpoint: str, temperature: float | None = None):
super().__init__(model=model, temperature=temperature)
self.auth_token = auth_token
self.endpoint = endpoint
@@ -293,7 +292,7 @@ def __init__(self, api_key: str):
super().__init__()
# ✅ Correct
-def __init__(self, model: str, api_key: str, temperature: Optional[float] = None):
+def __init__(self, model: str, api_key: str, temperature: float | None = None):
super().__init__(model=model, temperature=temperature)
```
diff --git a/docs/en/observability/braintrust.mdx b/docs/en/observability/braintrust.mdx
index 21ab52c852..239d4586df 100644
--- a/docs/en/observability/braintrust.mdx
+++ b/docs/en/observability/braintrust.mdx
@@ -47,7 +47,7 @@ Initialize the Braintrust OpenTelemetry instrumentation to start capturing trace
```python
import os
-from typing import Any, Dict
+from typing import Any
from braintrust.otel import BraintrustSpanProcessor
from crewai import Agent, Crew, Task
@@ -70,7 +70,6 @@ def setup_tracing() -> None:
CrewAIInstrumentor().instrument(tracer_provider=provider)
OpenAIInstrumentor().instrument(tracer_provider=provider)
-
setup_tracing()
```
diff --git a/docs/en/quickstart.mdx b/docs/en/quickstart.mdx
index 3b1b76ddfe..cd42670258 100644
--- a/docs/en/quickstart.mdx
+++ b/docs/en/quickstart.mdx
@@ -78,20 +78,19 @@ If you have not installed CrewAI yet, follow the [installation guide](/en/instal
```python content_crew.py
# src/latest_ai_flow/crews/content_crew/content_crew.py
- from typing import List
+
from crewai import Agent, Crew, Process, Task
from crewai.agents.agent_builder.base_agent import BaseAgent
from crewai.project import CrewBase, agent, crew, task
from crewai_tools import SerperDevTool
-
@CrewBase
class ResearchCrew:
"""Single-agent research crew used inside the Flow."""
- agents: List[BaseAgent]
- tasks: List[Task]
+ agents: list[BaseAgent]
+ tasks: list[Task]
agents_config = "config/agents.yaml"
tasks_config = "config/tasks.yaml"
@@ -133,12 +132,10 @@ If you have not installed CrewAI yet, follow the [installation guide](/en/instal
from latest_ai_flow.crews.content_crew.content_crew import ResearchCrew
-
class ResearchFlowState(BaseModel):
topic: str = ""
report: str = ""
-
class LatestAiFlow(Flow[ResearchFlowState]):
@start()
def prepare_topic(self, crewai_trigger_payload: dict | None = None):
@@ -158,15 +155,12 @@ If you have not installed CrewAI yet, follow the [installation guide](/en/instal
def summarize(self):
print("Report path: output/report.md")
-
def kickoff():
LatestAiFlow().kickoff()
-
def plot():
LatestAiFlow().plot()
-
if __name__ == "__main__":
kickoff()
```
@@ -194,9 +188,6 @@ If you have not installed CrewAI yet, follow the [installation guide](/en/instal
`crewai run` executes the Flow entrypoint defined in your project (same command as for crews; project type is `"flow"` in `pyproject.toml`).
-
-
-
You should see logs from the Flow and the crew. Open **`output/report.md`** for the generated report (excerpt):