Skip to content

Add retries to Think step.prompt()#1777

Draft
thomasgauvin wants to merge 11 commits into
mainfrom
thomasgauvin-think-step-prompt-retries
Draft

Add retries to Think step.prompt()#1777
thomasgauvin wants to merge 11 commits into
mainfrom
thomasgauvin-think-step-prompt-retries

Conversation

@thomasgauvin

@thomasgauvin thomasgauvin commented Jun 18, 2026

Copy link
Copy Markdown

When I run step.prompt() as part of an agentic workflow, I want to have an option for the step.prompt() to be retried (in case the agent fails due to capacity constraints, etc).

I have kept this 'dumb', which will retry the whole step.prompt(). I think the Think harness itself should have retries or 'continues' to ensure the task is pushed to completion before stopping.


Open in Devin Review

step.prompt() now accepts an optional retries option with maxAttempts,
baseDelayMs, and maxDelayMs. Retryable errors (e.g. Workers AI 3040
capacity errors) trigger fresh prompt attempts with jittered exponential
backoff, while timeouts, validation errors, aborted, and skipped prompts
are surfaced terminally.

Each attempt uses unique workflow step names and idempotency keys so
retries are durable across workflow hibernation and replays.
@changeset-bot

changeset-bot Bot commented Jun 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a622d14

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

This PR includes changesets to release 1 package
Name Type
@cloudflare/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 found 3 potential issues.

Open in Devin Review

Comment thread packages/think/src/workflows.ts Outdated
Comment thread packages/think/src/workflows.ts Outdated
Comment on lines +297 to +300
expect(sleepCalls[0].duration).toBeGreaterThanOrEqual(0);
expect(sleepCalls[0].duration).toBeLessThanOrEqual(100);
expect(sleepCalls[1].duration).toBeGreaterThanOrEqual(0);
expect(sleepCalls[1].duration).toBeLessThanOrEqual(200);

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.

🚩 Test backoff bounds may be vacuously satisfied due to the jitter bug

The retry test at packages/think/src/tests/workflows.test.ts:297-300 asserts sleepCalls[0].duration <= 100 and sleepCalls[1].duration <= 200. Because of the near-zero jitter fraction bug (BUG-0001), these assertions pass trivially (durations are always ~0). After the jitter bug is fixed, these bounds should still hold mathematically (jitter is in [0, upperBound]), but the test should also verify that durations are not always zero — e.g., asserting that at least one sleep duration is > 0 — to serve as a meaningful regression test for the backoff mechanism.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@pkg-pr-new

pkg-pr-new Bot commented Jun 18, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

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

@cloudflare/ai-chat

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

@cloudflare/codemode

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

create-think

npm i https://pkg.pr.new/create-think@1777

hono-agents

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

@cloudflare/shell

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

@cloudflare/think

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

@cloudflare/voice

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

@cloudflare/worker-bundler

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

commit: a622d14

thomasgauvin and others added 3 commits June 18, 2026 13:44
- Derive retry jitter from two raw SHA-256 digest bytes so the backoff
  fraction spans the full [0, 1) range instead of collapsing to ~0ms
  (base64url char codes / 0xffff was near-zero, defeating jitter).
- Keep the original :submit/:wait step names on the first attempt so
  in-flight workflows replay without re-executing completed steps; only
  retries get suffixed names.
- Persist and read back submitMessages maxRetries through the durable
  submission queue so modelMaxRetries actually reaches the inference loop
  (also fixes the maxRetries typecheck error).
- Strengthen the backoff test to assert jitter is non-zero and add a
  regression test for stable first-attempt step names.
…ep-prompt-retries

# Conflicts:
#	packages/think/src/think.ts
@thomasgauvin thomasgauvin marked this pull request as draft June 18, 2026 19:21
@thomasgauvin

thomasgauvin commented Jun 18, 2026

Copy link
Copy Markdown
Author

Remove from maxModelRetries from Think.submitMessages() because you can do it in beforeTurn()/getModel() (this sets the retry count for the whole agent)

thomasgauvin and others added 6 commits June 18, 2026 15:40
Addresses the chatRecovery race in step.prompt() retries without
disabling chatRecovery (which usefully preserves in-flight turn state
across DO restarts/stalls).

- Before each retry, cancel the abandoned attempt's submission via a
  durable `:cancel-N` step so its turn and any chatRecovery continuation
  cannot keep running and race the fresh attempt on the same session
  (the cause of duplicate/interleaved output). No-op once terminal.
- Add `retries.retryOnTimeout` (default true) to fail fast on wait
  timeouts instead of retrying a likely-to-repeat timeout.
- Log each retry via console.warn with step/attempt/delay/error.
- Tests: assert abandoned attempts are cancelled before retry and the
  successful final attempt is not; assert retryOnTimeout=false fails
  fast without backoff.
The test file's local _promptStep options type omitted retryOnTimeout,
failing the tests tsconfig typecheck in CI (the main package tsconfig
does not compile the test directory, so it passed locally).
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