CrewAI Adapter for uAgents
This example shows how to expose a CrewAI trip-planning crew as a uAgent with CrewaiRegisterTool from uagents-adapter.
CrewaiRegisterTool does not read AGENT_SEED. The mailbox seed is derived as uagent_seed_{name} and {port}. If you keep the sample name and port, every reader gets the same address. Change name (and optionally port) before you run the agent.
Prerequisites
- Python 3.11+ (the example README specifies 3.11)
- An OpenAI API key
- An Agentverse API key
- Read the uAgents Adapter guide for shared adapter parameters (
mailbox,ai_agent_address, and so on)
Getting Started
1. Clone the parent example repo
The trip planner lives in a subdirectory of fetchai/innovation-lab-examples. Clone the parent repository, then cd into Crewai-agents/trip_planner (there is no crewai-example/ folder).
macOS / Linux:
git clone https://github.com/fetchai/innovation-lab-examples.git
cd innovation-lab-examples/Crewai-agents/trip_planner
python3.11 -m venv venv
source venv/bin/activate
Windows (PowerShell):
git clone https://github.com/fetchai/innovation-lab-examples.git
cd innovation-lab-examples\Crewai-agents\trip_planner
py -3.11 -m venv venv
venv\Scripts\activate
2. Install dependencies
Install the versions this page uses. Do not run pip install -r requirements.txt from the cloned example until that file is updated: it still pins uagents-adapter==0.2.1 and uagents==0.22.3, which do not match CrewaiRegisterTool 0.6.2.
pip install uagents==0.25.5 "uagents-adapter[crewai]==0.6.2" python-dotenv langchain-openai
The [crewai] extra pulls in crewai==0.203.1 for adapter 0.6.2.
3. Environment variables
Create a .env file in Crewai-agents/trip_planner. Canonical Agentverse variable name (same as other Innovation Lab adapter pages):
OPENAI_API_KEY=your_openai_key
AGENTVERSE_API_KEY=your_agentverse_key
| Variable | Required? | Notes |
|---|---|---|
OPENAI_API_KEY | Yes | Used by the crew LLM (gpt-4o in trip_agents.py) and by NL parameter extraction |
AGENTVERSE_API_KEY | Yes | Mailbox / Agentverse registration. Older main_uagents.py in the example repo still reads AV_API_KEY; the sample below accepts either name |
AI_AGENT_ADDRESS | No | Override the NL formatter uAgent (agent1q...). If unset, the adapter default is used |
SERPER_API_KEY, BROWSERLESS_API_KEY, OPENWEATHER_API_KEY, SEARCH_API_KEY | No | Present in the example .env.example, but current trip_agents.py / trip_tasks.py are LLM-only and do not call those tools |
Do not set AGENT_SEED. It is unused by CrewaiRegisterTool.
4. Run the uAgents wrapper
Replace cloned main_uagents.py with the sample in this page (or edit the clone so it matches: AGENTVERSE_API_KEY, unique name, return_dict=True, optional AI_AGENT_ADDRESS). The example repo currently uses a different name, port 8033, AV_API_KEY, and a hardcoded ai_agent_address.
python main_uagents.py
Windows:
python main_uagents.py
5. Inspector and local agents
Copy the inspector URL from the agent output, or open Local agents and select your crew agent.
6. Chat from ASI:One
Copy the printed agent address into ASI:One and send a natural-language request that maps to query_params:
Plan a trip for me from London to Paris starting on 22 April 2026. I am interested in mountains, beaches, and history.
That maps to origin=London, cities=Paris, date_range=starting on 22 April 2026, interests=mountains, beaches, and history.
Optional: example client_agent.py
The example README also documents client_agent.py, a second uAgent that sends trip requests. You can skip it if you use ASI:One. If you run it, point it at the address printed by main_uagents.py (it changes when you change name or port).
Overview
The CrewAI adapter lets you:
- Run specialized CrewAI roles as one collaborative crew
- Expose that crew as a uAgent on Agentverse (mailbox + chat)
- Accept structured
query_paramsor natural-language chat that is extracted into those fields
Trip Planner Example
Standard CrewAI (main.py)
Interactive CLI without uAgents:
from textwrap import dedent
from crewai import Crew
from dotenv import load_dotenv
from trip_agents import TripAgents
from trip_tasks import TripTasks
load_dotenv()
class TripCrew:
def __init__(self, origin, cities, date_range, interests):
self.cities = cities
self.origin = origin
self.interests = interests
self.date_range = date_range
def run(self):
agents = TripAgents()
tasks = TripTasks()
city_selector_agent = agents.city_selection_agent()
local_expert_agent = agents.local_expert()
travel_concierge_agent = agents.travel_concierge()
identify_task = tasks.identify_task(
city_selector_agent,
self.origin,
self.cities,
self.interests,
self.date_range,
)
gather_task = tasks.gather_task(
local_expert_agent, self.origin, self.interests, self.date_range
)
plan_task = tasks.plan_task(
travel_concierge_agent, self.origin, self.interests, self.date_range
)
crew = Crew(
agents=[city_selector_agent, local_expert_agent, travel_concierge_agent],
tasks=[identify_task, gather_task, plan_task],
verbose=True,
)
result = crew.kickoff()
return result
if __name__ == "__main__":
print("## Welcome to Trip Planner Crew")
print("-------------------------------")
location = input(
dedent(
"""
From where will you be traveling from?
"""
)
)
cities = input(
dedent(
"""
What are the cities options you are interested in visiting?
"""
)
)
date_range = input(
dedent(
"""
What is the date range you are interested in traveling?
"""
)
)
interests = input(
dedent(
"""
What are some of your high level interests and hobbies?
"""
)
)
trip_crew = TripCrew(location, cities, date_range, interests)
result = trip_crew.run()
print("\n\n########################")
print("## Here is your Trip Plan")
print("########################\n")
print(result)
uAgents integration (main_uagents.py)
#!/usr/bin/env python3
"""Trip Planner script using CrewAI adapter for uAgents."""
import os
import time
from crewai import Crew
from dotenv import load_dotenv
from uagents_adapter import CrewaiRegisterTool
from trip_agents import TripAgents
from trip_tasks import TripTasks
class TripCrew:
def __init__(self, origin, cities, date_range, interests):
self.cities = cities
self.origin = origin
self.interests = interests
self.date_range = date_range
def run(self):
agents = TripAgents()
tasks = TripTasks()
city_selector_agent = agents.city_selection_agent()
local_expert_agent = agents.local_expert()
travel_concierge_agent = agents.travel_concierge()
identify_task = tasks.identify_task(
city_selector_agent,
self.origin,
self.cities,
self.interests,
self.date_range,
)
gather_task = tasks.gather_task(
local_expert_agent, self.origin, self.interests, self.date_range
)
plan_task = tasks.plan_task(
travel_concierge_agent, self.origin, self.interests, self.date_range
)
crew = Crew(
agents=[city_selector_agent, local_expert_agent, travel_concierge_agent],
tasks=[identify_task, gather_task, plan_task],
verbose=True,
)
result = crew.kickoff()
return result
def kickoff(self, inputs=None):
"""Adapter between uAgents messages and CrewAI."""
if inputs:
self.origin = inputs.get("origin", self.origin)
self.cities = inputs.get("cities", self.cities)
self.date_range = inputs.get("date_range", self.date_range)
self.interests = inputs.get("interests", self.interests)
return self.run()
def main():
load_dotenv()
api_key = os.getenv("AGENTVERSE_API_KEY") or os.getenv("AV_API_KEY")
openai_api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
print("Error: AGENTVERSE_API_KEY not found in environment")
return
if not openai_api_key:
print("Error: OPENAI_API_KEY not found in environment")
return
os.environ["OPENAI_API_KEY"] = openai_api_key
trip_crew = TripCrew("", "", "", "")
register_tool = CrewaiRegisterTool()
query_params = {
"origin": {"type": "str", "required": True},
"cities": {"type": "str", "required": True},
"date_range": {"type": "str", "required": True},
"interests": {"type": "str", "required": True},
}
tool_input = {
"crew_obj": trip_crew,
# Change this so your address is unique
"name": "trip-planner-crew-YOUR_UNIQUE_ID",
"port": 8080,
"description": "A CrewAI agent that helps plan trips based on preferences",
"api_token": api_key,
"mailbox": True,
"query_params": query_params,
"example_query": (
"Plan a trip from New York to Paris in June, "
"I'm interested in art and history other than museums."
),
"return_dict": True,
}
ai_agent_address = os.getenv("AI_AGENT_ADDRESS")
if ai_agent_address:
tool_input["ai_agent_address"] = ai_agent_address
result = register_tool.run(tool_input=tool_input)
print(f"CrewAI agent registration result: {result}")
print(f"Agent address: {result['agent_address']}")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\nExiting...")
if __name__ == "__main__":
main()
Natural-language queries
Chat text is not passed straight into kickoff. When a user sends a sentence, CrewaiRegisterTool can call an AI formatter uAgent (OpenAI behind the scenes in the logs) to fill query_params: origin, cities, date_range, interests.
- Omit
ai_agent_addressto use the adapter package default formatter. - Override with
ai_agent_addressintool_input, or setAI_AGENT_ADDRESSin.env. - The cloned example currently hardcodes
ai_agent_address=agent1q0h70caed8ax769shpemapzkyk65uscw4xwk6dc4t3emvp5jdcvqs9xs32y. Prefer the env override so you can change it without editing code.
Key differences in uAgents integration
CrewaiRegisterTool: Registers a CrewAI crew as a uAgent. This is the CrewAI-specific tool (not a generic Langchain register helper). There is noUAgentRegisterToolclass.kickoff: Bridges chat/structured inputs intoTripCrew.run().query_params: Declares the fields the formatter and clients should supply.example_query: Helps chat clients understand expected phrasing.return_dict=True:run()then returns a dict withagent_address(notaddress). The default return type is a string; do not look up a missing"address"key.
Specialized agents in the trip planner
Defined in trip_agents.py:
- City Selection Agent: Picks a city from the options
- Local Expert: Local experiences and practical detail
- Travel Concierge: Itinerary and logistics
Tasks in trip_tasks.py: identify, gather, plan.
Benefits of the uAgents integration
- Network communication: Reach the crew over the agent network
- Structured inputs:
query_paramsvalidation - Mailbox: Asynchronous delivery via Agentverse
- Discovery: Agentverse listing
- NL processing: Optional formatter agent (
ai_agent_address/AI_AGENT_ADDRESS) so chat becomes structured fields

Terminal Outputs
uAgents Integration (main_uagents.py)
First terminal:
(venv) abhi@Fetchs-MacBook-Pro test examples % python3 trip_planner/main_uagents.py
INFO: [Trip Planner Crew AI Agent adapters]: Starting agent with address: agent1q2sgs58jzw70e8vvsrlx8k3yukdqc9gwkhp8p7q6tslcxhy0eqtxyq4fv07
INFO: [Trip Planner Crew AI Agent adapters]: Agent 'Trip Planner Crew AI Agent adapters' started with address: agent1q2sgs58jzw70e8vvsrlx8k3yukdqc9gwkhp8p7q6tslcxhy0eqtxyq4fv07
INFO: [Trip Planner Crew AI Agent adapters]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8080&address=agent1q2sgs58jzw70e8vvsrlx8k3yukdqc9gwkhp8p7q6tslcxhy0eqtxyq4fv07
INFO: [Trip Planner Crew AI Agent adapters]: Starting server on http://0.0.0.0:8080 (Press CTRL+C to quit)
INFO: [Trip Planner Crew AI Agent adapters]: Starting mailbox client for https://agentverse.ai
INFO: [Trip Planner Crew AI Agent adapters]: Mailbox access token acquired
Connecting agent 'Trip Planner Crew AI Agent adapters' to Agentverse...
INFO: [mailbox]: Successfully registered as mailbox agent in Agentverse
Successfully connected agent 'Trip Planner Crew AI Agent adapters' to Agentverse
Updating agent 'Trip Planner Crew AI Agent adapters' README on Agentverse...
Successfully updated agent 'Trip Planner Crew AI Agent adapters' README on Agentverse
CrewAI agent registration result: Agent 'Trip Planner Crew AI Agent adapters' registered with address: agent1q2sgs58jzw70e8vvsrlx8k3yukdqc9gwkhp8p7q6tslcxhy0eqtxyq4fv07 with mailbox (Parameters: origin, cities, date_range, interests)
INFO: [mailbox]: Successfully registered as mailbox agent in Agentverse
INFO: [Trip Planner Crew AI Agent adapters]: Got a message from agent1qwwng5d939vyaa6d2trnllyltgrndtfd6z44h8ey8a56hf4dcatsytgzm49
INFO: [Trip Planner Crew AI Agent adapters]: Received message model digest: timestamp=datetime.datetime(2025, 4, 21, 10, 13, 39, 989489, tzinfo=datetime.timezone.utc) msg_id=UUID('7930acf1-b16e-4b20-896b-7d801763eaa6') content=[TextContent(type='text', text='Plan a trip for me from london to paris starting on 22nd of April 2025 and I am interested in a mountains beaches and history')]
INFO: [Trip Planner Crew AI Agent adapters]: Got a text message from agent1qwwng5d939vyaa6d2trnllyltgrndtfd6z44h8ey8a56hf4dcatsytgzm49: Plan a trip for me from london to paris starting on 22nd of April 2025 and I am interested in a mountains beaches and history
INFO: [Trip Planner Crew AI Agent adapters]: Using crew object: <__main__.TripCrew object at 0x12c1f79d0>
INFO: [Trip Planner Crew AI Agent adapters]: Extracting parameters using keys: ['origin', 'cities', 'date_range', 'interests']
INFO:httpx:HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
INFO: [Trip Planner Crew AI Agent adapters]: Extracted parameters: {'origin': 'london', 'cities': 'paris', 'date_range': '22nd of April 2025', 'interests': 'mountains beaches and history'}
INFO: [Trip Planner Crew AI Agent adapters]: Running crew with extracted parameters
╭─────────────────────────────────────────────────────── Crew Execution Started ───────────────────────────────────────────────────────╮
│ │
│ Crew Execution Started │
│ Name: crew │
│ ID: 1462f3ae-5ce4-4ea3-b1af-5639aac04dd2 │
│ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
🚀 Crew: crew
└── 📋 Task: c181e31b-6b7f-4471-ab8f-fa5f06078365
Status: Executing Task...
[... crew execution continues ...]
Standard CrewAI (main.py)
## Welcome to Trip Planner Crew
-------------------------------
From where will you be traveling from?
> New York
What are the cities options you are interested in visiting?
> Paris, Rome, Barcelona
What is the date range you are interested in traveling?
> June 10-20, 2026
What are some of your high level interests and hobbies?
> Food, art, architecture, and history
[City Selection Specialist] I'll analyze which city would be the best fit based on the traveler's preferences...
########################
## Here is your Trip Plan
########################
# PARIS: 3-DAY FOOD & ART JOURNEY
... itinerary continues ...
ASI:One chat
Copy the agent address into ASI:One and use the example query above.

