Skip to content

[FEATURE]: call the session.retry hook when the built-in retries run out #54862

Open

Description

@JoaoBerne

Feature hasn't been suggested before.

Describe the enhancement you want to request

On 2.0.27 the session retry count is still fixed: packages/core/src/session/runner/retry.ts uses Schedule.recurs(10).

2.0 added the session.retry plugin hook, which covers most of #43596. A plugin can stop a retry, change its delay, even keep retrying past the timeout cap. The one thing it can't do is go past the 10th retry. When the schedule runs out, policy returns { retry: false } before the hook is called, so the plugin never gets asked.

Could the hook still run in that case, with decision: { retry: false } as the default? A plugin could then keep going with its own delay, and nothing changes for anyone who doesn't have one.

Use case: a provider that stays down or out of quota for longer than 10 attempts cover, where you'd rather keep polling than fail the step.

A maxRetries config key would do it too, for people who'd rather not write a plugin to change a number, but the hook change is the smaller ask.

I had a V1 PR for this (#44517, closed in the V2 switch). Happy to send the V2 change if you want it.

Activity

  1. opencode-agent commented on Oct 12, 2026

    @opencode-agent
    Contributor

    Thanks for re-filing this for 2.0, @JoaoBerne. You're asking for the session.retry hook to run when the built-in schedule runs out, with decision: { retry: false } as the default, so a plugin can keep retrying past the 10th retry.

    I checked packages/core/src/session/runner/retry.ts and it works as you describe. When Schedule.recurs(10) is done, policy returns { retry: false } before the hook is called. A plugin can't work around that, so this needs the core change you propose. Maintainers will consider it.

    Related:

  2. akrisfx commented on Oct 16, 2026

    @akrisfx

    very usefull

  3. deanm0000 commented on Nov 4, 2026

    @deanm0000

    A maxRetries config key would do it too, for people who'd rather not write a plugin to change a number, but the hook change is the smaller ask.

    This would be my preference. For reference my use case is using the flex tier on openai and just letting it poll indefinitely. In that same vein I'd like if we could override the backoff timer and just always wait a fixed amount of time. Would that customization mean I have to make a plugin?

  4. JoaoBerne commented on Nov 5, 2026

    @JoaoBerne
    Author

    @deanm0000 For the fixed delay, yes, currently that requires a plugin, but just a small one. The retry hook can replace the delay, and core uses the value you set. Place this in .opencode/plugins/:

    export default {
      id: "fixed-retry-delay",
      async setup(ctx) {
        ctx.session.hook("retry", (event) => {
          if (event.decision.retry) event.decision.delay = 30_000
        })
      },
    }

    I tested this on 2.2.5 with a server that always returns a 500 error: with the delay set to 1s, retries came exactly 1 second apart, then stopped after the 10th attempt. That stop is the part no plugin can change yet, and it's the whole point of this issue.

    A quick update on the pointers above: since #56497, the limit lives in packages/core/src/model-retry.ts (Schedule.recurs(10), line 27). retry.ts still returns { retry: false } (line 38) before calling the hook (line 47), so the diagnosis is unchanged.

    As for the config key, either option works for me. I suggested changing the hook because it's a smaller diff, but the decision is up to the maintainers.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions