
Every OAuth integration for an agent carries a two-token reality:
A 20-minute demo never crosses the access token expiry boundary, so the "store the token and call the API" model looks correct. It is not correct. It is untested.
Anthropic built Fable 5 specifically to cross that boundary. Its own product materials describe a model that, run inside a harness like Claude Code or Claude Managed Agents, can work for days at a time: planning across stages, delegating to sub-agents, and checking its own work. The canonical examples are large codebase migrations and multi-day autonomous sessions. In early testing, Stripe reported pointing Fable 5 at a 50-million-line Ruby codebase and running the migration in a day.
A run measured in hours or days passes through the access-token expiry boundary many times. Expiry stops being an edge case and becomes the normal operating condition.
The single-token expiry problem is old and, on its own, tractable. What is new with Fable 5 is concurrency at the credential layer.
Fable 5's headline pattern is fan-out: an orchestrator decomposes a goal and delegates scoped workstreams to sub-agents that run in parallel. Community reports describe sessions spinning up hundreds, and in some cases up to roughly a thousand, parallel sub-agents for codebase-scale work.
Now consider one user's Slack or Google credential under that pattern:
If your refresh strategy is reactive (wait for the 401, then refresh), those concurrent refreshes race. For providers that rotate refresh tokens, and Slack is the common example, each successful refresh issues a new refresh token and retires the previous one.
The result: the first sub-agent refreshes and rotates the token. The others are still holding the old refresh token, so their refresh attempts fail against a credential the provider has already retired. One worker wins; the rest cascade into hard authentication failures that no retry can fix.
This is the "3am token expiry race condition" Scalekit has written about before, except Fable 5's architecture triggers it by design rather than by coincidence. The more the model parallelizes, the more reliably it reproduces the race.
This is what makes reactive handling so fragile across a real connector set:
A refresh strategy that works for GitHub in the demo silently fails for Slack in production.
When a token expires mid-run, the honest expectation is a crash. The reality is worse: API requests begin failing, often without surfacing as a hard error the agent treats as fatal, and the run continues.
The failure then surfaces days later as "why is the output wrong" rather than "auth expired at hour four."
Fable 5 makes this both more likely and more dangerous. More likely, because longer runs cross more expiry boundaries. More dangerous, because the model is explicitly built to operate with minimal oversight, so the watching human is gone by design.
A 20-minute task almost never overlaps a revocation event. A three-day task has a meaningfully larger window in which someone leaves or access is pulled. Your agent has to distinguish "refresh and continue" from "stop and request re-consent," without a human present.
The rule is simple: the credential should never touch the model. The agent calls a tool, receives a result, and never sees a token. Long-horizon fan-out makes that discipline harder to maintain by hand precisely when it matters most. Keeping credentials in a dedicated token vault is what separates production architectures from fragile prototypes.
None of this argues against long-horizon agents. It argues that the token lifecycle has to live in infrastructure, not in the agent code.
The production pattern has five parts:
With Scalekit, the agent expresses none of that lifecycle logic. You resolve a connected account for the user, discover the tools available under their grant with list_scoped_tools, and call a tool with execute_tool, passing a connection_name and the user's identifier.
Notice what is absent: no access token, no refresh call, no 401 handler, no per-provider branch for Slack versus Google. The identifier is the only thing that changes whose credential is used, and it is the same line whether the run lasts eighteen minutes or three days.
This is buildable in-house, and it is worth saying so plainly. Proactive refresh keyed off expires_in, a distributed lock, a single-retry-then-surface policy, and monitoring on refresh success and failure rates are a known, documented pattern. A capable team can implement it.
The cost is not the first provider. It is the tenth. Each connector brings its own expiry window, rotation behavior, and revocation semantics, and the surface compounds with every tool you add and every sub-agent you run in parallel. You also own the vault, the lock infrastructure, and the audit trail a security review will eventually ask about.
The real build-versus-buy question is not whether you can write proactive refresh once. It is whether you want to maintain provider-specific lifecycle logic, per tenant, at fan-out concurrency, as a permanent part of your codebase. For most teams shipping agents, that is undifferentiated infrastructure.
Fable 5 ships with blocking safety classifiers for dual-use domains such as cybersecurity and biology. When a classifier blocks a request, the Claude API returns a standard HTTP 200 with stop_reason: "refusal" and a stop_details object naming the restriction category, and the recommended pattern is to fall back to another model such as Claude Opus 4.8. Anthropic reports this triggers in fewer than 5% of sessions.
The implication for auth is small but real: when a step routes to a different model mid-run, the credential and tool layer has to survive the switch untouched. If your tokens live in the model's context or are tied to one model's runtime, a mid-run fallback is one more way the run breaks. Keeping the lifecycle in infrastructure makes the model swap a non-event.
Access tokens are deliberately short-lived, commonly 5 to 60 minutes, to limit the damage if one leaks. A Fable 5 run measured in hours or days crosses that boundary repeatedly, so expiry is the normal case, not an edge case. The fix is to refresh proactively using the expires_in value rather than reacting to a 401.
When several workers share one user's credential and cross the expiry boundary at once, each tries to refresh independently. For providers that rotate refresh tokens on use, the first refresh invalidates the token the others are holding, so their refreshes fail. Fable 5's sub-agent fan-out produces many concurrent workers on one credential, which reproduces the race routinely. A distributed lock that serializes refresh to a single winner resolves it.
Reactive retry is exactly what creates the race at concurrency, and it does nothing for silent failures that never surface as a clean 401. Proactive refresh removes the boundary from the agent's path; a single-retry-then-surface policy handles the residual cases without cascading.
A revoked refresh token cannot be recovered by automated retry. It requires explicit re-authorization through the consent flow. Your system needs to distinguish an expired access token, which refreshes silently, from a revoked grant, which should surface as a re-consent request. Longer runs widen the window in which revocation and offboarding occur, so this matters more for Fable 5 than for short tasks.
No. The credential should never reach the model or its sub-agents. The agent calls a tool, receives a result, and never sees a token. Keeping credentials in a vault and fetching them on demand keeps them out of context, logs, and persisted handoff state.
You can build proactive refresh, distributed locking, and monitoring yourself; it is a documented pattern. The cost is maintaining provider-specific expiry, rotation, and revocation logic across every connector, per tenant, at fan-out concurrency, plus the vault and audit layer. Scalekit provides that lifecycle management behind execute_tool so the agent code holds no tokens and no per-provider refresh logic.
The token lifecycle problem exists for any agent whose run outlasts its access token. Fable 5 makes it unavoidable rather than occasional, because it is explicitly built for multi-day, minimally supervised, sub-agent-heavy runs. The same fix applies to any long-horizon agent regardless of model.
Building a long-horizon agent that has to outlive its tokens? Scalekit's connectors handle OAuth, scoped per-user access, and the full token lifecycle so your agent code never touches a credential. Explore the connector catalog at docs.scalekit.com/agentkit/connectors, or talk to an engineer about your setup.