Skip to content

Run independent tool-call reads concurrently - #1867

Merged
RhysSullivan merged 8 commits into
mainfrom
toolcall-parallel-reads
Aug 30, 2026
Merged

Run independent tool-call reads concurrently#1867
RhysSullivan merged 8 commits into
mainfrom
toolcall-parallel-reads

Conversation

@RhysSullivan

Copy link
Copy Markdown
Collaborator

Every MCP tools/call paid for its storage reads serially on the dynamic invoke path in packages/core/sdk/src/executor.ts. Two sites now overlap their independent reads:

  • Pre-approval: the tool row lookup, the active policy rule set, and the connection row lookup run concurrently. The policy and connection results are captured as Exits and unwrapped exactly where the sequential code read them, so the error a caller sees for a given input is unchanged (tool-row read failure still dominates; a connection read failure still surfaces only where that read used to run).
  • Post-approval: credential resolution and the integration row lookup run concurrently. Both start only after enforceApproval completes, so a declined call still never starts credential resolution and never triggers a token refresh. The integration read is unwrapped after the credential values, keeping a credential resolution failure dominant over a storage failure.

Nothing moves relative to approval enforcement, the validateToolArgs pre-check, OAuth refresh coalescing, or the shape-memory path.

Tests: two overlap probes (instrumented FumaDb wrapper plus a counting credential provider) that fail when the reads are sequential, a regression test that a declined approval resolves no credentials, and a ConnectionNotFoundError test for a tool row that outlives its connection. Full packages/core/sdk suite, repo typecheck, lint, and format are green.

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Cloudflare preview

Torn down — the PR is closed.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 30, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
executor-marketing b3a0ddb Commit Preview URL

Branch Preview URL
Aug 30 2026, 04:54 AM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 30, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
executor-cloud b3a0ddb Aug 30 2026, 04:56 AM

@pkg-pr-new

pkg-pr-new Bot commented Aug 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@1867

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@1867

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@1867

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@1867

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@1867

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@1867

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@1867

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@1867

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@1867

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@1867

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@1867

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@1867

executor

npm i https://pkg.pr.new/executor@1867

commit: b3a0ddb

@RhysSullivan
RhysSullivan marked this pull request as ready for review August 30, 2026 05:04
@RhysSullivan
RhysSullivan merged commit 98d6c6a into main Aug 30, 2026
77 of 80 checks passed
@RhysSullivan RhysSullivan mentioned this pull request Aug 30, 2026
midego1 added a commit to midego1/executor that referenced this pull request Aug 31, 2026
Upstream's execute-read-concurrency tests (UsefulSoftwareCo#1867) run execute under
adversarial scheduler budgets, and with the audit wrapper in place two of
them hung the run loop. The A/B pointed at Effect.timeout around the
tool-call-log insert.

Investigating why exposed the real defect: the write runs in an onExit
finalizer, which is uninterruptible, so the timeout's interrupt could never
land. The 2s cap this feature shipped with was decorative in exactly the
sick-database case it was written for — it protected nothing, and its timer
machinery deadlocked under adversarial budgets. Making the write
interruptible inside the finalizer did not help; the timer itself is the
problem there.

So the write is now awaited, deliberately unbounded, and honest about it:
bounding a stalled driver is the driver's job; what the wrapper owes the
caller is that a row exists before the call returns and that a failed write
never changes the call. TOOL_CALL_LOG_WRITE_TIMEOUT is gone from the public
surface.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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