crewai - ✅(Solved) Fix [FEATURE] [FEATURE] Add opt in context_strategy="summarized" to reduce inter task context pollution [1 pull requests, 2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
crewAIInc/crewAI#4661Fetched 2026-04-08 00:40:49
View on GitHub
Comments
2
Participants
2
Timeline
11
Reactions
0
Author
Timeline (top)
commented ×2cross-referenced ×2labeled ×2referenced ×2

Root Cause

  1. Token-budget truncation — Simply truncating raw outputs to a fixed character limit. Simpler but loses important information that may appear at the end of an output.
  2. Inline summary generation — Telling the task's own LLM to produce a summary alongside its output. Unreliable because LLMs don't always follow formatting instructions, and it breaks structured outputs (output_json, output_pydantic).
  3. Pass both summary and full output — Let the downstream LLM choose. Doesn't solve the problem because tokens are still consumed in the context window regardless.

Fix Action

Fixed

PR fix notes

PR #4662: fix: reset executor messages and iterations between task executions

Description (problem / solution / changelog)

fix: reset executor messages and iterations between task executions

Summary

When CrewAgentExecutor is reused across sequential tasks (the common path via Agent._update_executor_parameters()), invoke() and ainvoke() were calling _setup_messages() which appends to self.messages without clearing first. This caused:

  • Message accumulation: system/user messages doubled with each task (1→2→3…)
  • Iteration counter not resetting: could trigger premature max-iteration exits
  • Context pollution: Task N's LLM call included the full message history from Tasks 1…N-1

The fix adds two lines at the top of both invoke() and ainvoke():

self.messages = []
self.iterations = 0

This matches the behavior of the experimental AgentExecutor which already correctly resets state per invocation.

Fixes #4319, #4389, #4661

Review & Testing Checklist for Human

  • Verify no code path intentionally relies on messages persisting across invoke() calls. The _update_executor_parameters() method in agent/core.py updates tools/prompt/etc but never touched messages — confirm this was always a bug, not a feature.
  • Run the full test suite (uv run pytest lib/crewai/tests/ -vv) to check for regressions — the new tests pass in isolation but should be validated against the full suite in CI.
  • Manual smoke test: Create a Crew with one agent assigned to 2+ sequential tasks, call crew.kickoff(), and verify the agent doesn't receive stale context from prior tasks.

Notes

  • The experimental AgentExecutor (flow-based) already resets state correctly; this PR brings CrewAgentExecutor (the default executor) in line with that behavior.
  • Requested by: João
  • Link to Devin Session
<!-- CURSOR_SUMMARY -->

[!NOTE] Low Risk Low risk: small, localized lifecycle change to clear messages and iterations at the start of invoke/ainvoke, plus isolated unit tests validating reuse behavior.

Overview Prevents state leakage when reusing the same CrewAgentExecutor across sequential tasks by resetting self.messages and self.iterations at the start of both invoke() and ainvoke(), avoiding context pollution and premature max-iteration exits.

Adds regression tests covering sync/async reuse to ensure message history doesn’t accumulate across calls and the iteration counter restarts per execution.

<sup>Written by Cursor Bugbot for commit 23bc9aa9fa71867aca490aeb7af21865105b776c. This will update automatically on new commits. Configure here.</sup>

<!-- /CURSOR_SUMMARY -->

Changed files

  • lib/crewai/src/crewai/agents/crew_agent_executor.py (modified, +14/-0)
  • lib/crewai/tests/agents/test_crew_agent_executor_state_reset.py (added, +252/-0)
RAW_BUFFERClick to expand / collapse

Opt-in Context Summarization for Inter-Task Context

Problem (traced through codebase)

In Crew._execute_tasks(), each task receives context via _get_context()aggregate_raw_outputs_from_task_outputs() in formatter.py:26. This concatenates ALL prior task raw outputs verbatim. In a 5-task crew, Task 5's prompt contains ~8,000+ tokens of unfiltered prior output, causing ContextLengthExceeded errors or degraded LLM quality.

Proposed Solution

Add an opt-in context_strategy field:

  • Crew(context_strategy="summarized") — crew-level, default is "full" (existing behavior unchanged)
  • Task(context_strategy="full") — per-task override for tasks needing full output

When "summarized":

  • After each task completes, a small LLM call (~100 tokens) using the task's existing agent.llm compresses the output into a 2-3 sentence summary
  • Summary stored in a new TaskOutput.context_summary field
  • _get_context() uses summaries instead of raw outputs
  • Falls back to truncation if LLM call fails (never crashes)
  • Works with both sequential and async task execution

Files Changed (~100 lines total)

FileChange
tasks/task_output.pyAdd context_summary field
utilities/formatter.pyAdd aggregate_summarized_outputs_* functions (existing untouched)
crew.pyAdd context_strategy field, summary generation, update _get_context()
task.pyAdd per-task context_strategy override
tests/test_context_strategy.pyNew test file

What This Does NOT Change

  • Default behavior is "full" — zero breaking changes
  • Existing aggregate_raw_outputs_* functions untouched
  • No new dependencies
  1. Token-budget truncation — Simply truncating raw outputs to a fixed character limit. Simpler but loses important information that may appear at the end of an output.
  2. Inline summary generation — Telling the task's own LLM to produce a summary alongside its output. Unreliable because LLMs don't always follow formatting instructions, and it breaks structured outputs (output_json, output_pydantic).
  3. Pass both summary and full output — Let the downstream LLM choose. Doesn't solve the problem because tokens are still consumed in the context window regardless.

Willingness to Contribute Yes, I'd be happy to submit a pull request

extent analysis

Fix Plan

To implement the opt-in context summarization, follow these steps:

  • Add a context_strategy field to the Crew class with a default value of "full".
  • Add a context_strategy field to the Task class with a default value of "full".
  • Create a new TaskOutput field called context_summary to store the summarized output.
  • Implement a function to generate a summary of the task output using a small LLM call.
  • Update the _get_context() function to use the summarized output instead of the raw output.

Example Code

# crew.py
class Crew:
    def __init__(self, context_strategy="full"):
        self.context_strategy = context_strategy

# task.py
class Task:
    def __init__(self, context_strategy="full"):
        self.context_strategy = context_strategy

# task_output.py
class TaskOutput:
    def __init__(self, context_summary=None):
        self.context_summary = context_summary

# utilities/formatter.py
def aggregate_summarized_outputs(task_outputs):
    summaries = []
    for output in task_outputs:
        if output.context_summary:
            summaries.append(output.context_summary)
    return "\n".join(summaries)

# crew.py
def _get_context(self, task_outputs):
    if self.context_strategy == "summarized":
        return aggregate_summarized_outputs(task_outputs)
    else:
        # existing behavior
        return aggregate_raw_outputs_from_task_outputs(task_outputs)

# Generate summary using LLM
def generate_summary(task_output):
    # Use a small LLM call to generate a summary
    summary = llm.generate_summary(task_output)
    return summary

# Update TaskOutput with summary
def update_task_output(task_output):
    summary = generate_summary(task_output)
    task_output.context_summary = summary
    return task_output

Verification

To verify that the fix worked, test the following scenarios:

  • Create a Crew with context_strategy="summarized" and verify that the _get_context() function returns the summarized output.
  • Create a Task with context_strategy="full" and verify that the _get_context() function returns the raw output.
  • Test the generate_summary() function to ensure it produces a valid summary.
  • Test the update_task_output() function to ensure it updates the TaskOutput with the correct summary.

Extra Tips

  • Make sure to handle errors and edge cases when generating summaries using the LLM.
  • Consider adding a fallback mechanism to truncate the output if the LLM call fails.
  • Test the implementation thoroughly to ensure it works correctly with both sequential and async task execution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING