Skip to content

fix(think): preserve orphaned execution outcomes - #2059

Merged
ben-reitz merged 7 commits into
mainfrom
fix/think-orphaned-execution-outcome-role
Aug 18, 2026
Merged

fix(think): preserve orphaned execution outcomes#2059
ben-reitz merged 7 commits into
mainfrom
fix/think-orphaned-execution-outcome-role

Conversation

@ben-reitz

@ben-reitz ben-reitz commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #2010.

What is the bug

Think can pause an execution while it waits for human approval. If compaction removes that execution's tool call before the approval arrives, the action still resolves, but the next model call fails because instead of saving the approval as part of the original tool call, it saves the approval as a system message in the middle of the conversation as a fallback outcome.

AI SDK v7 rejects it locally, while strict Anthropic-compatible routes return a 400 as they don't allow system messages to be inserted into the conversation mid-conversation. That message stays in history, so later turns keep failing too.

Why it happens

Normally Think replaces the paused tool result in place and continues the conversation. When the original tool part is gone, Think appends a text fallback so an already-applied approval or rejection is not silently lost.

That fallback is framework-authored, but providers cannot safely receive it as an arbitrarily placed system message.

The fix

We're keeping the same framework-authored system notes in durable session history as the fallback here, so clients and recovery logic do not mistake them for human messages.

The change is that when assembling provider messages, Think will now project recognised execution-outcome notes to ordinary user context. The same projection handles notes already stored by older Think releases without rewriting session history.

The durable-role/provider-role split is a narrow compatibility fix until Think has first-class framework events with independent storage, UI, recovery, and model projections.

Options I tried

before landing on this one:

  1. store it as a user message instead of a system one - this didn't work because it then appears like a user message in the UI which means users, harness logic, and potentially models mistaking it as a user message
  2. appending it to the compaction note - decided this doesn't really work for this because it needs to exist as a durable system note rather than just part of a larger compaction summary

Related issue

I think solving #1676 would give us that more holistic event model, but it will be a much larger change and needs more thought and planning. This fix solves the immediate problem.

@changeset-bot

changeset-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f2b5d3a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@cloudflare/think Patch
@cloudflare/agent-think Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

@pkg-pr-new

pkg-pr-new Bot commented Aug 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@2059

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@2059

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@2059

hono-agents

npm i https://pkg.pr.new/hono-agents@2059

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@2059

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@2059

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@2059

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@2059

commit: f2b5d3a

@ben-reitz
ben-reitz marked this pull request as draft August 6, 2026 14:49
@ben-reitz
ben-reitz marked this pull request as ready for review August 10, 2026 09:41
@ben-reitz ben-reitz added wip still a work in progress ready-for-review-and-merge PR is ready for review and/or merge and removed wip still a work in progress labels Aug 10, 2026
@ben-reitz
ben-reitz merged commit d5973c0 into main Aug 18, 2026
7 checks passed
@ben-reitz
ben-reitz deleted the fix/think-orphaned-execution-outcome-role branch August 18, 2026 13:07
@github-actions github-actions Bot mentioned this pull request Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review-and-merge PR is ready for review and/or merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Think: orphaned execution-outcome fallback appends role:system at illegal positions — wedges sessions on Bedrock/Azure (Anthropic placement rules)

1 participant