Which Task and Agent Attributes Can Be Put in the YAML File?

Which Task and Agent attributes can be put in the YAML file instead of crew.py?

I want to put as much as possible into the YAML files to keep crew.py clean and succinct.

Here are the links to the attributes:
Agents Attributes
Tasks Attributes

I have tried adding the LLM and Tools attributes to the YAML problems but could not get them to work. While that may have been because of something I was doing wrong, I want to see which attributes could be added to the YAML files and which could not.

Thank you.

1 Like

All agent and task parameters can be put in YAML files.

You have to use proper YAML formatting, otherwise you will hit errors, and it won’t work.

Where is the documentation for this please

1 Like

I have the same question. I see a lot of documentation for using the attributes in crew.py, but I have not seen anything on how to use them in the YAML files.

For example, I tried to list tools in the Agents YAML file using the formatting shown for the Python code but could not get it to work.

It’s the same documentation you use, just put the parameter name and value in the yaml file Agents - CrewAI

Here is an example with tools, remember you need to use yaml formatting not python formatting

data_miner_alpha:
  role: >
    Financial Transaction Analyzer
  goal: >
    Analyze and categorize financial transactions from bank statements, identifying patterns and anomalies within defined date ranges.
  backstory: >
    You are a highly skilled financial analyst bot designed to sift through complex transaction data. Your strength is in recognizing subtle financial trends and pinpointing irregularities for audit purposes.
  tools:
    - ExtractTransactionDetailsTool
  llm: o3-mini

tasks:

extract_transactions_batch_1:
  description: >
    For account number: {account_number_1}
    Time period: From {start_date} to {end_date}

    Extract all transaction data using ExtractTransactionDetailsTool.

    Return an empty list if no transactions are found.
  expected_output: >
    A complete dataset of transactions including:
    - Raw transaction data with all available fields
    - Metadata about the extraction process
    - Any data quality notes or issues encountered
  agent: data_miner_alpha
  async_execution: True
analyze_transactions:
  description: >
    Analyze all financial transactions using ExtractTransactionDetailsTool.
    Focus on:
    - Transaction dates and times
    - Transaction amounts
    - Transaction categories
    - Merchant/Payee information
  expected_output: >
    A structured analysis of transactions including:
    - Total transaction volume
    - Transaction details and timestamps
    - Transaction categories and amounts
    - Identification of potential anomalies
  agent: transaction_analyzer
  context: [
    extract_transactions_batch_1,
    extract_transactions_batch_2
  ]
2 Likes

Thank you.

Would you happen to have an example of how to call the agents and tasks from the YAML file into the Python file so the script will recognize and use the attributes?

I appreciate the help.

The usual way you usually import yaml file attributes is how you do it, nothing changes

agents_config = "config/agents.yaml"
tasks_config = "config/tasks.yaml"

@agent
def data_miner_alpha(self) -> Agent:
    return Agent(config=self.agents_config["data_miner_alpha"], verbose=True)

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

@crew
def crew(self) -> Crew:
    return Crew(
        agents=self.agents,
        tasks=self.tasks,
        process=Process.sequential,
        verbose=True,
    )

Do you have some code in a repo I can look at so that I can help you debug your issue?

2 Likes

Thanks.

I started a repo using the CrewAI Game Builder Crew Example.

When agents are assigned tools a “KeyError: ‘SerperDevTool’” or whatever the tool names are.

rthidden/game-builder-crew

1 Like

@rthidden Alerted me to this question (thank you), which I also posed today very generally here. Not meaning to hijack this question (no disrespect). I’m eventually hoping for a formalized generalized answer to YAML file attribute/value capabilities. It’s cleaner to be able to factor that out of the code and into YAML files.

Hi @zinyando In your ./agent.yaml example, is the tools: ExtractTransactionDetailsTool the name of a Python class somewhere in your codebase (perhaps one that you wrote).

This is one example (there are a few) where the documentation is lacking.

Thank you.

It’s a tool created by the user and instantiated on the crew file that will use it Tools - CrewAI

1 Like

Okay, then it appears that a list of acceptable values for tools: inside YAML files include already existing: [Out-of-the-box tools | Method-tools decorated with: @tool | Class tools created by subclassing: BaseTool]'.

And specifying anything outside would trigger an exception (which makes sense).

Hopefully documentation expansion will come for all YAML attributes.

Thank you.

I do not think it works like that, but maybe someone can explain it to me. When adding tools in a YAML-compatible way. I get key errors.

senior_engineer_agent:
  role: >
    Senior Software Engineer
  goal: >
    Create software as needed
  backstory: >
    You are a Senior Software Engineer at a leading tech think tank.
    Your expertise in programming in Python and do your best to produce perfect code.
  allow_delegation: False
  verbose: True
  tools:
    - SerperDevTool
  llm: gpt-4o mini

qa_engineer_agent:
  role: >
    Software Quality Control Engineer
  goal: >
    Create Perfect code, by analyzing the code that is given for errors
  backstory: >
    You are a software engineer that specializes in checking code
    for errors. You have an eye for detail and a knack for finding
    hidden bugs.
    You check for missing imports, variable declarations, mismatched
    brackets and syntax errors.
    You also check for security vulnerabilities, and logic errors
  allow_delegation: False
  verbose: True
  tools:
    - SerperDevTool

chief_qa_engineer_agent:
  role: >
    Chief Software Quality Control Engineer
  goal: >
    Ensure that the code does the job that it is supposed to do
  backstory: >
    You feel that programmers always do only half the job, so you are
    super dedicated to make high quality code.
  allow_delegation: True
  verbose: True
  tools:
    - SerperDevTool
"""This file contains the crew definition for the GameBuilder crew"""
from typing import List
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
from crewai_tools import SerperDevTool

@CrewBase
class GameBuilderCrew:
    """GameBuilder crew"""
    agents_config = 'config/agents.yaml'
    tasks_config = 'config/tasks.yaml'

    @agent
    def senior_engineer_agent(self) -> Agent:
        """Creates the Senior Engineer Agent"""
        return Agent(config=self.agents_config['senior_engineer_agent'])

    @agent
    def qa_engineer_agent(self) -> Agent:
        """Creates the QA Engineer Agent"""
        return Agent(config=self.agents_config['qa_engineer_agent'])

    @agent
    def chief_qa_engineer_agent(self) -> Agent:
        """Creates the Chief QA Engineer Agent"""
        return Agent(config=self.agents_config['chief_qa_engineer_agent'])

    @task
    def code_task(self) -> Task:
        """Creates the Code Task"""
        return Task(
            config=self.tasks_config['code_task'],
            agent=self.senior_engineer_agent()
        )   

    @task
    def review_task(self) -> Task:
        """Creates the Review Task"""
        return Task(
            config=self.tasks_config['review_task'],
            agent=self.qa_engineer_agent(),
            #### output_json=ResearchRoleRequirements
        )

    @task
    def evaluate_task(self) -> Task:
        """Creates the Evaluate Task"""
        return Task(
            config=self.tasks_config['evaluate_task'],
            agent=self.chief_qa_engineer_agent()
        )

    @crew
    def crew(self) -> Crew:
        """Creates the GameBuilderCrew"""
        return Crew(
            agents=self.agents,
            tasks=self.tasks,
            process=Process.sequential,
            verbose=True,
        )
PS C:\Users\rthid\CrewAI Examples\game-builder-crew> poetry run game_builder_crew
C:\Users\rthid\AppData\Local\pypoetry\Cache\virtualenvs\game-builder-crew-mS3YMhaY-py3.12\Lib\site-packages\pydantic\_internal\_config.py:295: PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.10/migration/
  warnings.warn(DEPRECATION_MESSAGE, DeprecationWarning)
## Welcome to the Game Crew
-------------------------------
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\rthid\CrewAI Examples\game-builder-crew\src\game_builder_crew\main.py", line 19, in run
    game = GameBuilderCrew().crew().kickoff(inputs=inputs)
           ^^^^^^^^^^^^^^^^^
  File "C:\Users\rthid\AppData\Local\pypoetry\Cache\virtualenvs\game-builder-crew-mS3YMhaY-py3.12\Lib\site-packages\crewai\project\crew_base.py", line 35, in __init__
    self.map_all_agent_variables()
  File "C:\Users\rthid\AppData\Local\pypoetry\Cache\virtualenvs\game-builder-crew-mS3YMhaY-py3.12\Lib\site-packages\crewai\project\crew_base.py", line 143, in map_all_agent_variables
    self._map_agent_variables(
  File "C:\Users\rthid\AppData\Local\pypoetry\Cache\virtualenvs\game-builder-crew-mS3YMhaY-py3.12\Lib\site-packages\crewai\project\crew_base.py", line 171, in _map_agent_variables
    tool_functions[tool]() for tool in tools
    ~~~~~~~~~~~~~~^^^^^^
KeyError: 'SerperDevTool'

Hi everyone,

This solution I’m going to present aims to clarify how to use the tools and llm attributes in the YAML configuration files for agents.

Understanding the problem

When replicating the problem, you’ll basically encounter an error in a dictionary key, specifically in the crewai/project/crew_base.py file. Let’s look at the first lines of the method that raises the exception:

def map_agent_variables(
    self,
    agent_name: str,
    agent_info: Dict[str, Any],
    agents: Dict[str, Callable],
    llms: Dict[str, Callable],
    tool_functions: Dict[str, Callable],
    cache_handler_functions: Dict[str, Callable],
    callbacks: Dict[str, Callable],
) -> None:
    if llm := agent_info.get("llm"):
        try:
            self.agents_config[agent_name]["llm"] = llms[llm]()
        except KeyError:
            self.agents_config[agent_name]["llm"] = llm
    if tools := agent_info.get("tools"):
        self.agents_config[agent_name]["tools"] = [
            tool_functions[tool]() for tool in tools
        ]

Ok, let’s see what it does with the llm attribute from the YAML. It first searches for a key with the name you set to llm (a string). If it finds this key in the llms dict, then it runs the callable associated with that key. If the string you provided is not a key (which happens often since llms = {} by default), then it simply uses that string as the model parameter for a crewai.LLM object later. If you don’t believe me, go read the code yourself. :smiling_face:

And what about the tools parameter from the YAML, which is a list of strings? Well, it tests each string as a key in the tools dict then it runs the callable associated with that key.

Finding the solution

The llms and tools dicts are populated in a scan that’s done in a previous method named map_all_agent_variables, which I’ll omit. This method scans the decorators that are defined in crewai/project/__init__.py.

You’re certainly already used to saying from crewai.project import CrewBase, agent, task, crew, the new thing is that you can (and should) say from crewai.project import tool, llm. That’s the key insight.

Once you do this, the callables decorated with @tool will be automatically listed in the tools dict and so the callables decorated with @llm will be automatically listed in the llms dict. This is elegant.

Semi-functional example

File max_agents.yaml:

max_agent:
  role: >
    Max Role
  goal: >
    Max Goal
  backstory: >
    Max Backstory
  verbose: true
  llm: max_llm
  tools:
    - max_tool

File max_tasks.yaml:

max_task:
  description: >
    Max's question is: {user_question}
  expected_output: >
    Max answer
  agent: max_agent

File crew.py:

from crewai import Agent, Crew, Task, Process, LLM
from crewai.project import CrewBase, agent, task, crew, tool, llm
from crewai.tools import BaseTool
from crewai_tools import DirectoryReadTool
import os

os.environ['LLM_API_KEY'] = 'YOUR_KEY_NOT_MINE'

@CrewBase
class MaxCrew:
    agents_config = 'max_agents.yaml' 
    tasks_config = 'max_tasks.yaml'
    
    @agent
    def max_agent(self) -> Agent:
        return Agent(
            config=self.agents_config['max_agent'],
        )
    
    @task
    def max_task(self) -> Task:
        return Task(
            config=self.tasks_config['max_task'],
        )
    
    @tool
    def max_tool(self) -> BaseTool:
        return DirectoryReadTool(directory='./')
    
    @llm
    def max_llm(self) -> LLM:
        return LLM(
            model='max/maxgpt-999b-chat',
            temperature=0.7,
            timeout=90,
            max_tokens=512,
        )
    
    @crew
    def crew(self) -> Crew:
        return Crew(
            agents=self.agents,
            tasks=self.tasks,
            process=Process.sequential,
            verbose=True,
        )

Suggestions

I suggest that the CrewAI team enriches the documentation on this topic and perhaps even make the crewai create crew command add this import to the crew.py file, as this would encourage the use of this approach.

3 Likes

Hi @rthidden I see what you mean. I think the example provided by @Max_Moura (which came after) might help.

I could be wrong, but you may have to wrap ServerDevTool in a @tool decorated function much like how @Max_Moura wrapped and used DirectoryReadTool() like this:

    @tool
    def max_tool(self) -> BaseTool:
        return DirectoryReadTool(directory='./')

1 Like

Thanks for this. Looking at map_agent_variable,s are the only agent attributes allowed in the YAML listed there? Are the other variables beyond llm and tools allowed in the YAML?

I think that is right. I am going to try it out. I am still curious about the other attributes.

Or did we already confirm all the other attributes work in the YAML or do only ones with decorators work?

1 Like

@rthidden I suspect that only identifiers of decorated function names and BaseTool subclass names work in the YAML file for tools: and llm:. And you supply the meticulous detail (attributes / parameter values) that you require in those (functions and subclass) definitions.

So, one idea might be to have a dedicated Python module with all LLM variations that you need across your projects, and import and use them as needed. Just a thought. :person_shrugging:

1 Like

Do you mind opening a PR to the docs with this info? It might help others!!

2 Likes