Two agents in a row
In a sequential crew, tasks run in list order and each one sees the output of those before it. The clerk finds the order; the writer answers from that.
Lesson 2's desk had two workers: a clerk and a writer who only saw the clerk's finding. A crew with two agents and two tasks does the same.
from crewai import Agent, Crew, Task
from shop_llm import ShopLLM
from tools import lookup_order
clerk = Agent(role="Order clerk", goal="Find the status of customers' orders",
backstory="You can look up any order in the shop's system.",
llm=ShopLLM(model="shop"), tools=[lookup_order])
writer = Agent(role="Reply writer", goal="Write replies to customers",
backstory="You write short, friendly emails.",
llm=ShopLLM(model="shop"))The clerk has the lookup tool. The writer has none: its job is words.
look = Task(description="Find the order in this message: {question}",
expected_output="The order's status.", agent=clerk)
reply = Task(description="Write the customer a reply.",
expected_output="A short, friendly email.", agent=writer)
crew = Crew(agents=[clerk, writer], tasks=[look, reply])The reply task does not mention the question. It gets the clerk's answer instead, because a crew's default process, sequential, runs tasks in list order and passes the earlier outputs to each later task.
result = crew.kickoff(inputs={"question": "Where is my order A17?"})
print(result.raw)The writer's model received the clerk's output under the heading This is the context you're working with:, and lesson 9's model has no rule for that, so it saw A17, no tool, and gave up.
A model that reads the context
if "working with:" in text:
context = text.split("working with:")[1].strip().split("\n\n")[0]
return f"Dear customer, {context}"When a message carries context and no tool fits, the model writes a reply from it. Put these lines in decide after the tool call and before if orders:, and save the file; the lessons from here on use this version.
result = crew.kickoff(inputs={"question": "Where is my order A17?"})
for output in result.tasks_output:
print(f"{output.agent}: {output.raw}")tasks_output shows both steps: the clerk's finding, then the writer's email built from it. result.raw is the last task's output.
Choosing what a task sees
reply.context = [look]
result = crew.kickoff(inputs={"question": "Where is my order B22?"})
print(result.raw)context names the tasks whose outputs a task receives. Here it matches the default, but with three tasks it lets the last one see the first and skip the middle. The tasks page asks for it whenever a task depends on one that did not run immediately before it.
- Swap the order of the tasks in the crew and read what the writer gets.
- Set
reply.context = []and see which branch ofdecideanswers. - Add a third task for the writer that shortens the reply.
This is what real progress feels like.