Skip to content

feat(gateway): re-mint once and resume on a 401 from an aged bearer - #1224

Open
brandonleung wants to merge 3 commits into
brandon/wizard-w1-2-mint-refusal-codefrom
brandon/wizard-w1-3-remint-on-401
Open

feat(gateway): re-mint once and resume on a 401 from an aged bearer#1224
brandonleung wants to merge 3 commits into
brandon/wizard-w1-2-mint-refusal-codefrom
brandon/wizard-w1-3-remint-on-401

Conversation

@brandonleung

@brandonleung brandonleung commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Problem

The anthropic subprocess captures its bearer at spawn and pi bakes it into the provider, so a token must outlive the whole session. That is why the server TTL is a day, and a shorter one cannot ship without this.

Changes

A 401 from an aged bearer re-mints and resumes instead of ending the run.

  • On a 401 where the bearer is past 0.8 of its TTL, the gateway session resets, mints again, and restarts query() with a resume. Once per run: a second 401 fails, so a revoked token cannot drive an unbounded mint loop.
  • The pi harness re-registers its provider with the new bearer, and the triage provider re-reads auth rather than closing over the token.
  • The 401 is recognised from pi's own diagnostic error code, falling back to the message text only when a turn failed before pi attached a diagnostic. Deciding a re-mint by pattern-matching error prose breaks silently whenever pi or the SDK rewords its message.

Test plan

pnpm test. The 0.8 boundary runs under fake timers so the revert mutant dies on every run rather than by wall-clock luck; a second 401, a young bearer, and concurrent 401s each have a case.

Known gap: a run longer than about two TTLs still dies at its second 401, so the charts TTL stays at its current value until that bound is either raised or accepted.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci ai-observability
  • /wizard-ci basic-integration
  • /wizard-ci mcp-analytics
  • /wizard-ci replay-vision
  • /wizard-ci revenue
  • /wizard-ci self-driving
  • /wizard-ci warehouse
  • /wizard-ci warehouse-seeded

Test an individual app:

  • /wizard-ci ai-observability/anthropic
  • /wizard-ci ai-observability/google-adk
  • /wizard-ci ai-observability/groq
Show more apps
  • /wizard-ci ai-observability/manual-capture
  • /wizard-ci ai-observability/openai
  • /wizard-ci ai-observability/openai-agents
  • /wizard-ci ai-observability/opentelemetry
  • /wizard-ci ai-observability/vercel-ai
  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/flutter
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/typescript-sdk
  • /wizard-ci replay-vision/javascript-node
  • /wizard-ci replay-vision/next-js
  • /wizard-ci replay-vision/react-vite
  • /wizard-ci revenue/stripe
  • /wizard-ci self-driving/astro
  • /wizard-ci self-driving/fastapi
  • /wizard-ci self-driving/nuxt
  • /wizard-ci self-driving/react-router
  • /wizard-ci self-driving/sveltekit
  • /wizard-ci warehouse/monorepo-env
  • /wizard-ci warehouse/multi-source-next
  • /wizard-ci warehouse/stripe-node
  • /wizard-ci warehouse/zero-source
  • /wizard-ci warehouse-seeded/next-stripe
  • /wizard-ci warehouse-seeded/next-stripe-declined

Test against a Context Mill branch:

  • /wizard-ci all context-mill:my-branch

Add context-mill:<branch> to any command above to pin the Context Mill branch. It defaults to main.

Results will be posted here when complete.

@brandonleung
brandonleung force-pushed the brandon/wizard-w1-3-remint-on-401 branch from 7c0893a to 5200d83 Compare September 8, 2026 18:11
@brandonleung
brandonleung force-pushed the brandon/wizard-w1-3-remint-on-401 branch from 5200d83 to 155d804 Compare September 8, 2026 19:52
@brandonleung
brandonleung force-pushed the brandon/wizard-w1-3-remint-on-401 branch from 155d804 to fb5732b Compare September 8, 2026 20:20
@brandonleung
brandonleung force-pushed the brandon/wizard-w1-3-remint-on-401 branch from fb5732b to d1b2e48 Compare September 8, 2026 20:45
@brandonleung
brandonleung force-pushed the brandon/wizard-w1-3-remint-on-401 branch from d1b2e48 to 3172e81 Compare September 8, 2026 20:57
@brandonleung
brandonleung marked this pull request as ready for review September 8, 2026 21:26
@brandonleung
brandonleung requested a review from a team as a code owner September 8, 2026 21:26
@edwinyjlim

Copy link
Copy Markdown
Member

@gewenyu99 we might need to update health checks. it might be looking at the old gateway

Comment thread src/lib/agent/agent-interface.ts

@gewenyu99 gewenyu99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

How long is the TTL that we might need a remint mid run?

I think the shape is a little sus, I'm afraid of the mid-run nudging being pretty unpredictable.

Not blocking if this stack runs

// A turn that ends on a 401 from an aged bearer re-mints once and
// continues; pi resolves the provider's apiKey per request, so
// re-registering is enough.
const turns = withGatewayRemint({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we just refresh before every single agent start?
No single agent should run beyond the TTL/ this just chops up the conversation stream unnecessarily and will likely be soooper hard to maintain. But not blocking

export function isGatewayAuthRejection(
errorMessage: string | undefined,
): boolean {
return /\b401\b|authentication_error|unauthorized/i.test(errorMessage ?? '');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There shouldn't be styling attached to stuff thrown through the gateway. There is a real/proper abort path to take

brandonleung and others added 3 commits September 8, 2026 19:22
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… prose

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@brandonleung
brandonleung force-pushed the brandon/wizard-w1-3-remint-on-401 branch from e6767f2 to 388cd7d Compare September 8, 2026 23:24
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.

3 participants