Lab 01 — CrewAI Sequential Crew Engine

Phase 19 · Lab 01 · Phase README · Warmup

The problem

CrewAI's first-and-most-used process is sequential: you list Agents and Tasks, group them into a Crew, and call crew.kickoff(inputs). The tasks run in the order you listed them, each task's output feeds forward to the next, and runtime inputs get interpolated into the prompts. It looks trivial — which is exactly why interviewers use it to find out whether you actually know the mechanism or have only ever driven the framework from the outside. Three questions separate the two:

  1. In what order do tasks run, and who decides? Listed order. No LLM, no planner. That determinism is the point of sequential (contrast the manager LLM in lab-02).
  2. How does task 2 see task 1's work? Through context — and the rule is a three-way switch: context=None feeds the previous task forward; context=[t1, t3] reads exactly those tasks; context=[] isolates the task.
  3. How do runtime inputs reach the prompt? Through {placeholder} interpolation at kickoff, so one crew definition serves a thousand inputs.

You build the whole engine, with the LLM injected as a pure policy(prompt, context) so the crew is deterministic, offline, and fully testable.

What you build

PieceWhat it doesThe lesson
interpolate(template, inputs)safe {key} substitutionone crew definition, many runs; why not str.format
Agent (role/goal/backstory + policy)renders persona+task into a prompt, calls the injected LLMthe persona is the system prompt
Task (description, expected_output, agent, context)a unit of work + its context rulefeed-forward vs fan-in vs isolated
Crew.kickoff(inputs)the sequential loop; returns a CrewOutputorder, context passing, per-task outputs
CrewOutput / TaskOutputfinal .raw + .tasks_output per taskhow you read a crew's result

File map

FileRole
lab.pyyour implementation (fill the # TODOs)
solution.pyreference + worked example (python solution.py)
test_lab.py22 tests: order, context (3 modes), interpolation, validation, determinism
requirements.txtpytest only

Run it

pytest test_lab.py -v                       # your lab.py (red until you implement)
LAB_MODULE=solution pytest test_lab.py -v   # the reference (green)
python solution.py                          # worked example

Success criteria

  • You can state, without looking, the three context modes and what each produces.
  • You can explain why sequential needs no LLM to decide control flow — and why that makes it cheaper and more debuggable than hierarchical.
  • Your interpolate leaves a stray {brace} untouched (and you can say why str.format would be wrong here).
  • CrewOutput.raw is the last task's output and .tasks_output holds every task in order.
  • All 22 tests pass under both lab and solution.

How this maps to the real stack

  • This is CrewAI's Process.sequential. Real Agent(role=, goal=, backstory=, llm=, tools=), Task(description=, expected_output=, agent=, context=[...]), and Crew(agents=, tasks=, process=Process.sequential).kickoff(inputs=) behave exactly as modeled: tasks run in listed order, outputs feed forward, context overrides the default feed-forward, and {placeholders} are interpolated from inputs.
  • The injected policy is where the LLM lives in real CrewAI (llm= on the agent). Stubbing it is precisely how you unit-test a real crew — you assert control flow and context without paying for tokens or fighting non-determinism.
  • CrewOutput mirrors the real return type: .raw, .tasks_output, and (in real CrewAI) .pydantic / .json_dict for structured outputs and .token_usage for cost.

Limits of the miniature. Real agents also run a tool-use loop inside each task (the agent may call tools several times before producing the task output — that is Phase 02/03 territory), support output_pydantic / output_json structured results, guardrails, and async_execution. We model the orchestration — order, context, interpolation, collection — which is the part the process actually owns.

Extensions (your own machine)

  • Add a tool-use loop inside Agent.execute: let the policy return a tool_call, run a looked-up tool, append the observation, and re-invoke — the ReAct loop from Phase 01, now inside a CrewAI task.
  • Add output_pydantic-style structured output: a task declares a schema, and kickoff validates the raw output against it (reuse the validator from Phase 02).
  • Add async_execution=True for tasks with no context dependency and run them concurrently, then fan them into a downstream task — the first step toward the parallelism Flows give you (lab-03).

Interview / resume signal

"Built a faithful miniature of CrewAI's sequential crew engine — agent/task/crew primitives, three-mode context passing (feed-forward / explicit fan-in / isolated), input interpolation, and per-task output collection — with the LLM injected as a pure policy so the whole crew is deterministic and unit-testable offline."