Attribute Error: 'str' object has no attribute 'get'

error line: crewAI/src/crewai/utilities/config.py at 00eede0d5d7b9ea591d939689e8e05f89f9d975d · crewAIInc/crewAI · GitHub

what seems to be happening based on debugging:

given this code:

    @task
    def first_task(self) -> Task:
        return Task(
            config=self.tasks_config["first_task"],
        )

    @task
    def second_task(self) -> Task:
        return Task(
            config=self.tasks_config["second_task"],
            context=[self.first_task],
        )

the first task runs fine, but the second task fails. this appears to be because

  1. when a Task is defined, part of the underlying flow is to process the task config, which somehow calls this pydantic code: pydantic/pydantic/main.py at bff747748e57c0db384dbd0df886fa623fa3a703 · pydantic/pydantic · GitHub
  2. which calls process_model_config (which just calls process_config): https ://github.com/crewAIInc/crewAI/blob/main/src/crewai/task.py#L197
  3. which gets the config attribute of whatever is passed in: https ://github.com/crewAIInc/crewAI/blob/main/src/crewai/utilities/config.py#L19
    – crew only lets me put two links in here

so for a task with defined config this works fine, and even for a task with no config it works fine because values get returned i there is no config field found.

however, for some reason i cannot identify, whenever the context field exists on a Task, that same 3 step process is subsequently called on the first value of the context array, which is a function

# the Task object
{'description': 'completes task 2.', 'expected_output': 'beep', 'output_json': <class 'task.class'>, 'context': [<bound method task2 of <crewai.project.crew_base.CrewBase(crew) object at 0x105dc3cd0>>]}

# the first value of the context array
<bound method crew.task2 of <crewai.project.crew_base.CrewBase(crew) object at 0x105dc3cd0>>

this results in the error 'function' object has no attribute 'get', because the code is trying to get the context field from a function. bad!

but why?? is the context supposed to be the task rather than a function?? i think it must be that… but then how do we properly express the context as the full task rather than a function?

Edit: Answer

yes, that was it. by changing the context line above to call the function rather than pass it, the failure stops:

            context=[self.first_task()],

@matt @Dabnis may want to update the docs to show that the context needs to pass the called function, rather than the function object itself

2 Likes