mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-16 04:18:35 +00:00
Fix task configuration with None context parameter in YAML
Fixes #3696 When context: None is specified in YAML, yaml.safe_load() converts it to the string 'None' instead of Python's None object. The code was attempting to iterate over this string character by character, causing KeyError: 'N' when trying to look up task names. Changes: - Added isinstance(context_list, list) check in crew_base.py before iterating context_list to handle YAML's conversion of None to string - Added test case test_task_with_none_context_from_yaml to verify tasks can be configured with context: None without errors - Added test YAML configurations in tests/config_none_context/ to reproduce and verify the fix The fix ensures that only actual list values are processed, allowing None and other non-list values to pass through without causing errors. Co-Authored-By: João <joao@crewai.com>
This commit is contained in:
@@ -260,9 +260,10 @@ def CrewBase(cls: T) -> T: # noqa: N802
|
||||
output_pydantic_functions: dict[str, Callable],
|
||||
) -> None:
|
||||
if context_list := task_info.get("context"):
|
||||
self.tasks_config[task_name]["context"] = [
|
||||
tasks[context_task_name]() for context_task_name in context_list
|
||||
]
|
||||
if isinstance(context_list, list):
|
||||
self.tasks_config[task_name]["context"] = [
|
||||
tasks[context_task_name]() for context_task_name in context_list
|
||||
]
|
||||
|
||||
if tools := task_info.get("tools"):
|
||||
self.tasks_config[task_name]["tools"] = [
|
||||
|
||||
5
tests/config_none_context/agents.yaml
Normal file
5
tests/config_none_context/agents.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
test_agent:
|
||||
role: Test Agent
|
||||
goal: Test goal
|
||||
backstory: Test backstory
|
||||
verbose: true
|
||||
11
tests/config_none_context/tasks.yaml
Normal file
11
tests/config_none_context/tasks.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
task_with_none_context:
|
||||
description: A test task with None context
|
||||
expected_output: Some output
|
||||
agent: test_agent
|
||||
context: None
|
||||
|
||||
task_with_valid_context:
|
||||
description: A test task with valid context
|
||||
expected_output: Some output
|
||||
agent: test_agent
|
||||
context: [task_with_none_context]
|
||||
@@ -287,3 +287,38 @@ def test_internal_crew_with_mcp():
|
||||
adapter_mock.assert_called_once_with(
|
||||
{"host": "localhost", "port": 8000}, connect_timeout=120
|
||||
)
|
||||
|
||||
|
||||
def test_task_with_none_context_from_yaml():
|
||||
@CrewBase
|
||||
class CrewWithNoneContext:
|
||||
agents_config = "config_none_context/agents.yaml"
|
||||
tasks_config = "config_none_context/tasks.yaml"
|
||||
|
||||
agents: list[BaseAgent]
|
||||
tasks: list[Task]
|
||||
|
||||
@agent
|
||||
def test_agent(self):
|
||||
return Agent(config=self.agents_config["test_agent"])
|
||||
|
||||
@task
|
||||
def task_with_none_context(self):
|
||||
return Task(config=self.tasks_config["task_with_none_context"])
|
||||
|
||||
@task
|
||||
def task_with_valid_context(self):
|
||||
return Task(config=self.tasks_config["task_with_valid_context"])
|
||||
|
||||
@crew
|
||||
def crew(self):
|
||||
return Crew(agents=self.agents, tasks=self.tasks, verbose=True)
|
||||
|
||||
crew_instance = CrewWithNoneContext()
|
||||
|
||||
task_none = crew_instance.task_with_none_context()
|
||||
assert task_none is not None
|
||||
|
||||
task_valid = crew_instance.task_with_valid_context()
|
||||
assert task_valid.context is not None
|
||||
assert len(task_valid.context) == 1
|
||||
|
||||
Reference in New Issue
Block a user