Skip to content

Commit 0ca6b4f

Browse files
author
Davidson Gomes
committed
refactor(agent): remove CrewAI agent support and update related configurations
1 parent 2a80bdf commit 0ca6b4f

File tree

10 files changed

+43
-389
lines changed

10 files changed

+43
-389
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12-
- Add CrewAI agents
1312
- Add Task Agent for structured single-task execution
1413
- Improve context management in agent execution
1514

README.md

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ The Evo AI platform allows:
1515
- JWT authentication with email verification
1616
- **[Agent 2 Agent (A2A) Protocol Support](https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/)**: Interoperability between AI agents following Google's A2A specification
1717
- **[Workflow Agent with LangGraph](https://www.langchain.com/langgraph)**: Building complex agent workflows with LangGraph and ReactFlow
18-
- **[CrewAI Agent Support](https://www.crewai.com/)**: Organizing agents into specialized crews with assigned tasks
1918
- **Secure API Key Management**: Encrypted storage of API keys with Fernet encryption
2019
- **Agent Organization**: Folder structure for organizing agents by categories
2120

@@ -154,40 +153,7 @@ Executes sub-agents in a custom workflow defined by a graph structure. This agen
154153

155154
The workflow structure is built using ReactFlow in the frontend, allowing visual creation and editing of complex agent workflows with nodes (representing agents or decision points) and edges (representing flow connections).
156155

157-
### 7. CrewAI Agent
158-
159-
Allows organizing agents into a "crew" with specific tasks assigned to each agent. Based on the CrewAI concept, where each agent has a specific responsibility to perform a more complex task collaboratively.
160-
161-
```json
162-
{
163-
"client_id": "{{client_id}}",
164-
"name": "research_crew",
165-
"type": "crew_ai",
166-
"folder_id": "folder_id (optional)",
167-
"config": {
168-
"tasks": [
169-
{
170-
"agent_id": "agent-uuid-1",
171-
"description": "Search for recent information on the topic",
172-
"expected_output": "Search report in JSON format"
173-
},
174-
{
175-
"agent_id": "agent-uuid-2",
176-
"description": "Analyze data and create visualizations",
177-
"expected_output": "Charts and analyses in HTML format"
178-
},
179-
{
180-
"agent_id": "agent-uuid-3",
181-
"description": "Write final report combining results",
182-
"expected_output": "Markdown document with complete analysis"
183-
}
184-
],
185-
"sub_agents": ["agent-uuid-4", "agent-uuid-5"]
186-
}
187-
}
188-
```
189-
190-
### 8. Task Agent
156+
### 7. Task Agent
191157

192158
Executes a specific task using a target agent. Task Agent provides a streamlined approach for structured task execution, where the agent_id specifies which agent will process the task, and the task description can include dynamic content placeholders.
193159

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ dependencies = [
5151
"langgraph==0.4.1",
5252
"opentelemetry-sdk==1.33.0",
5353
"opentelemetry-exporter-otlp==1.33.0",
54-
"crewai==0.119.0",
5554
]
5655

5756
[project.optional-dependencies]

src/api/agent_routes.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
│ For any future changes to the code in this file, it is recommended to │
2525
│ include, together with the modification, the information of the developer │
2626
│ who changed it and the date of modification. │
27-
│ │
28-
│ @update: May 14, 2025 - Added support for crew_ai agent type │
2927
└──────────────────────────────────────────────────────────────────────────────┘
3028
"""
3129

src/schemas/agent_config.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,15 @@ class Config:
238238
from_attributes = True
239239

240240

241-
class CrewAITask(BaseModel):
242-
"""Task configuration for Crew AI agents"""
241+
class AgentTask(BaseModel):
242+
"""Task configuration for agents"""
243243

244244
agent_id: Union[UUID, str] = Field(
245245
..., description="ID of the agent assigned to this task"
246246
)
247+
enabled_tools: Optional[List[str]] = Field(
248+
default_factory=list, description="List of tool names to be used in the task"
249+
)
247250
description: str = Field(..., description="Description of the task to be performed")
248251
expected_output: str = Field(..., description="Expected output from this task")
249252

@@ -260,17 +263,17 @@ class Config:
260263
from_attributes = True
261264

262265

263-
class CrewAIConfig(BaseModel):
264-
"""Configuration for Crew AI agents"""
266+
class AgentConfig(BaseModel):
267+
"""Configuration for agents"""
265268

266-
tasks: List[CrewAITask] = Field(
267-
..., description="List of tasks to be performed by the crew"
269+
tasks: List[AgentTask] = Field(
270+
..., description="List of tasks to be performed by the agent"
268271
)
269272
api_key: Optional[str] = Field(
270-
default_factory=generate_api_key, description="API key for the Crew AI agent"
273+
default_factory=generate_api_key, description="API key for the agent"
271274
)
272275
sub_agents: Optional[List[UUID]] = Field(
273-
default_factory=list, description="List of IDs of sub-agents used in crew"
276+
default_factory=list, description="List of IDs of sub-agents used in agent"
274277
)
275278

276279
class Config:

src/schemas/schemas.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from uuid import UUID
3434
import uuid
3535
import re
36-
from src.schemas.agent_config import LLMConfig, CrewAIConfig
36+
from src.schemas.agent_config import LLMConfig, AgentConfig
3737

3838

3939
class ClientBase(BaseModel):
@@ -98,7 +98,7 @@ class AgentBase(BaseModel):
9898
goal: Optional[str] = Field(None, description="Agent goal or objective")
9999
type: str = Field(
100100
...,
101-
description="Agent type (llm, sequential, parallel, loop, a2a, workflow, crew_ai, task)",
101+
description="Agent type (llm, sequential, parallel, loop, a2a, workflow, task)",
102102
)
103103
model: Optional[str] = Field(
104104
None, description="Agent model (required only for llm type)"
@@ -136,11 +136,10 @@ def validate_type(cls, v):
136136
"loop",
137137
"a2a",
138138
"workflow",
139-
"crew_ai",
140139
"task",
141140
]:
142141
raise ValueError(
143-
"Invalid agent type. Must be: llm, sequential, parallel, loop, a2a, workflow, crew_ai or task"
142+
"Invalid agent type. Must be: llm, sequential, parallel, loop, a2a, workflow or task"
144143
)
145144
return v
146145

@@ -200,7 +199,7 @@ def validate_config(cls, v, values):
200199
raise ValueError(
201200
f'Agent {values["type"]} must have at least one sub-agent'
202201
)
203-
elif values["type"] == "crew_ai" or values["type"] == "task":
202+
elif values["type"] == "task":
204203
if not isinstance(v, dict):
205204
raise ValueError(f'Invalid configuration for agent {values["type"]}')
206205
if "tasks" not in v:
@@ -217,7 +216,6 @@ def validate_config(cls, v, values):
217216
if field not in task:
218217
raise ValueError(f"Task missing required field: {field}")
219218

220-
# Validar sub_agents, se existir
221219
if "sub_agents" in v and v["sub_agents"] is not None:
222220
if not isinstance(v["sub_agents"], list):
223221
raise ValueError("sub_agents must be a list")

src/services/agent_builder.py

Lines changed: 17 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
from src.services.mcp_service import MCPService
4141
from src.services.custom_agents.a2a_agent import A2ACustomAgent
4242
from src.services.custom_agents.workflow_agent import WorkflowAgent
43-
from src.services.custom_agents.crew_ai_agent import CrewAIAgent
4443
from src.services.custom_agents.task_agent import TaskAgent
4544
from src.services.apikey_service import get_decrypted_api_key
4645
from sqlalchemy.orm import Session
@@ -50,7 +49,7 @@
5049
from datetime import datetime
5150
import uuid
5251

53-
from src.schemas.agent_config import CrewAITask
52+
from src.schemas.agent_config import AgentTask
5453

5554
logger = setup_logger(__name__)
5655

@@ -74,7 +73,7 @@ async def _agent_tools_builder(self, agent) -> List[AgentTool]:
7473
return agent_tools
7574

7675
async def _create_llm_agent(
77-
self, agent
76+
self, agent, enabled_tools: List[str] = []
7877
) -> Tuple[LlmAgent, Optional[AsyncExitStack]]:
7978
"""Create an LLM agent from the agent data."""
8079
# Get custom tools from the configuration
@@ -95,6 +94,10 @@ async def _create_llm_agent(
9594
# Combine all tools
9695
all_tools = custom_tools + mcp_tools + agent_tools
9796

97+
if enabled_tools:
98+
all_tools = [tool for tool in all_tools if tool.name in enabled_tools]
99+
logger.info(f"Enabled tools enabled. Total tools: {len(all_tools)}")
100+
98101
now = datetime.now()
99102
current_datetime = now.strftime("%d/%m/%Y %H:%M")
100103
current_day_of_week = now.strftime("%A")
@@ -200,6 +203,8 @@ async def _get_sub_agents(
200203
sub_agent, exit_stack = await self.build_a2a_agent(agent)
201204
elif agent.type == "workflow":
202205
sub_agent, exit_stack = await self.build_workflow_agent(agent)
206+
elif agent.type == "task":
207+
sub_agent, exit_stack = await self.build_task_agent(agent)
203208
elif agent.type == "sequential":
204209
sub_agent, exit_stack = await self.build_composite_agent(agent)
205210
elif agent.type == "parallel":
@@ -218,7 +223,7 @@ async def _get_sub_agents(
218223
return sub_agents
219224

220225
async def build_llm_agent(
221-
self, root_agent
226+
self, root_agent, enabled_tools: List[str] = []
222227
) -> Tuple[LlmAgent, Optional[AsyncExitStack]]:
223228
"""Build an LLM agent with its sub-agents."""
224229
logger.info("Creating LLM agent")
@@ -230,7 +235,9 @@ async def build_llm_agent(
230235
)
231236
sub_agents = [agent for agent, _ in sub_agents_with_stacks]
232237

233-
root_llm_agent, exit_stack = await self._create_llm_agent(root_agent)
238+
root_llm_agent, exit_stack = await self._create_llm_agent(
239+
root_agent, enabled_tools
240+
)
234241
if sub_agents:
235242
root_llm_agent.sub_agents = sub_agents
236243

@@ -341,10 +348,11 @@ async def build_task_agent(
341348
# Convert tasks to the expected format by TaskAgent
342349
tasks = []
343350
for task_config in config.get("tasks", []):
344-
task = CrewAITask(
351+
task = AgentTask(
345352
agent_id=task_config.get("agent_id"),
346353
description=task_config.get("description", ""),
347354
expected_output=task_config.get("expected_output", ""),
355+
enabled_tools=task_config.get("enabled_tools", []),
348356
)
349357
tasks.append(task)
350358

@@ -362,57 +370,7 @@ async def build_task_agent(
362370

363371
except Exception as e:
364372
logger.error(f"Error building Task agent: {str(e)}")
365-
raise ValueError(f"Error building CrewAI agent: {str(e)}")
366-
367-
async def build_crew_ai_agent(
368-
self, root_agent: Agent
369-
) -> Tuple[CrewAIAgent, Optional[AsyncExitStack]]:
370-
"""Build a CrewAI agent with its sub-agents."""
371-
logger.info(f"Creating CrewAI agent: {root_agent.name}")
372-
373-
agent_config = root_agent.config or {}
374-
375-
# Verify if we have tasks configured
376-
if not agent_config.get("tasks"):
377-
raise ValueError("tasks are required for CrewAI agents")
378-
379-
try:
380-
# Get sub-agents if there are any
381-
sub_agents = []
382-
if root_agent.config.get("sub_agents"):
383-
sub_agents_with_stacks = await self._get_sub_agents(
384-
root_agent.config.get("sub_agents")
385-
)
386-
sub_agents = [agent for agent, _ in sub_agents_with_stacks]
387-
388-
# Additional configurations
389-
config = root_agent.config or {}
390-
391-
# Convert tasks to the expected format by CrewAIAgent
392-
tasks = []
393-
for task_config in config.get("tasks", []):
394-
task = CrewAITask(
395-
agent_id=task_config.get("agent_id"),
396-
description=task_config.get("description", ""),
397-
expected_output=task_config.get("expected_output", ""),
398-
)
399-
tasks.append(task)
400-
401-
# Create the CrewAI agent
402-
crew_ai_agent = CrewAIAgent(
403-
name=root_agent.name,
404-
tasks=tasks,
405-
db=self.db,
406-
sub_agents=sub_agents,
407-
)
408-
409-
logger.info(f"CrewAI agent created successfully: {root_agent.name}")
410-
411-
return crew_ai_agent, None
412-
413-
except Exception as e:
414-
logger.error(f"Error building CrewAI agent: {str(e)}")
415-
raise ValueError(f"Error building CrewAI agent: {str(e)}")
373+
raise ValueError(f"Error building Task agent: {str(e)}")
416374

417375
async def build_composite_agent(
418376
self, root_agent
@@ -477,26 +435,23 @@ async def build_composite_agent(
477435
else:
478436
raise ValueError(f"Invalid agent type: {root_agent.type}")
479437

480-
async def build_agent(self, root_agent) -> Tuple[
438+
async def build_agent(self, root_agent, enabled_tools: List[str] = []) -> Tuple[
481439
LlmAgent
482440
| SequentialAgent
483441
| ParallelAgent
484442
| LoopAgent
485443
| A2ACustomAgent
486444
| WorkflowAgent
487-
| CrewAIAgent
488445
| TaskAgent,
489446
Optional[AsyncExitStack],
490447
]:
491448
"""Build the appropriate agent based on the type of the root agent."""
492449
if root_agent.type == "llm":
493-
return await self.build_llm_agent(root_agent)
450+
return await self.build_llm_agent(root_agent, enabled_tools)
494451
elif root_agent.type == "a2a":
495452
return await self.build_a2a_agent(root_agent)
496453
elif root_agent.type == "workflow":
497454
return await self.build_workflow_agent(root_agent)
498-
elif root_agent.type == "crew_ai":
499-
return await self.build_crew_ai_agent(root_agent)
500455
elif root_agent.type == "task":
501456
return await self.build_task_agent(root_agent)
502457
else:

src/services/agent_service.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ async def create_agent(db: Session, agent: AgentCreate) -> Agent:
202202
if "api_key" not in agent.config or not agent.config["api_key"]:
203203
agent.config["api_key"] = generate_api_key()
204204

205-
elif agent.type == "crew_ai" or agent.type == "task":
205+
elif agent.type == "task":
206206
if not isinstance(agent.config, dict):
207207
agent.config = {}
208208
raise HTTPException(
@@ -682,8 +682,8 @@ async def update_agent(
682682
if "config" not in agent_data:
683683
agent_data["config"] = agent_config
684684

685-
if ("type" in agent_data and agent_data["type"] in ["crew_ai", "task"]) or (
686-
agent.type in ["crew_ai", "task"] and "config" in agent_data
685+
if ("type" in agent_data and agent_data["type"] in ["task"]) or (
686+
agent.type in ["task"] and "config" in agent_data
687687
):
688688
config = agent_data.get("config", {})
689689
if "tasks" not in config:

0 commit comments

Comments
 (0)