Skip to content
Open
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
2 changes: 0 additions & 2 deletions docs/en/guides/concepts/evaluating-use-cases.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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 = ""
Expand Down
6 changes: 2 additions & 4 deletions docs/en/guides/crews/first-crew.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ This will generate a project with the basic structure needed for your crew. The
<img src="/images/crews.png" alt="CrewAI Framework Overview" />
</Frame>


## 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.
Expand Down Expand Up @@ -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:
Expand Down
13 changes: 6 additions & 7 deletions docs/en/guides/flows/first-flow.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -286,15 +285,15 @@ 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
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"""
Expand Down Expand Up @@ -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.
Expand Down
16 changes: 6 additions & 10 deletions docs/en/guides/flows/mastering-flow-state.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -469,15 +467,14 @@ 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
active: bool = True
login_count: int = 0

class ComplexState(BaseModel):
users: Dict[str, UserData] = {}
users: dict[str, UserData] = {}
active_user_count: int = 0

class TransformationFlow(Flow[ComplexState]):
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down
21 changes: 7 additions & 14 deletions docs/en/learn/bring-your-own-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ 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.

1. BaseAgentAdapter
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
Expand All @@ -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 ...
Expand All @@ -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)
Expand All @@ -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:
Expand Down Expand Up @@ -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 ...
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}",
Expand All @@ -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.",
Expand Down
4 changes: 2 additions & 2 deletions docs/en/learn/conditional-tasks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand Down
21 changes: 10 additions & 11 deletions docs/en/learn/custom-llm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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):
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
```

Expand Down
3 changes: 1 addition & 2 deletions docs/en/observability/braintrust.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -70,7 +70,6 @@ def setup_tracing() -> None:
CrewAIInstrumentor().instrument(tracer_provider=provider)
OpenAIInstrumentor().instrument(tracer_provider=provider)


setup_tracing()
```

Expand Down
Loading