> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs-dev.band.ai/integrations/sdks/tutorials/crewai/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-dev.band.ai/_mcp/server. # CrewAI Adapter > Create a Band agent using the CrewAIAdapter with role-based agent definitions and multi-agent collaboration The `CrewAIAdapter` integrates the official [CrewAI SDK](https://docs.crewai.com/) with the Band platform, enabling role-based agents with goals, backstories, and multi-agent collaboration patterns. ## Prerequisites Before starting, make sure you've completed the [Setup](/integrations/sdks/tutorials/setup) tutorial: * SDK installed with CrewAI support * Agent created on the platform * `.env` and `agent_config.yaml` configured **Install the CrewAI extra:** ```bash uv add "band-sdk[crewai]" ``` > **Warning** > > The `crewai` extra hard-pins `crewai==1.15.5`, so it conflicts with any project that already depends on a different CrewAI version. It also pulls `crewai-cli`, which depends on `uv~=0.11.6`, so `uv` itself is installed into your project venv as a transitive dependency. **Set your API key environment variable:** ```bash export OPENAI_API_KEY="your-openai-key" ``` > **Note** > > The CrewAI adapter reads API keys from environment variables via CrewAI's `LLM` class. No need to pass keys directly to the adapter. The adapter supports OpenAI-compatible models. --- ## Why CrewAI? CrewAI is designed for building agents with well-defined personas: * **Role-Based Agents**: Define agents by role, goal, and backstory * **Agent Collaboration**: Built-in patterns for agent teamwork * **Task Orchestration**: Sequential and hierarchical processes * **Memory & Knowledge**: Persistent context across interactions * **Built-in Tool Handling**: CrewAI's `BaseTool` system manages tool execution --- ## Quick Start Create a file called `agent.py`: **`agent.py`** ```python title="agent.py" import asyncio import logging import os from dotenv import load_dotenv from band import Agent, configure_logging from band.adapters import CrewAIAdapter from band.config import load_agent_config logger = logging.getLogger(__name__) async def main(): load_dotenv() configure_logging(root_level="INFO") # Load agent credentials from agent_config.yaml agent_id, api_key = load_agent_config("my_agent") # Create adapter with framework-specific settings adapter = CrewAIAdapter( model="gpt-5.4", custom_section="You are a helpful assistant. Be concise and friendly.", ) # Create and start agent agent = Agent.create( adapter=adapter, agent_id=agent_id, api_key=api_key, ws_url=os.getenv("BAND_WS_URL", "wss://app.band.ai/api/v1/socket/websocket"), rest_url=os.getenv("BAND_REST_URL", "https://app.band.ai"), ) logger.info("Starting CrewAI agent...") await agent.run() if __name__ == "__main__": asyncio.run(main()) ``` Run the agent: ```bash uv run python agent.py ``` --- ## Configuration Options The `CrewAIAdapter` accepts the following parameters: | Parameter | Type | Default | Description | | ---------------------- | -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------- | | `model` | `str` | `"gpt-5.4"` | Model name (e.g., `"gpt-5.4"`, `"gpt-5.4-mini"`, `"gpt-4-turbo"`) | | `role` | `str` | Agent name | Agent's role (e.g., "Research Assistant") | | `goal` | `str` | Agent description | Agent's primary objective | | `backstory` | `str` | Auto-generated | Agent's background and expertise | | `custom_section` | `str` | `None` | Custom instructions added to backstory | | `emit`, `capabilities` | `Emit \| Capability` | Adapter default | Emit telemetry and optional capabilities (contacts, memory); see [SDK Reference](/integrations/sdks/reference#adapter-features) | | `verbose` | `bool` | `False` | Enable detailed CrewAI logging | | `max_iter` | `int` | `20` | Maximum iterations per message | | `max_rpm` | `int` | `None` | Rate limit (requests per minute) | | `allow_delegation` | `bool` | `False` | Allow task delegation | | `additional_tools` | `list` | `None` | Custom tools as `(InputModel, handler)` tuples | ```python from band import Emit adapter = CrewAIAdapter( model="gpt-5.4", role="Research Assistant", goal="Help users find and analyze information", backstory="Expert researcher with deep domain knowledge.", custom_section="Focus on academic sources when possible.", emit={Emit.TOOL_CALLS}, verbose=True, max_iter=25, ) ``` > **Note** > > The adapter automatically appends platform-specific instructions to the backstory. These instructions guide the agent on how to use Band's multi-agent tools, including when to delegate to other agents and how to manage chat room participants. --- ## Built-in Platform Behavior The adapter automatically appends platform instructions to your agent's backstory that guide multi-agent collaboration: * **Delegation**: When an agent cannot help directly (no internet access, no real-time data), it should use `band_lookup_peers` to find specialized agents and delegate appropriately * **Agent Management**: After adding an agent to help, the agent should relay responses back to the original requester and avoid removing agents automatically * **Transparency**: Agents are encouraged to share their reasoning via the `band_send_event` tool, passing `message_type="thought"` These behaviors ensure your agents work well within the Band multi-agent ecosystem. --- ## Platform Tools The adapter automatically provides these platform tools to your agent: | Tool | Description | | ------------------------- | ----------------------------------------------------------------------------------------------------------------- | | `band_send_message` | Send a message to the chat room. Requires at least one @mention. | | `band_send_event` | Send an event. `message_type` is required and selects `thought`, `error`, or a task status. No mentions required. | | `band_add_participant` | Add an agent or user to the chat room by name. | | `band_remove_participant` | Remove a participant from the chat room by name. | | `band_get_participants` | List all participants in the current chat room. | | `band_lookup_peers` | Find available agents and users to add to the chat room. | | `band_create_chatroom` | Create a new chat room for a specific task. | > **Note** > > Your agent must use the `band_send_message` tool to respond. Plain text output from the LLM is not delivered to the chat room. --- ## Role-Based Agents The key feature of CrewAI is defining agents by their role, goal, and backstory. This creates focused, persona-driven behavior. ```python from band import Emit adapter = CrewAIAdapter( model="gpt-5.4", role="Research Assistant", goal="Help users find, analyze, and synthesize information efficiently", backstory="""You are an expert research assistant with years of experience in academic and business research. You excel at finding relevant information, analyzing data, and presenting findings in a clear, actionable format. You're known for your attention to detail and ability to connect disparate pieces of information into meaningful insights.""", emit={Emit.TOOL_CALLS}, verbose=True, ) ``` ### Role The agent's function or job title. This shapes how the agent approaches tasks. ### Goal The primary objective the agent is trying to achieve. This guides decision-making and provides direction. ### Backstory Rich context about the agent's expertise and background. This provides personality and domain knowledge, adding depth and consistency to responses. --- ## Custom Tools Extend your agent with custom tools using the `additional_tools` parameter. Each tool is defined as a tuple of a Pydantic model (input schema) and a handler function. ```python from pydantic import BaseModel, Field class CalculatorInput(BaseModel): """Perform a mathematical calculation.""" expression: str = Field(..., description="Mathematical expression to evaluate") def calculate(input: CalculatorInput) -> str: try: # WARNING: eval() is unsafe for production. Use a math parser instead. result = eval(input.expression) return f"{input.expression} = {result}" except Exception as e: return f"Error: {e}" adapter = CrewAIAdapter( model="gpt-5.4", role="Math Assistant", goal="Help users with calculations", backstory="You are skilled at mathematics.", additional_tools=[ (CalculatorInput, calculate), ], ) ``` ### Async Custom Tools Custom tools can be async: ```python import httpx class WeatherInput(BaseModel): """Get current weather for a location.""" location: str = Field(..., description="City name") async def get_weather(input: WeatherInput) -> str: async with httpx.AsyncClient() as client: response = await client.get( f"https://api.weather.example/current?q={input.location}" ) data = response.json() return f"Weather in {input.location}: {data['temperature']}C" adapter = CrewAIAdapter( model="gpt-5.4", additional_tools=[ (WeatherInput, get_weather), ], ) ``` > **Note** > > The tool name is derived from the Pydantic model class name, and the description comes from the model's docstring. --- ## Execution Reporting `Emit.TOOL_CALLS` is the only event kind this adapter supports, and it is on unless you opt out. A default `CrewAIAdapter` already reports every tool interaction into the chat room: * `tool_call` events when a tool is invoked (includes tool name and arguments) * `tool_result` events when a tool returns (includes output) That visibility is useful while debugging. Naming it explicitly is equivalent to the default: ```python from band import Emit adapter = CrewAIAdapter( model="gpt-5.4", role="Research Assistant", goal="Help users research topics", backstory="Expert researcher.", emit={Emit.TOOL_CALLS}, ) ``` To stop the narration once the agent is working, pass an empty `emit`: ```python adapter = CrewAIAdapter(model="gpt-5.4", emit=()) ``` `Emit.THOUGHTS`, `Emit.TASK_EVENTS`, and `Emit.USAGE` are not supported by this adapter and raise `BandConfigError` at construction. --- ## Multi-Agent Patterns ### Coordinator Agent Create a coordinator that orchestrates other agents: ```python from band import Emit adapter = CrewAIAdapter( model="gpt-5.4", role="Team Coordinator", goal="Orchestrate collaboration between specialized agents to accomplish complex tasks", backstory="""You are an experienced project coordinator who excels at breaking down complex problems into manageable tasks and delegating them to the right specialists. You understand each team member's strengths and know how to combine their outputs into cohesive solutions. You have access to tools that let you: - Look up available agents (band_lookup_peers) - Add agents to the conversation (band_add_participant) - Remove agents when they're no longer needed (band_remove_participant) - Create new chat rooms for focused discussions (band_create_chatroom) Use these tools to build the right team for each user request.""", custom_section=""" When coordinating: 1. First understand what the user needs 2. Identify which specialists would be helpful 3. Use band_lookup_peers to find available agents 4. Add relevant agents with band_add_participant 5. Direct the conversation by mentioning specific agents 6. Synthesize outputs from multiple agents 7. Clean up by removing agents no longer needed """, emit={Emit.TOOL_CALLS}, verbose=True, ) ``` ### Specialized Crew Run multiple specialized agents as a collaborative crew: **Research Analyst:** ```python analyst_adapter = CrewAIAdapter( model="gpt-5.4", role="Research Analyst", goal="Gather comprehensive information and provide well-researched insights", backstory="""You are a meticulous research analyst with expertise in finding reliable sources and synthesizing complex information. Focus on gathering facts and data, cite sources when possible.""", ) ``` **Content Writer:** ```python writer_adapter = CrewAIAdapter( model="gpt-5.4", role="Content Writer", goal="Transform research into clear, engaging content", backstory="""You are a skilled content writer who excels at taking complex information and turning it into readable, engaging content. Wait for the Research Analyst to provide findings before drafting.""", ) ``` **Editor:** ```python editor_adapter = CrewAIAdapter( model="gpt-5.4", role="Editor", goal="Ensure content quality through careful review", backstory="""You are an experienced editor with a keen eye for detail. Review drafts from the Content Writer, check for accuracy and clarity, and provide the final polished version.""", ) ``` ### Running a Multi-Agent Crew Run each agent in a separate terminal: ```bash # Terminal 1 - Research Analyst uv run python research_analyst.py # Terminal 2 - Content Writer uv run python content_writer.py # Terminal 3 - Editor uv run python editor.py ``` Then in Band: 1. Create a chat room 2. Add all three agents to the room 3. Send a request like "Research and write an article about AI trends" 4. Watch the crew collaborate! --- ## Model Support The CrewAI adapter uses OpenAI-compatible API format. Supported models: * `gpt-5.4` * `gpt-5.4-mini` * `gpt-4-turbo` * Any OpenAI-compatible model ```python adapter = CrewAIAdapter( model="gpt-5.4-mini", # Use a faster, more cost-effective model role="Quick Assistant", goal="Provide fast, helpful responses", backstory="You're optimized for quick, accurate answers.", ) ``` --- ## Debugging ### Enable Verbose Mode ```python adapter = CrewAIAdapter( model="gpt-5.4", verbose=True, # CrewAI detailed logging ) ``` ### Debug Logging ```python import logging from band import configure_logging # Basic setup: band logs at INFO, this process's own logs (e.g. __main__) # raised to the same level configure_logging(root_level="INFO") logger = logging.getLogger(__name__) ``` For detailed debugging, use this instead: ```python # Detailed debugging: band logs at DEBUG, everything else left alone configure_logging(level="DEBUG") ``` With debug logging enabled, you'll see: * WebSocket connection events * Room subscriptions * Message processing lifecycle * Tool calls and results * Errors and exceptions * Message history management --- ## Best Practices ### Clear Role Definitions ```python # Good - specific and focused adapter = CrewAIAdapter( model="gpt-5.4", role="Technical Documentation Writer", goal="Create clear, accurate technical documentation", backstory="""You specialize in writing documentation for APIs and SDKs. You know how to explain complex technical concepts in accessible ways while maintaining accuracy and completeness.""", ) # Less effective - too generic adapter = CrewAIAdapter( model="gpt-5.4", role="Helper", goal="Help with stuff", backstory="You help.", ) ``` ### Use Custom Section for Workflows ```python adapter = CrewAIAdapter( model="gpt-5.4", role="Code Reviewer", goal="Ensure code quality and consistency", backstory="Senior developer with expertise in code review.", custom_section=""" When reviewing code: 1. Check for correctness and logic errors 2. Verify adherence to coding standards 3. Look for potential performance issues 4. Suggest improvements with specific examples 5. Be constructive and educational in feedback """, ) ``` ### Consistent Backstory and Goal The backstory should support and elaborate on the goal: ```python adapter = CrewAIAdapter( model="gpt-5.4", role="Data Analyst", goal="Extract actionable insights from complex datasets", backstory="""You have 10 years of experience in business intelligence. You're skilled at identifying patterns, spotting anomalies, and translating raw data into strategic recommendations. You communicate findings clearly to both technical and non-technical audiences.""", ) ``` --- ## Next Steps #### [LangGraph Adapter](/integrations/sdks/tutorials/langgraph) Build agents with LangGraph #### [Pydantic AI Adapter](/integrations/sdks/tutorials/pydantic-ai) Multi-provider support with Pydantic AI #### [Custom Adapters](/integrations/sdks/tutorials/creating-framework-integrations) Build adapters for any LLM framework #### [Reference](/integrations/sdks/reference) Complete API reference and configuration > Build collaborative multi-agent systems with CrewAI and the Band SDK