Unit 02.04: Splitting one vague task into two checkable ones
"Handle the request and reply to the customer" is two tasks wearing one name, and neither half can be checked while they are joined.
Split on the output, and declare the dependency
The split point is wherever the output changes shape. A decision is structured data; a reply is prose. One contract cannot describe both.
The code splits a vague task into a decision and a reply, with the dependency declared through context.
from crewai import Agent, Task
agent = Agent(role="Support analyst", goal="Resolve refund questions",
backstory="You work from records.", allow_delegation=False)
vague = Task(description="Handle the refund request and reply to the customer",
expected_output="A resolved request", agent=agent)
decide = Task(
description="Decide eligibility for ACC-1187's June refund request.",
expected_output=('JSON with keys decision (eligible|not_eligible|unknown), '
'days_elapsed (int), policy_line (str).'),
agent=agent,
)
reply = Task(
description="Write the customer reply for the decision produced above.",
expected_output=("3-5 sentences stating the decision, the reason, the "
"policy line, and one next step."),
agent=agent,
context=[decide],
)
for label, task in [("vague", vague), ("decide", decide), ("reply", reply)]:
# Task.context defaults to a NOT_SPECIFIED sentinel, not None or [] --
# so `task.context or []` raises. Check the type instead.
upstream = task.context if isinstance(task.context, list) else []
print(f"{label:7} depends on: {[t.description[:24] for t in upstream]}")
print(f" {task.expected_output[:76]}\n")
# `context=[decide]` makes the dependency explicit. Splitting also means a
# reviewer can approve the decision without approving the wording, which is the
# gate Module 5 builds.
context=[decide] makes the dependency explicit rather than implicit in the ordering. Note the detail in the code comment: Task.context defaults to a NOT_SPECIFIED sentinel, not None or [] - so the natural task.context or [] raises a TypeError rather than giving you an empty list.
The split also creates a place for the human gate. A reviewer can approve the eligibility decision without approving the wording, which is exactly the separation Module 5 depends on.
The mistake this prevents
The mistake is splitting into tasks that pass prose between them. If the first task's output is a paragraph the second has to interpret, you have two tasks and one contract - and the interpretation step is where the meaning drifts. Pass structured data across the boundary.
Takeaway
Split where the output changes shape, pass structured data between the halves, and declare the dependency with context. The split is also where a human gate can go.
