Skip to content

Python: [Bug]: CompactionProvider.before_run drops synthetic summary messages created by compaction strategies #7943

Closed

Description

Description

What happened?

When CompactionProvider.before_run is configured with a before_strategy that replaces excluded messages with new synthetic ones (ToolResultCompactionStrategy, SummarizationStrategy), the newly created summary Message is silently discarded instead of being kept in the session context.

before_run identifies which messages survived compaction using id() against the projected message list, then filters each provider's existing context.context_messages[sid] bucket down to that surviving set:

projected = project_included_messages(all_messages)
projected_set = {id(m) for m in projected}
for sid in list(context.context_messages):
    context.context_messages[sid] = [m for m in context.context_messages[sid] if id(m) in projected_set]

Both ToolResultCompactionStrategy and SummarizationStrategy build their replacement summary via messages.insert(...), so the new Message object was never a member of any context.context_messages[sid] list to begin with. Because the reconciliation step only filters existing lists rather than rebuilding them from the projected list, there is no bucket for the new summary message to land in, and it's dropped. The original messages it was meant to summarize are still correctly excluded, so the net result is that content disappears entirely rather than being compacted into a summary.

after_strategy is unaffected, since it mutates the stored history list in place rather than reconciling a filtered projection against per-source buckets — which makes this easy to miss, since the two strategy hooks behave differently for the exact same strategy classes.

What did you expect to happen?

I expected the summary/tool-result message produced by the compaction strategy to be preserved in context.context_messages (and therefore included in the next model call), replacing the original messages it summarizes — matching the documented behavior of these strategies and their behavior when used as after_strategy.

Steps to reproduce the issue

  1. Build a SessionContext with a message history containing a tool-call group (assistant function_call + tool function_result) followed by a normal assistant text message, added via context.extend_messages("history", messages).
  2. Create a CompactionProvider(before_strategy=ToolResultCompactionStrategy(keep_last_tool_call_groups=0)).
  3. Call await provider.before_run(agent=None, session=None, context=context, state={}).
  4. Inspect context.get_messages() (or context.context_messages["history"]).

Observed: the tool-call/result pair is excluded as expected, but the "[Tool results: get_weather: sunny, 18°C]" summary message that should replace it is missing — 4 messages in, 2 messages out, with the tool information lost entirely rather than condensed.

Expected: 3 messages — the original user message, the new summary message, and the final assistant text — reflecting a genuine compaction rather than data loss.

Code Sample

from agent_framework import (
    CompactionProvider,
    Message,
    SessionContext,
    ToolResultCompactionStrategy,
)

messages = [
    Message(role="user", contents=["What's the weather?"]),
    # assistant function call
    # tool result
    # assistant final response
]

context = SessionContext(input_messages=[])
context.extend_messages("history", messages)

provider = CompactionProvider(
    before_strategy=ToolResultCompactionStrategy(
        keep_last_tool_call_groups=0
    )
)

await provider.before_run(
    agent=None,
    session=None,
    context=context,
    state={},
)

print(context.get_messages())

Error Messages / Stack Traces

There is no exception or stack trace.

This is a silent data-loss/correctness issue. The compaction strategy successfully creates the replacement summary message, but `CompactionProvider.before_run` does not preserve it when reconciling the projected messages back into `context.context_messages`.

Package Versions

agent-framework: 1.16.0 and
agent-framework: 1.1.5.0

Python Version

Python 3.13.15

Additional Context

The issue appears to be specific to compaction strategies used as before_strategy.

after_strategy does not appear to have the same problem because it operates on the stored history differently rather than reconstructing the provider buckets from the projected flattened message list.

I checked existing GitHub issues and recent compaction-related changes for reports involving:

  • CompactionProvider
  • before_strategy
  • summarization
  • tool-result compaction
  • loss of summarized/tool-result messages

I did not find an existing issue describing this specific before_run reconciliation problem.

There are existing compaction-related fixes, including changes around keeping function-call and function-result occurrences atomic during compaction, but those address a different part of the compaction pipeline.

The likely root cause is that before_run assumes all messages in the projected result already belong to an existing context.context_messages bucket, while replacement-based strategies can introduce new Message objects.

A fix would need to preserve and re-bucket these newly-created messages when reconciling the projected message list back into context.context_messages. The existing summary metadata identifying the messages being summarized may provide a more reliable way to determine the appropriate source than relying only on message position.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Aug 29, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Aug 29, 2026
  3. github-actions commented on Aug 29, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    The defect reproduces in python/packages/core/agent_framework/_compaction.py::CompactionProvider.before_run at lines 1587-1590 when a before strategy inserts a new included Message into the flattened list; ToolResultCompactionStrategy and SummarizationStrategy both use this pattern. Minimal repro: populate a SessionContext with user, function-call, tool-result, and final-assistant messages, run before_run with ToolResultCompactionStrategy(keep_last_tool_call_groups=0), and assert that the generated tool summary remains in context.get_messages().

    • Failing test: python/packages/core/tests/core/test_compaction.py::test_compaction_provider_before_run_preserves_tool_result_summary
    • Files examined: python/packages/core/agent_framework/_compaction.py, python/packages/core/agent_framework/_sessions.py, python/packages/core/tests/core/test_compaction.py, python/packages/core/pyproject.toml
    • Tests run: test_compaction_provider_before_run_preserves_tool_result_summary (failed), test_tool_result_compaction_zero_collapses_all (passed)
    • Reported version: 1.15.0
    • Current version: 1.16.0
  4. added
    agentsUsage: [Issues, PRs], Target: Single agent
    compactionUsage: [Issues, PRs], Target: compaction
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Aug 29, 2026
  5. Namraa310806 commented on Aug 29, 2026

    @Namraa310806
    ContributorAuthor

    Working on this and I will submit the Fix with the approach mentioned in the report in short time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

agentsUsage: [Issues, PRs], Target: Single agentcompactionUsage: [Issues, PRs], Target: compactionpythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions