CrewAI Integration
Matimo integrates seamlessly with CrewAI for multi-agent orchestration. Convert any Matimo tool to a CrewAI BaseTool with a single function call.
- Installation
- Basic Setup
- Single Agent Example
- Multi-Agent Crew Example
- Advanced Patterns
- Troubleshooting
Installation
Section titled “Installation”Requirements
Section titled “Requirements”- Python 3.11+
- CrewAI >= 0.80
- Matimo >= 0.2.0 (the approval callbacks shown here are new in 0.2.0)
Install
Section titled “Install”# Install matimo with CrewAI supportpip install "matimo[crewai]" matimo-slack# or with uvuv add "matimo[crewai]" matimo-slack
# Install CrewAIpip install crewaiBasic Setup
Section titled “Basic Setup”import asyncioimport osfrom matimo import Matimofrom matimo.integrations.crewai import convert_tools_to_crewaifrom crewai import Agent, Task, Crewfrom langchain_openai import ChatOpenAI
async def setup(): # 1. Initialize Matimo matimo = await Matimo.init(auto_discover=True)
# 2. Filter tools (optional: use all or subset) slack_tools_def = [ t for t in matimo.list_tools() if t.name.startswith('slack_') ]
# 3. Convert to CrewAI BaseTool crewai_tools = convert_tools_to_crewai( slack_tools_def, matimo, credentials={'SLACK_BOT_TOKEN': os.environ['SLACK_BOT_TOKEN']}, )
return matimo, crewai_tools
asyncio.run(setup())Approvals and Unset Parameters
Section titled “Approvals and Unset Parameters”A crew’s tool calls go through the same governance as matimo.execute(). Calls to tools that need approval, requires_approval: true, HTTP DELETE or command tools (secure by default in 0.2.0), or a destructive keyword in a sql/command argument, ask the instance’s on_approval callback, and are refused without one:
async def ask_operator(request: ApprovalRequest) -> bool: return await my_ui.confirm(f"Allow {request.tool_name} with {request.params}?")
matimo = await Matimo.init(auto_discover=True, on_approval=ask_operator)crewai_tools = convert_tools_to_crewai(matimo.list_tools(), matimo)CrewAI fills optional parameters the model leaves out with None; since 0.2.0 those are dropped before the call, so the tool’s own defaults apply.
Single Agent Example
Section titled “Single Agent Example”import asyncioimport osfrom matimo import Matimofrom matimo.integrations.crewai import convert_tools_to_crewaifrom crewai import Agent, Task, Crewfrom langchain_openai import ChatOpenAI
async def slack_agent_demo(): # Initialize matimo = await Matimo.init(auto_discover=True)
# Get Slack tools only slack_tools_def = [ t for t in matimo.list_tools() if t.name.startswith('slack_') ]
# Convert to CrewAI tools = convert_tools_to_crewai( slack_tools_def, matimo, credentials={'SLACK_BOT_TOKEN': os.environ['SLACK_BOT_TOKEN']}, )
# Create agent slack_manager = Agent( role='Slack Manager', goal='Send messages and manage Slack channels', tools=tools, llm=ChatOpenAI(model='gpt-4o-mini'), verbose=True, )
# Create task task = Task( description='Send a greeting message to #general channel', agent=slack_manager, expected_output='Message sent successfully', )
# Run crew (actually runs the agent) crew = Crew(agents=[slack_manager], tasks=[task]) result = crew.kickoff() print(f"Result: {result}")
# Runasyncio.run(slack_agent_demo())Multi-Agent Crew Example
Section titled “Multi-Agent Crew Example”import asyncioimport osfrom matimo import Matimofrom matimo.integrations.crewai import convert_tools_to_crewaifrom crewai import Agent, Task, Crewfrom langchain_openai import ChatOpenAI
async def multi_agent_crew(): # Initialize Matimo matimo = await Matimo.init(auto_discover=True)
# Get tools by provider slack_tools = [ t for t in matimo.list_tools() if t.name.startswith('slack_') ] github_tools = [ t for t in matimo.list_tools() if t.name.startswith('github_') ]
# Convert both slack_crewai_tools = convert_tools_to_crewai( slack_tools, matimo, credentials={'SLACK_BOT_TOKEN': os.environ['SLACK_BOT_TOKEN']}, ) github_crewai_tools = convert_tools_to_crewai( github_tools, matimo, credentials={'GITHUB_TOKEN': os.environ['GITHUB_TOKEN']}, )
# Create agents slack_manager = Agent( role='Slack Communicator', goal='Handle all Slack communications', tools=slack_crewai_tools, llm=ChatOpenAI(model='gpt-4o-mini'), )
github_manager = Agent( role='GitHub Coordinator', goal='Manage GitHub repositories and issues', tools=github_crewai_tools, llm=ChatOpenAI(model='gpt-4o-mini'), )
# Create tasks slack_task = Task( description='Post daily standup to #engineering', agent=slack_manager, expected_output='Standup posted', )
github_task = Task( description='List open issues for the project', agent=github_manager, expected_output='Issues listed', )
# Run crew with multiple agents crew = Crew( agents=[slack_manager, github_manager], tasks=[slack_task, github_task], verbose=True, ) result = crew.kickoff() print(f"Crew result: {result}")
asyncio.run(multi_agent_crew())Advanced Patterns
Section titled “Advanced Patterns”Pattern 1: Hierarchical Crew (Manager Pattern)
Section titled “Pattern 1: Hierarchical Crew (Manager Pattern)”from crewai import Agent, Task, Crew
async def hierarchical_crew(): matimo = await Matimo.init(auto_discover=True)
# Worker agents slack_worker = Agent( role='Slack Specialist', goal='Execute Slack operations', tools=convert_tools_to_crewai([...], matimo), )
github_worker = Agent( role='GitHub Specialist', goal='Execute GitHub operations', tools=convert_tools_to_crewai([...], matimo), )
# Manager agent coordinates workers manager = Agent( role='Project Manager', goal='Coordinate team activities', tools=[], # Manager uses reports, not direct tools )
# Tasks with dependencies tasks = [ Task(description='Check GitHub issues', agent=github_worker), Task(description='Post status to Slack', agent=slack_worker), Task(description='Summarize progress', agent=manager), ]
crew = Crew(agents=[slack_worker, github_worker, manager], tasks=tasks) result = crew.kickoff() return result
asyncio.run(hierarchical_crew())Pattern 2: Sequential vs Parallel Execution
Section titled “Pattern 2: Sequential vs Parallel Execution”from crewai import Crew, Process
# Sequential (default): one task at a timecrew_sequential = Crew( agents=[agent1, agent2], tasks=[task1, task2], # task2 waits for task1 process=Process.sequential, # Default)
# Hierarchical: manager coordinates workerscrew_hierarchical = Crew( agents=[worker1, worker2, manager], tasks=[task1, task2, task3], process=Process.hierarchical, manager_agent=manager,)
result = crew_sequential.kickoff()Pattern 3: Custom Credentials Per Agent
Section titled “Pattern 3: Custom Credentials Per Agent”import os
async def custom_credentials(): matimo = await Matimo.init(auto_discover=True)
# Different credentials for different agents agent1_tools = convert_tools_to_crewai( tools, matimo, credentials={ 'SLACK_BOT_TOKEN': os.environ.get('SLACK_BOT_TOKEN_PROD'), } )
agent2_tools = convert_tools_to_crewai( tools, matimo, credentials={ 'SLACK_BOT_TOKEN': os.environ.get('SLACK_BOT_TOKEN_DEV'), } )
# Agents use isolated credentials agent1 = Agent(..., tools=agent1_tools) agent2 = Agent(..., tools=agent2_tools)Troubleshooting
Section titled “Troubleshooting”Issue: Tools Not Showing in Agent
Section titled “Issue: Tools Not Showing in Agent”Problem: Agent can’t see/use tools in CrewAI.
Solution: Verify tools are converted properly:
tools = convert_tools_to_crewai(tool_definitions, matimo)print(f"Converted {len(tools)} tools")print([t.name for t in tools]) # Should see tool namesIssue: Credentials Not Working
Section titled “Issue: Credentials Not Working”Problem: Tool execution fails with authentication error.
Solution: Pass credentials at conversion time:
tools = convert_tools_to_crewai( tool_definitions, matimo, credentials={'SLACK_BOT_TOKEN': os.environ['SLACK_BOT_TOKEN']},)Issue: Performance/Timeout
Section titled “Issue: Performance/Timeout”Problem: Tools run slow or timeout in Jupyter/async context.
Solution: CrewAI uses a shared executor for event loops; ensure Jupyter environment has async support:
# In Jupyter, use asyncio properlyimport asyncioimport nest_asyncio
nest_asyncio.apply() # Allow nested event loopsBest Practices
Section titled “Best Practices”-
Filter tools by provider: Don’t load all 153 native tools; be specific
slack_tools = [t for t in matimo.list_tools() if 'slack' in t.name] -
Pass credentials at conversion: Isolate credentials per agent
tools = convert_tools_to_crewai(slack_tools, matimo, credentials={...}) -
Use descriptive agent roles: Help LLM understand tool purpose
Agent(role='Slack Message Sender', goal='Send messages to Slack', ...) -
Set verbose=True for debugging: See what the agent is doing
crew = Crew(..., verbose=True) -
Monitor tool coverage: Ensure agent has the tools it needs
print(f"Agent has {len(agent.tools)} tools")
See Also
Section titled “See Also”- LangChain Integration
- Agno Integration: Use with LangChain agents
- Native Python Patterns: SDK without framework
- Tool Discovery: Provider packages and their tools
- API Reference: Python SDK API