Context
Cron isolated sessions fail with [CLI_ERROR] Not logged in · Please run /login because the cron runner doesn't inject auth credentials into the CLI environment.
The auto-reply path wraps CLI execution in withAuthKeyRetry → resolveAuthEnv() (src/auto-reply/reply/agent-runner-execution.ts:375), which resolves the agent's auth profile to env vars (e.g., ANTHROPIC_API_KEY). The cron isolated runner creates ChannelBridge with only runtimeEnv from config (e.g., CLAUDE_CONFIG_DIR), missing the API key/token.
Root cause
Upstream added auth profile propagation to the cron runner in v2026.2.22 (91944ede4c), passing authProfileId to runEmbeddedPiAgent. During sync #2071 (v2026.2.25), this was skipped because it depends on src/agents/auth-profiles/session-override.ts (EXCLUDED — fork has its own src/auth/ module). The divergence note incorrectly assumed CLI runtimes handle their own auth.
See: hq/upstream/salvage-notes/cron-auth-profile-propagation.md
What
Wrap the ChannelBridge creation + execution in src/cron/isolated-agent/run.ts with withAuthKeyRetry, mirroring the auto-reply path pattern at agent-runner-execution.ts:376-402.
Implementation
In src/cron/isolated-agent/run.ts (~line 333), replace the direct ChannelBridge creation + bridge.handle() with:
import { withAuthKeyRetry } from "../../middleware/auth-key-retry.js";
runResult = await withAuthKeyRetry<AgentDeliveryResult>(
{
cfg: cfgWithAgentDefaults,
agentId,
baseEnv: resolveAgentRuntimeEnv(params.cfg, agentId),
},
async (runtimeEnv) => {
const bridge = new ChannelBridge({
provider: resolveAgentRuntimeOrThrow(params.cfg, agentId),
sessionMap,
gatewayUrl: resolveGatewayUrlFromConfig(cfgWithAgentDefaults),
gatewayToken: resolveGatewayTokenFromConfig(cfgWithAgentDefaults),
workspaceDir,
runtimeArgs: resolveAgentRuntimeArgs(params.cfg, agentId),
runtimeEnv,
});
return await bridge.handle(message, undefined, abortSignal);
},
(result) => result.error,
);
Key details:
baseEnv = resolveAgentRuntimeEnv() (preserves CLAUDE_CONFIG_DIR etc.)
withAuthKeyRetry merges baseEnv + resolved auth env, passes combined env to callback
- With single profile:
maxAttempts = 1, no retry — degenerates to resolve-once
- With multiple profiles: rotates on
isAuthRotatableError (rate-limit/auth failures)
- Third arg
(result) => result.error extracts error from non-thrown results for rotation check
Out of scope
Acceptance Criteria
Files
src/cron/isolated-agent/run.ts (primary — wrap bridge execution with withAuthKeyRetry)
src/middleware/auth-key-retry.ts (reference — existing retry/rotation logic)
src/auto-reply/reply/agent-runner-execution.ts:376-402 (reference — pattern to mirror)
Related
Context
Cron isolated sessions fail with
[CLI_ERROR] Not logged in · Please run /loginbecause the cron runner doesn't inject auth credentials into the CLI environment.The auto-reply path wraps CLI execution in
withAuthKeyRetry→resolveAuthEnv()(src/auto-reply/reply/agent-runner-execution.ts:375), which resolves the agent's auth profile to env vars (e.g.,ANTHROPIC_API_KEY). The cron isolated runner createsChannelBridgewith onlyruntimeEnvfrom config (e.g.,CLAUDE_CONFIG_DIR), missing the API key/token.Root cause
Upstream added auth profile propagation to the cron runner in v2026.2.22 (
91944ede4c), passingauthProfileIdtorunEmbeddedPiAgent. During sync #2071 (v2026.2.25), this was skipped because it depends onsrc/agents/auth-profiles/session-override.ts(EXCLUDED — fork has its ownsrc/auth/module). The divergence note incorrectly assumed CLI runtimes handle their own auth.See:
hq/upstream/salvage-notes/cron-auth-profile-propagation.mdWhat
Wrap the
ChannelBridgecreation + execution insrc/cron/isolated-agent/run.tswithwithAuthKeyRetry, mirroring the auto-reply path pattern atagent-runner-execution.ts:376-402.Implementation
In
src/cron/isolated-agent/run.ts(~line 333), replace the directChannelBridgecreation +bridge.handle()with:Key details:
baseEnv=resolveAgentRuntimeEnv()(preservesCLAUDE_CONFIG_DIRetc.)withAuthKeyRetrymergesbaseEnv+ resolved auth env, passes combined env to callbackmaxAttempts = 1, no retry — degenerates to resolve-onceisAuthRotatableError(rate-limit/auth failures)(result) => result.errorextracts error from non-thrown results for rotation checkOut of scope
defaultfield from AgentConfig and introduce sole-agent auto-selection #1575)Acceptance Criteria
maxAttempts = 1)runtimeEnvconfig (e.g.,CLAUDE_CONFIG_DIR) is preserved in merged envFiles
src/cron/isolated-agent/run.ts(primary — wrap bridge execution withwithAuthKeyRetry)src/middleware/auth-key-retry.ts(reference — existing retry/rotation logic)src/auto-reply/reply/agent-runner-execution.ts:376-402(reference — pattern to mirror)Related
defaultfield from AgentConfig and introduce sole-agent auto-selection #1575 — gut: removedefaultfield from AgentConfighq/upstream/salvage-notes/cron-auth-profile-propagation.md