Most existing CrewAI code and many flow templates use this layout, so you will meet it constantly.
Before the JSON-first layout, every CrewAI project looked like this, and crewai create crew NAME --classic still produces it:
config/agents.yamlandconfig/tasks.yaml: agent and task text, keyed by name.crew.py: a class that builds the crew in Python.main.py: functions such asrun(),train()andtest()thatcrewai runand friends call.
crew.py uses decorators: the @name lines placed above a class or function, which register or wrap it.
@CrewBaseon the class loads the two YAML files intoself.agents_configandself.tasks_config.@agenton a method that returns anAgent;@taskon one that returns aTask. They collect the results intoself.agentsandself.tasksautomatically.@crewon the method that returns the finalCrew.
The method names must match the YAML keys (researcher in YAML, def researcher in Python). Tasks keep the order in which their methods appear in the class.
Why choose classic? You can attach Python objects directly: custom tool instances, Pydantic output classes, callbacks and guardrail functions. In YAML the agent: field of a task refers to an agent by name, and {placeholders} work as before. Flow projects (crewai create flow) also generate crews in this classic style.
YAML uses > to write long text across several lines; the line breaks become spaces.
Example
# config/agents.yaml -> researcher:
# role: >
# {topic} Senior Data Researcher
# goal: > ... backstory: > ...
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
@CrewBase
class ResearchCrew:
@agent
def researcher(self) -> Agent: # name matches the YAML key
return Agent(config=self.agents_config["researcher"], verbose=True)
@task
def research_task(self) -> Task:
return Task(config=self.tasks_config["research_task"])
@crew
def crew(self) -> Crew:
return Crew(agents=self.agents, tasks=self.tasks, process=Process.sequential)
# main.py: ResearchCrew().crew().kickoff(inputs={"topic": "AI LLMs"})Remember
--classiccreates crew.py plus config/agents.yaml and config/tasks.yaml@CrewBase,@agent,@task,@crewcollect objects into a Crew- Method names must match YAML keys
Watch out for
- Renaming a YAML key but not the matching @agent/@task method, which raises a KeyError on load.