CrewAI's quadratic context problem: why a 5-agent crew costs 6× more than you expect
Cost-audit series, episode 3. This series began with an AI agent that burned 136M tokens overnight →.
CrewAI is one of the most-starred agent orchestration frameworks on GitHub. Its pitch is intuitive: define a crew of role-playing agents, assign tasks, watch them collaborate. What the README doesn't tell you is that the default context-passing model has a quadratic token cost curve. A 5-agent crew doesn't cost 5× a solo agent — on input tokens it costs closer to 6×, and once you stack memory, delegation, and verbose mode it climbs to 8–15×. The multiplier grows with every agent or task you add.
This audit shows you exactly where the tokens go, with line numbers.
The architecture in one paragraph
CrewAI executes tasks sequentially (by default). Each task has an optional context list — a list of other tasks whose outputs should be available to the executing agent. When you don't specify context explicitly, CrewAI's default behavior is to make all previously completed tasks available to each subsequent agent. The output of Task 1 goes into Task 2's prompt. Task 1 + Task 2 outputs go into Task 3's prompt. And so on.
This is linear accumulation — and it produces a quadratic total token count.
The code that does it
src/crewai/crew.py — the Crew._get_context method (line 792 at tag 0.80.0):
def _get_context(self, task: Task, task_outputs: List[TaskOutput]):
context = (
aggregate_raw_outputs_from_tasks(task.context)
if task.context
else aggregate_raw_outputs_from_task_outputs(task_outputs)
)
return context
Source: src/crewai/crew.py#L792
The decisive branch is the else: when a task sets no explicit context, CrewAI falls back to aggregate_raw_outputs_from_task_outputs(task_outputs) — the outputs of all prior tasks. That aggregation helper (in crewai/utilities) serializes each prior task's full raw output into the string that gets injected into the current task's prompt. There is no summarization, no truncation, no deduplication. The string grows with every task.
src/crewai/crew.py — the task execution loop lives in Crew._execute_tasks (defined at line 635 at tag 0.80.0; the context-injection call is at line 696). Simplified to the two lines that matter:
# inside _execute_tasks, iterating over the crew's tasks:
context = self._get_context(task, task_outputs) # task_outputs = every prior task's output
task_output = task.execute_sync(
agent=agent_to_use, context=context, tools=agent_to_use.tools
)
Source: src/crewai/crew.py (method _execute_tasks)
task_outputs is the running list of every prior task's output, so it grows as the crew progresses. Each call to execute_sync constructs a full prompt that includes that accumulated context string, and it is sent with every LLM API request — not cached between tasks (CrewAI doesn't use prompt caching by default).
The math
Assume:
- N = 5 tasks (a typical research + writing crew)
- T_task = 500 tokens per task output (modest: a paragraph or a JSON object)
- T_system = 800 tokens per agent's system prompt + task description (role, goal, backstory, task instructions)
Token count for Task k = T_system + (k-1) × T_task (accumulated context from all prior tasks)
| Task | Context tokens | System + task | Total input tokens |
|---|---|---|---|
| 1 | 0 | 800 | 800 |
| 2 | 500 | 800 | 1,300 |
| 3 | 1,000 | 800 | 1,800 |
| 4 | 1,500 | 800 | 2,300 |
| 5 | 2,000 | 800 | 2,800 |
| Total | 5,000 | 4,000 | 9,000 |
A naive model would predict 5 × 800 = 4,000 input tokens. The actual bill is 9,000 — 2.25× for just five tasks with modest outputs. Now scale up:
- T_task = 2,000 tokens (a realistic research output, a code block, a structured list):
| Task | Context tokens | System + task | Total input tokens |
|---|---|---|---|
| 1 | 0 | 800 | 800 |
| 2 | 2,000 | 800 | 2,800 |
| 3 | 4,000 | 800 | 4,800 |
| 4 | 6,000 | 800 | 6,800 |
| 5 | 8,000 | 800 | 8,800 |
| Total | 20,000 | 4,000 | 24,000 |
Now you're at 6× the naive estimate — and that's input tokens only. Add output tokens from each task (another ~2,000 × 5 = 10,000) and the total API cost for one crew run is 34,000 tokens instead of the ~14,000 you'd expect.
With claude-sonnet-4-6 ($3/M input, $15/M output):
- Naive estimate: (4,000 × $3 + 10,000 × $15) / 1,000,000 = $0.162
- Actual: (24,000 × $3 + 10,000 × $15) / 1,000,000 = $0.222 — 37% over
Now run 50 crew executions per day:
- Naive: $0.162 × 50 × 30 = $243/month
- Actual: $0.222 × 50 × 30 = $333/month
For a SaaS product with hundreds of daily crew runs, this gap becomes tens of thousands of dollars per month — and it gets worse as you add agents or as task outputs grow.
Three multipliers on top of the base cost
1. Memory layers (each one adds tokens)
CrewAI's memory=True flag (off by default, but heavily promoted) activates four memory systems:
# src/crewai/memory/short_term/short_term_memory.py
class ShortTermMemory(Memory):
def search(self, query: str, score_threshold: float = 0.35):
return self.storage.search(query=query, score_threshold=score_threshold)
Source: src/crewai/memory/short_term/short_term_memory.py
Short-term memory retrieves every stored item scoring above a similarity threshold (default 0.35) and appends them to the prompt — the count is unbounded, so a longer run history injects more retrieved context per task. Long-term memory hits an SQLite database. Entity memory maintains structured entity descriptions. Semantic memory uses ChromaDB embeddings — each retrieval costs an embedding API call plus the tokens from the retrieved chunks injected into the prompt.
With memory=True on a 10-run crew history, expect +1,500–3,000 tokens per task in retrieval overhead.
2. verbose=True (the default in most tutorials)
Most CrewAI tutorials set verbose=True or verbose=2. This surfaces the agent's intermediate reasoning — but the real cost driver isn't the logging, it's the ReAct loop underneath it. CrewAI runs its own CrewAgentExecutor (not LangChain's), and each agent step accumulates the full "Thought / Action / Observation" trace back into the LLM prompt for the next iteration. Each tool call adds another round of Thought + Action + Observation tokens before the final answer. For an agent that calls 3 tools, this can add 800–2,000 tokens per task.
3. Human delegation (allow_delegation=True)
When an agent can delegate to another, it can route subtasks to specialist agents mid-task. This is CrewAI's "hierarchical" feature. The cost: each delegation creates a new complete LLM call with the delegating agent's accumulated context inherited into the delegatee's prompt. A single task can spawn 2–3 delegation chains, each carrying the full context blob from above.
What a real run looks like
Let's measure a concrete 3-agent research crew using @wartzar-bee/tokenscope:
npx @wartzar-bee/tokenscope crew-session.jsonl
For a crew with:
- Researcher agent: finds + summarizes 3 sources (outputs ~1,800 tokens)
- Analyst agent: interprets the research (outputs ~1,200 tokens)
- Writer agent: produces a structured report (outputs ~2,000 tokens)
The per-agent context accumulation (illustrative — tokenscope reports the session total you can check this against, not a per-agent split):
Per-agent context accumulation:
researcher → input: 1,100 output: 1,800 (system + task only)
analyst → input: 2,900 output: 1,200 (+1,800 context from researcher)
writer → input: 4,100 output: 2,000 (+1,800 + 1,200 context from prior two)
Total input: 8,100
Total output: 5,000
Session total: 13,100 tokens
Naive estimate (no context accumulation): 8,300 tokens
Actual multiplier: 1.58×
This is a modest crew. Bump to 5 agents with research-heavy outputs and the multiplier reaches 4–6×. Add memory and delegation: 8–15×.
The fix: explicit context scoping
CrewAI lets you control which tasks feed context to which. Use the context parameter explicitly:
from crewai import Task
research_task = Task(
description="Find the top 3 cloud cost optimization techniques.",
agent=researcher,
# no context — this is the first task
)
analysis_task = Task(
description="Analyze the techniques and rank by ROI.",
agent=analyst,
context=[research_task], # only research output, not all prior tasks
)
writing_task = Task(
description="Write a 500-word summary of the #1 technique.",
agent=writer,
context=[analysis_task], # only the analysis — researcher output not needed here
)
Result: the writer agent sees only the analyst's output (~1,200 tokens), not the researcher's raw output + the analyst's output (3,000 tokens). Context tokens halved on the most expensive task.
For longer pipelines, consider a summary task: a cheap, short-output task that condenses prior results, and only its output flows forward. The cost of the summarization step is far less than sending raw outputs through N subsequent agents.
Measuring your own crew
If you're running CrewAI in production, the default LLM logging doesn't surface how much of each call is re-sent accumulated context. Point tokenscope at a session transcript to see it:
npm install -g @wartzar-bee/tokenscope
Export your run as a session JSONL (a Claude Code session under ~/.claude/projects, or any transcript in that format), then:
npx @wartzar-bee/tokenscope crew-session.jsonl
# machine-readable:
npx @wartzar-bee/tokenscope crew-session.jsonl --json
You'll see the session total, how much is new work versus re-sent accumulated context, and where the growth is steepest — the accumulation this whole post is about.
Summary
CrewAI's default context model accumulates all prior task outputs into every subsequent agent's prompt. This produces a quadratic total token count as N grows — not linear. The practical impact at modest scale (5 agents, 2,000-token outputs): 4–6× the token count you'd expect. Add memory layers, delegation, and verbose mode: 8–15×.
The fix is explicit context scoping: pass only the task outputs that each agent actually needs. It's a one-line change per task, and it can halve your API bill immediately.
Next in the series: we'll look at LangGraph's token footprint — the stateful graph model has a different cost shape, and it's worth understanding before you migrate from LangChain to LangGraph chasing efficiency gains.
wartzar-bee builds tools for operating cost-efficient autonomous agents. tokenscope is free and open-source. Follow on dev.to →
Top comments (0)