You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make lazy OAuth a cancellable, host-owned operation. A subagent may discover that authentication is required, but it must never start or render an interactive authentication flow inside its own context. It must wait while the top-level interactive host handles the challenge, then resume or terminate deterministically.
What happened
A Codex account exhausted its quota, so the user logged out and allowed lazy authentication to start:
Lazy auth opened the browser with the wrong existing account/profile—the account whose quota was already exhausted.
Cancelling or abandoning that auth attempt did not settle the pending operation; the LLxprt instance appeared to hang.
Another LLxprt instance attempted a device-code fallback, but the intended second account did not have that flow enabled because it is not used for headless authentication.
Recovery required killing and continuing instances until one authenticated through the intended browser account.
Separately, subagents that encountered missing/expired Codex authentication printed instructions telling the user to enable authentication inside the subagent context and then waited there. That context is not the interactive owner and may not be directly accessible.
Browser/profile association for OAuth buckets is already tracked by #1045. This issue is about deterministic cancellation and ownership of interactive auth, whether lazy auth was triggered by the host or by a subagent.
Expected behavior
Authentication may be required by any provider runtime, but only the top-level interactive host owns authentication UI, browser/device-flow selection, cancellation, and completion.
A subagent that needs authentication should enter a visible waiting-for-auth state and escalate a structured challenge to the host. It must not print user instructions, launch a browser, start device polling, or block on an interaction local to the subagent.
The host should complete one of four terminal outcomes—success, cancelled, failed, or timed out—and deliver it to every attached waiter exactly once. Successful authentication may resume the blocked request through the established retry/recovery policy. Every other result must settle it with a typed, recoverable outcome rather than leave a pending promise, stream, task, listener, or process.
Required architecture and invariants
Host-owned auth coordinator
Introduce or designate one session-level coordinator as the owner of interactive authentication.
Provider/agent runtimes report an auth challenge containing the provider, configured profile/bucket identity, requesting runtime/task identity, reason, and a correlation ID. Do not send credentials through the event.
Propagate subagent challenges through the orchestrator to the owning interactive host.
Coalesce equivalent concurrent challenges so one host interaction can serve all matching waiters.
Represent waiting explicitly in task/subagent status without adding auth instructions to the subagent transcript.
If there is no interactive supervising host, fail fast with an actionable structured error instead of opening an invisible prompt or waiting indefinitely.
Cancellation and cleanup
The visible cancel action aborts provider polling, callback listeners/servers, timers, and ephemeral auth-session state.
User cancellation of a shared host interaction settles all attached waiters as cancelled while keeping the host, parent agent, and subagents alive.
Cancellation of one requesting task detaches only that waiter; it must not abort a shared auth attempt while other live waiters still require it.
If no waiters remain, the coordinator cleans up the orphaned attempt.
Host shutdown, provider failure, callback failure, and timeout use the same deterministic teardown path.
Cancellation/failure must not silently switch from browser auth to device-code auth or loop back into the same account. The host may explicitly offer retry, another configured bucket/account, or another supported auth method.
A cancelled attempt can be retried without restarting LLxprt.
Every waiter and resource settles exactly once, including races between success, cancellation, timeout, and shutdown.
Timeout and retry safety
Every interactive auth session has a finite, configurable lifetime and performs the same cleanup as explicit cancellation when it expires.
Timeout is a backstop, not a substitute for a working cancel action.
Lazy auth no longer turns a wrong-account browser launch into a process-restart loop. Authentication has one visible owner, cancel always settles, subagents wait without impersonating the UI, and successful auth resumes the work that actually requested it.
Objective
Make lazy OAuth a cancellable, host-owned operation. A subagent may discover that authentication is required, but it must never start or render an interactive authentication flow inside its own context. It must wait while the top-level interactive host handles the challenge, then resume or terminate deterministically.
What happened
A Codex account exhausted its quota, so the user logged out and allowed lazy authentication to start:
Browser/profile association for OAuth buckets is already tracked by #1045. This issue is about deterministic cancellation and ownership of interactive auth, whether lazy auth was triggered by the host or by a subagent.
Expected behavior
Authentication may be required by any provider runtime, but only the top-level interactive host owns authentication UI, browser/device-flow selection, cancellation, and completion.
A subagent that needs authentication should enter a visible waiting-for-auth state and escalate a structured challenge to the host. It must not print user instructions, launch a browser, start device polling, or block on an interaction local to the subagent.
The host should complete one of four terminal outcomes—success, cancelled, failed, or timed out—and deliver it to every attached waiter exactly once. Successful authentication may resume the blocked request through the established retry/recovery policy. Every other result must settle it with a typed, recoverable outcome rather than leave a pending promise, stream, task, listener, or process.
Required architecture and invariants
Host-owned auth coordinator
Cancellation and cleanup
Timeout and retry safety
Acceptance criteria
Related issues
Appreciable outcome
Lazy auth no longer turns a wrong-account browser launch into a process-restart loop. Authentication has one visible owner, cancel always settles, subagents wait without impersonating the UI, and successful auth resumes the work that actually requested it.