Skip to content

fix: strip reasoningContent blocks in filter_restored_tool_context - #627

Open
gingeekrishna wants to merge 3 commits into
aws:mainfrom
gingeekrishna:fix/621-filter-restored-tool-context-thinking
Open

gingeekrishna wants to merge 3 commits into
aws:mainfrom
gingeekrishna:fix/621-filter-restored-tool-context-thinking

Conversation

@gingeekrishna

Copy link
Copy Markdown

Summary

  • _filter_restored_tool_context() stripped toolUse/toolResult blocks from restored session history but left reasoningContent (extended thinking) blocks intact.
  • Bedrock rejects an assistant message where reasoningContent blocks are present without their companion toolUse blocks, raising a ValidationException.
  • Fix: add "reasoningContent" not in content to the filter predicate so thinking blocks are stripped together with the tool calls they preceded.

Root cause

When extended thinking is enabled, an assistant turn produces a message like:

{
  "role": "assistant",
  "content": [
    {"reasoningContent": {"reasoningText": {"text": "…"}}},
    {"toolUse": {"toolUseId": "t1", "name": "my_tool", "input": {}}}
  ]
}

reasoningContent and toolUse are semantically coupled — the Bedrock API requires them to appear together. filter_restored_tool_context was removing toolUse while keeping reasoningContent, producing a partial message that the API refuses.

Test plan

  • test_strips_reasoning_content_alongside_tool_use — assistant message with reasoningContent+toolUse → both stripped, only plain-text assistant message survives
  • test_message_with_only_reasoning_and_tool_use_is_dropped_entirely — message becomes empty after stripping → excluded from output
  • test_text_alongside_reasoning_and_tool_use_is_preserved — text content survives after stripping reasoning+toolUse
  • test_messages_without_tool_context_are_unchanged — plain text messages pass through unchanged (no regression)
  • test_existing_tool_use_filtering_still_works — original toolUse/toolResult behaviour preserved
5 passed in 0.XXs

Fixes #621

When extended thinking is enabled, assistant messages contain
reasoningContent blocks alongside toolUse blocks. The filter was
stripping toolUse/toolResult but leaving reasoningContent intact,
producing a partial assistant message that Bedrock rejects with:

  ValidationException: `thinking` or `redacted_thinking` blocks in
  the latest assistant message cannot be modified.

reasoningContent blocks are semantically coupled to the tool calls
that follow them — stripping the tool context without the accompanying
reasoning leaves an incoherent and API-rejected message. The fix adds
reasoningContent to the set of block types removed by the filter.

Fixes aws#621

Signed-off-by: gingeekrishna <gingeekrishna@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes restored-session filtering for Bedrock extended thinking by ensuring reasoningContent blocks are removed alongside toolUse/toolResult blocks, preventing invalid assistant messages from being sent to Bedrock.

Changes:

  • Update _filter_restored_tool_context() to also strip reasoningContent blocks when filtering restored history.
  • Expand the session manager integration test suite with regression cases covering reasoning+tool interactions and preservation of plain text.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/bedrock_agentcore/memory/integrations/strands/test_agentcore_memory_session_manager.py Adds regression tests validating restored-history filtering when reasoningContent is present.
src/bedrock_agentcore/memory/integrations/strands/session_manager.py Extends restored tool-context filtering to remove reasoningContent blocks and documents the rationale.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +802 to +806
"""Strip historical toolUse/toolResult context from restored messages.

Extended-thinking (reasoningContent) blocks are coupled to the tool
calls that follow them. Bedrock rejects an assistant message whose
reasoningContent blocks have been separated from their companion
…_context

Clarify that the flag strips reasoningContent (extended thinking) blocks
in addition to toolUse/toolResult, and explain why the two are always
removed together.

Signed-off-by: gingeekrishna <gingeekrishna@gmail.com>
@gingeekrishna

Copy link
Copy Markdown
Author

Done - addressed Copilot review: updated the filter_restored_tool_context docstring in AgentCoreMemoryConfig (commit d4f9b5d) to clarify that it strips toolUse, toolResult, and reasoningContent (extended thinking) blocks, with a note explaining that reasoning blocks must always be removed alongside the tool calls that followed them.

@art-aws

art-aws commented Oct 13, 2026

Copy link
Copy Markdown

Independent confirmation from a different model generation, plus one case the tests do not pin down.

Reproduction, Claude Haiku 5.5 (adaptive thinking on by default), bedrock-agentcore 1.13.0. Same ValidationException as #621 on the second turn of any restored session with filter_restored_tool_context=True. We carry a workaround in production that wraps _filter_restored_tool_context and additionally drops reasoningContent, with the same predicate this PR adds; it has been running in SMART, the Social Messaging Agent Runtime Toolkit (awslabs/social-messaging-agent-runtime-toolkit, public release this month), since 2026-10-09 with no regressions on Haiku 4.5 histories, where it is a no-op.

The root cause is broader than tool coupling. The PR's docstring and all five tests frame reasoningContent as paired with a following toolUse. The API constraint is actually that a thinking block is bound to the exact context it was produced in, and is rejected on replay if anything before it changed. Stripping tool blocks is one such change, but so is a system prompt that differs between turns (ours includes the current time), and that invalidates reasoning blocks in text-only assistant turns with no toolUse at all. The predicate in this PR handles that case correctly because it strips every reasoningContent; the tests do not exercise it, so a future reviewer could narrow the strip to "only when paired with toolUse" and reintroduce the failure.

Suggested addition: one test where an assistant message is [reasoningContent, text] with no tool blocks, asserting the result is [text]. And a one-line docstring change from "coupled to the tool calls" to "bound to the context they were produced in; any edit to earlier history, including this filter's own tool stripping, invalidates them."

Happy to open that as a follow-up commit on this branch if useful. This fix is the right shape and we would like to drop our wrapper once it ships.

@gingeekrishna

Copy link
Copy Markdown
Author

@art-aws thanks for the independent confirmation and the sharper framing -- you're right that the real invariant is "bound to the context it was produced in," not "coupled to the following tool call." Done in eff72ee:

  • Reworded the docstring to say reasoningContent is invalidated by any earlier change to history (including this filter's own tool stripping), not just a missing companion toolUse.
  • Added test_strips_reasoning_content_with_no_tool_blocks: an assistant message [reasoningContent, text] with no tool blocks at all, asserting the result is [text].

The implementation was already correct for your text-only case (it strips reasoningContent unconditionally), so this closes the gap you flagged where a future reviewer could otherwise "fix" it into only stripping when paired with a tool and silently reintroduce the failure. All 188 tests in the file pass.

Glad to hear this lets you drop the SMART wrapper once it ships.

reasoningContent is invalidated by any change earlier in the context, not
just tool stripping, so the filter must drop it unconditionally rather
than only when paired with toolUse. Adds the missing text-only case and
clarifies the docstring accordingly.
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Oct 15, 2026
@gingeekrishna
gingeekrishna force-pushed the fix/621-filter-restored-tool-context-thinking branch from eff72ee to 4c44c6e Compare October 15, 2026 22:31
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Oct 15, 2026

This branch is waiting to be deployed

1 waiting deployment
manual-approval — 4c44c6e7 Waiting Oct 15, 2026 by gingeekrishna via Test (payments) #1634
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] filter_restored_tool_context is incompatible with extended thinking

3 participants