From b4ddc834b34f26291d8d1b8692bd37c5b5e6ce22 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 16:48:01 +0000 Subject: [PATCH] enhance: improve validator flexibility and role matching robustness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Broaden allowed_agents validator to accept any Sequence type (not just list) - Add .strip() to role string comparisons for whitespace handling - Improve type hints and documentation based on code review feedback Co-Authored-By: João --- src/crewai/agents/agent_builder/base_agent.py | 14 ++++++++------ src/crewai/tools/agent_tools/agent_tools.py | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/crewai/agents/agent_builder/base_agent.py b/src/crewai/agents/agent_builder/base_agent.py index 091690613..73e17a2b7 100644 --- a/src/crewai/agents/agent_builder/base_agent.py +++ b/src/crewai/agents/agent_builder/base_agent.py @@ -2,7 +2,9 @@ import uuid from abc import ABC, abstractmethod from copy import copy as shallow_copy from hashlib import md5 +from __future__ import annotations from typing import Any, Callable, Dict, List, Optional, TypeVar, Union +from collections.abc import Sequence from pydantic import ( UUID4, @@ -107,9 +109,9 @@ class BaseAgent(ABC, BaseModel): default=False, description="Enable agent to delegate and ask questions among each other.", ) - allowed_agents: Optional[List[Union[str, "BaseAgent"]]] = Field( + allowed_agents: Optional[List[Union[str, BaseAgent]]] = Field( default=None, - description="List of agent roles or agent instances that this agent can delegate to. If None, can delegate to all agents when allow_delegation=True.", + description="List of agent roles or agent instances that this agent can delegate to. If None, can delegate to all agents when allow_delegation=True. Empty list prevents all delegation.", ) tools: Optional[List[BaseTool]] = Field( default_factory=list, description="Tools at agents' disposal" @@ -200,19 +202,19 @@ class BaseAgent(ABC, BaseModel): @field_validator("allowed_agents", mode="before") @classmethod - def validate_allowed_agents(cls, allowed_agents: Optional[List[Union[str, "BaseAgent"]]]) -> Optional[List[Union[str, "BaseAgent"]]]: + def validate_allowed_agents(cls, allowed_agents: Optional[Sequence[Union[str, BaseAgent]]]) -> Optional[List[Union[str, BaseAgent]]]: """Validate the allowed_agents list.""" if allowed_agents is None: return None - if not isinstance(allowed_agents, list): - raise ValueError("allowed_agents must be a list of agent roles (strings) or agent instances") + if not isinstance(allowed_agents, Sequence) or isinstance(allowed_agents, str): + raise ValueError("allowed_agents must be a list or tuple of agent roles (strings) or agent instances") for agent in allowed_agents: if not isinstance(agent, (str, BaseAgent)): raise ValueError("Each item in allowed_agents must be either a string (agent role) or a BaseAgent instance") - return allowed_agents + return list(allowed_agents) @model_validator(mode="after") def validate_and_set_attributes(self): diff --git a/src/crewai/tools/agent_tools/agent_tools.py b/src/crewai/tools/agent_tools/agent_tools.py index 82818f45b..bada92829 100644 --- a/src/crewai/tools/agent_tools/agent_tools.py +++ b/src/crewai/tools/agent_tools/agent_tools.py @@ -53,7 +53,7 @@ class AgentTools: for agent in self.agents: for allowed in delegating_agent.allowed_agents: if isinstance(allowed, str): - if agent.role.lower() == allowed.lower(): + if agent.role.strip().lower() == allowed.strip().lower(): filtered_agents.append(agent) break elif isinstance(allowed, BaseAgent):