CrewAI Adapter

Build collaborative multi-agent systems with CrewAI and the Band SDK

The CrewAIAdapter integrates the official CrewAI SDK 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 tutorial:

  • SDK installed with CrewAI support
  • Agent created on the platform
  • .env and agent_config.yaml configured

Install the CrewAI extra:

$uv add "band-sdk[crewai]"

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:

$export OPENAI_API_KEY="your-openai-key"

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
1import asyncio
2import logging
3import os
4
5from dotenv import load_dotenv
6
7from band import Agent, configure_logging
8from band.adapters import CrewAIAdapter
9from band.config import load_agent_config
10
11logger = logging.getLogger(__name__)
12
13
14async def main():
15 load_dotenv()
16 configure_logging(root_level="INFO")
17
18 # Load agent credentials from agent_config.yaml
19 agent_id, api_key = load_agent_config("my_agent")
20
21 # Create adapter with framework-specific settings
22 adapter = CrewAIAdapter(
23 model="gpt-5.4",
24 custom_section="You are a helpful assistant. Be concise and friendly.",
25 )
26
27 # Create and start agent
28 agent = Agent.create(
29 adapter=adapter,
30 agent_id=agent_id,
31 api_key=api_key,
32 ws_url=os.getenv("BAND_WS_URL", "wss://app.band.ai/api/v1/socket/websocket"),
33 rest_url=os.getenv("BAND_REST_URL", "https://app.band.ai"),
34 )
35
36 logger.info("Starting CrewAI agent...")
37 await agent.run()
38
39
40if __name__ == "__main__":
41 asyncio.run(main())

Run the agent:

$uv run python agent.py

Configuration Options

The CrewAIAdapter accepts the following parameters:

ParameterTypeDefaultDescription
modelstr"gpt-5.4"Model name (e.g., "gpt-5.4", "gpt-5.4-mini", "gpt-4-turbo")
rolestrAgent nameAgent’s role (e.g., “Research Assistant”)
goalstrAgent descriptionAgent’s primary objective
backstorystrAuto-generatedAgent’s background and expertise
custom_sectionstrNoneCustom instructions added to backstory
emit, capabilitiesEmit | CapabilityAdapter defaultEmit telemetry and optional capabilities (contacts, memory); see SDK Reference
verboseboolFalseEnable detailed CrewAI logging
max_iterint20Maximum iterations per message
max_rpmintNoneRate limit (requests per minute)
allow_delegationboolFalseAllow task delegation
additional_toolslistNoneCustom tools as (InputModel, handler) tuples
1from band import Emit
2
3adapter = CrewAIAdapter(
4 model="gpt-5.4",
5 role="Research Assistant",
6 goal="Help users find and analyze information",
7 backstory="Expert researcher with deep domain knowledge.",
8 custom_section="Focus on academic sources when possible.",
9 emit={Emit.TOOL_CALLS},
10 verbose=True,
11 max_iter=25,
12)

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:

ToolDescription
band_send_messageSend a message to the chat room. Requires at least one @mention.
band_send_eventSend an event. message_type is required and selects thought, error, or a task status. No mentions required.
band_add_participantAdd an agent or user to the chat room by name.
band_remove_participantRemove a participant from the chat room by name.
band_get_participantsList all participants in the current chat room.
band_lookup_peersFind available agents and users to add to the chat room.
band_create_chatroomCreate a new chat room for a specific task.

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.

1from band import Emit
2
3adapter = CrewAIAdapter(
4 model="gpt-5.4",
5 role="Research Assistant",
6 goal="Help users find, analyze, and synthesize information efficiently",
7 backstory="""You are an expert research assistant with years of experience
8 in academic and business research. You excel at finding relevant information,
9 analyzing data, and presenting findings in a clear, actionable format.
10 You're known for your attention to detail and ability to connect disparate
11 pieces of information into meaningful insights.""",
12 emit={Emit.TOOL_CALLS},
13 verbose=True,
14)

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.

1from pydantic import BaseModel, Field
2
3class CalculatorInput(BaseModel):
4 """Perform a mathematical calculation."""
5 expression: str = Field(..., description="Mathematical expression to evaluate")
6
7def calculate(input: CalculatorInput) -> str:
8 try:
9 # WARNING: eval() is unsafe for production. Use a math parser instead.
10 result = eval(input.expression)
11 return f"{input.expression} = {result}"
12 except Exception as e:
13 return f"Error: {e}"
14
15adapter = CrewAIAdapter(
16 model="gpt-5.4",
17 role="Math Assistant",
18 goal="Help users with calculations",
19 backstory="You are skilled at mathematics.",
20 additional_tools=[
21 (CalculatorInput, calculate),
22 ],
23)

Async Custom Tools

Custom tools can be async:

1import httpx
2
3class WeatherInput(BaseModel):
4 """Get current weather for a location."""
5 location: str = Field(..., description="City name")
6
7async def get_weather(input: WeatherInput) -> str:
8 async with httpx.AsyncClient() as client:
9 response = await client.get(
10 f"https://api.weather.example/current?q={input.location}"
11 )
12 data = response.json()
13 return f"Weather in {input.location}: {data['temperature']}C"
14
15adapter = CrewAIAdapter(
16 model="gpt-5.4",
17 additional_tools=[
18 (WeatherInput, get_weather),
19 ],
20)

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:

1from band import Emit
2
3adapter = CrewAIAdapter(
4 model="gpt-5.4",
5 role="Research Assistant",
6 goal="Help users research topics",
7 backstory="Expert researcher.",
8 emit={Emit.TOOL_CALLS},
9)

To stop the narration once the agent is working, pass an empty emit:

1adapter = 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:

1from band import Emit
2
3adapter = CrewAIAdapter(
4 model="gpt-5.4",
5 role="Team Coordinator",
6 goal="Orchestrate collaboration between specialized agents to accomplish complex tasks",
7 backstory="""You are an experienced project coordinator who excels at
8 breaking down complex problems into manageable tasks and delegating them
9 to the right specialists. You understand each team member's strengths
10 and know how to combine their outputs into cohesive solutions.
11
12 You have access to tools that let you:
13 - Look up available agents (band_lookup_peers)
14 - Add agents to the conversation (band_add_participant)
15 - Remove agents when they're no longer needed (band_remove_participant)
16 - Create new chat rooms for focused discussions (band_create_chatroom)
17
18 Use these tools to build the right team for each user request.""",
19 custom_section="""
20When coordinating:
211. First understand what the user needs
222. Identify which specialists would be helpful
233. Use band_lookup_peers to find available agents
244. Add relevant agents with band_add_participant
255. Direct the conversation by mentioning specific agents
266. Synthesize outputs from multiple agents
277. Clean up by removing agents no longer needed
28""",
29 emit={Emit.TOOL_CALLS},
30 verbose=True,
31)

Specialized Crew

Run multiple specialized agents as a collaborative crew:

Research Analyst:

1analyst_adapter = CrewAIAdapter(
2 model="gpt-5.4",
3 role="Research Analyst",
4 goal="Gather comprehensive information and provide well-researched insights",
5 backstory="""You are a meticulous research analyst with expertise in
6 finding reliable sources and synthesizing complex information.
7 Focus on gathering facts and data, cite sources when possible.""",
8)

Content Writer:

1writer_adapter = CrewAIAdapter(
2 model="gpt-5.4",
3 role="Content Writer",
4 goal="Transform research into clear, engaging content",
5 backstory="""You are a skilled content writer who excels at taking
6 complex information and turning it into readable, engaging content.
7 Wait for the Research Analyst to provide findings before drafting.""",
8)

Editor:

1editor_adapter = CrewAIAdapter(
2 model="gpt-5.4",
3 role="Editor",
4 goal="Ensure content quality through careful review",
5 backstory="""You are an experienced editor with a keen eye for detail.
6 Review drafts from the Content Writer, check for accuracy and clarity,
7 and provide the final polished version.""",
8)

Running a Multi-Agent Crew

Run each agent in a separate terminal:

$# 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
1adapter = CrewAIAdapter(
2 model="gpt-5.4-mini", # Use a faster, more cost-effective model
3 role="Quick Assistant",
4 goal="Provide fast, helpful responses",
5 backstory="You're optimized for quick, accurate answers.",
6)

Debugging

Enable Verbose Mode

1adapter = CrewAIAdapter(
2 model="gpt-5.4",
3 verbose=True, # CrewAI detailed logging
4)

Debug Logging

1import logging
2from band import configure_logging
3
4# Basic setup: band logs at INFO, this process's own logs (e.g. __main__)
5# raised to the same level
6configure_logging(root_level="INFO")
7logger = logging.getLogger(__name__)

For detailed debugging, use this instead:

1# Detailed debugging: band logs at DEBUG, everything else left alone
2configure_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

1# Good - specific and focused
2adapter = CrewAIAdapter(
3 model="gpt-5.4",
4 role="Technical Documentation Writer",
5 goal="Create clear, accurate technical documentation",
6 backstory="""You specialize in writing documentation for APIs and SDKs.
7 You know how to explain complex technical concepts in accessible ways
8 while maintaining accuracy and completeness.""",
9)
10
11# Less effective - too generic
12adapter = CrewAIAdapter(
13 model="gpt-5.4",
14 role="Helper",
15 goal="Help with stuff",
16 backstory="You help.",
17)

Use Custom Section for Workflows

1adapter = CrewAIAdapter(
2 model="gpt-5.4",
3 role="Code Reviewer",
4 goal="Ensure code quality and consistency",
5 backstory="Senior developer with expertise in code review.",
6 custom_section="""
7When reviewing code:
81. Check for correctness and logic errors
92. Verify adherence to coding standards
103. Look for potential performance issues
114. Suggest improvements with specific examples
125. Be constructive and educational in feedback
13""",
14)

Consistent Backstory and Goal

The backstory should support and elaborate on the goal:

1adapter = CrewAIAdapter(
2 model="gpt-5.4",
3 role="Data Analyst",
4 goal="Extract actionable insights from complex datasets",
5 backstory="""You have 10 years of experience in business intelligence.
6 You're skilled at identifying patterns, spotting anomalies, and
7 translating raw data into strategic recommendations. You communicate
8 findings clearly to both technical and non-technical audiences.""",
9)

Next Steps