Skip to content

fix(ai-isolate-cloudflare): accumulate toolResults across rounds#524

Open
Sriketk wants to merge 1 commit intoTanStack:mainfrom
Sriketk:fix/ai-isolate-cloudflare-accumulate-tool-results
Open

fix(ai-isolate-cloudflare): accumulate toolResults across rounds#524
Sriketk wants to merge 1 commit intoTanStack:mainfrom
Sriketk:fix/ai-isolate-cloudflare-accumulate-tool-results

Conversation

@Sriketk
Copy link
Copy Markdown

@Sriketk Sriketk commented May 3, 2026

Summary

The Cloudflare isolate driver wipes toolResults between need_tools rounds (packages/typescript/ai-isolate-cloudflare/src/isolate-driver.ts:178). wrap-code uses sequential tc_<idx> ids that are re-derived from scratch every time the Worker re-executes user code, so prior-round results must stay in the cache. With the wipe, multi-tool programs like:

const x = await A();
const y = await B();
return x + y;

ping-pong between {tc_0} and {tc_1}:

round sent toolResults worker reaction
1 (none) throws on tc_0
2 {tc_0} tc_0 cached → throws on tc_1
3 {tc_1} (pre-fix) tc_0 missing → throws on tc_0 again
4 {tc_0} tc_1 missing → throws on tc_1 again
... ... until MaxRoundsExceeded

Single-tool code worked because only one cache entry was ever needed in a given round.

Fix

One-line change: toolResults = {}toolResults = { ...(toolResults ?? {}) }. Within an execute() call's round loop only — toolResults is local to execute(), so each new execute() still starts fresh (independent code, independent ids).

Why this slipped through

Existing isolate-driver.test.ts cases:

  • All need_tools cases are single-round (need_tools → done).
  • IDs in tests use ad-hoc shapes like add_1, getA_1 — never wrap-code's real tc_<idx> format. The end-to-end contract between driver and wrap-code was never validated.
  • The MaxRoundsExceeded test loops the same tool, so doesn't exercise the multi-tool ping-pong.

Test plan

Adds accumulates toolResults across rounds for sequential tool calls to tests/isolate-driver.test.ts. Uses tc_<idx>-shaped ids matching wrap-code and asserts round 3 carries both tc_0 and tc_1.

  • New test fails on prior implementation (expected {success:true, value:'a'}, received undefined for tc_0 in round 3)
  • All 16 driver tests pass with the fix (pnpm vitest run tests/isolate-driver.test.ts)
  • Live repro against deployed Worker (cobalt-sandbox.sriketk5.workers.dev) confirms multi-tool code converges in 3 rounds post-fix

Related

Discovered while running multi-tool code through @tanstack/ai-isolate-cloudflare@0.1.8 from a Cobalt MCP integration. Independent of #523 (which ports the worker from unsafe_eval to worker_loader); this fix touches isolate-driver.ts only and applies to both the legacy and ported binding paths.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed tool result handling in the Cloudflare isolate driver to properly maintain state across multiple sequential tool execution rounds, preventing premature termination of multi-tool programs.
  • Tests

    • Added regression test covering sequential tool execution scenarios to ensure results are correctly preserved across multiple rounds.

The Cloudflare isolate driver wiped toolResults between need_tools rounds.
wrap-code uses sequential tc_<idx> ids that are re-derived from scratch
every time the Worker re-executes user code, so prior-round results must
remain in the cache. With the wipe, multi-tool programs (e.g.
`await A(); await B();`) ping-pong between {tc_0} and {tc_1} and exhaust
maxToolRounds, surfacing as MaxRoundsExceeded.

Single-tool code worked because only one cache entry was ever needed in a
given round. Existing tests covered single-round flows only and used
ad-hoc tool-call ids rather than wrap-code's real tc_<idx> shape, so the
regression slipped through.

Adds a tc_<idx>-shaped regression test covering two sequential tool
calls. The test fails on the prior implementation and passes after the
one-line fix.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5ed11eda-f303-4edb-be46-dae6943088eb

📥 Commits

Reviewing files that changed from the base of the PR and between ff33855 and ed7240f.

📒 Files selected for processing (3)
  • .changeset/accumulate-tool-results.md
  • packages/typescript/ai-isolate-cloudflare/src/isolate-driver.ts
  • packages/typescript/ai-isolate-cloudflare/tests/isolate-driver.test.ts

📝 Walkthrough

Walkthrough

The Cloudflare isolate driver is fixed to accumulate toolResults across multiple tool-execution rounds instead of resetting to empty each round, preventing tool-ID reuse from causing round exhaustion. A regression test validates multi-tool sequential behavior.

Changes

Tool Results Accumulation Fix

Layer / File(s) Summary
Core Logic Fix
packages/typescript/ai-isolate-cloudflare/src/isolate-driver.ts
In CloudflareIsolateContext.execute, toolResults is now carried forward across rounds by cloning prior results instead of resetting to {} each iteration. Inline comments explain why sequential tc_<idx> tool IDs require result retention.
Regression Test
packages/typescript/ai-isolate-cloudflare/tests/isolate-driver.test.ts
New test case accumulates toolResults across rounds for sequential tool calls verifies that toolResults from tc_0 and tc_1 are both present in the final request POST body after three worker rounds.
Changelog
.changeset/accumulate-tool-results.md
Patch release entry documents the toolResults accumulation fix and notes the new end-to-end regression test covering previously missing multi-tool behavior.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A rabbit hops through tool rounds with glee,
No more results lost, hooray!
Sequential tools now dance, tc_0 and tc_1 stay,
Cloudflare's isolate, both safe and spry! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description comprehensively documents the problem, solution, test approach, and verification steps; however, it does not explicitly follow the repository's template structure with the required checklist sections. Consider using the provided template with explicit 'Changes', 'Checklist', and 'Release Impact' sections for consistency, though substantive information is well-documented.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main fix: accumulating toolResults across rounds in the Cloudflare isolate driver.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant