← Back to PRs

#16390: fix(cron): jobs land in wrong agent session when agentId isn't in agents.list (#16256)

by yinghaosang open 2026-02-14 18:25 View on GitHub →
gateway stale size: M trusted-contributor
## Summary Cron jobs with a non-default `agentId` (like `ops` or `content`) always get their sessions stored under `agent:main:cron:<jobId>` instead of `agent:<agentId>:cron:<jobId>`. Same thing happens for system events on the main-session path — they go to the wrong agent's session key. Closes #16256 lobster-biscuit ## Root Cause `resolveCronAgent` in `server-cron.ts` checked whether the requested agentId existed in `agents.list` before using it. Agents that exist via their directory but aren't in `agents.list` got silently dropped back to the default agent. So the job's `agentId` was ignored and everything landed under `main`. ## Changes - Before: `resolveCronAgent` required the agent to be in `agents.list` — unlisted agents fell back to default - After: uses the requested agentId directly (just normalizes it), falls back to default only when no agentId is set ## Tests - 4 new tests in `server-cron.test.ts` covering both the isolated-job and system-event paths: - unlisted agent passes through correctly - listed agent still works - missing agentId falls back to default - system events use the right session key for unlisted agents - All fail before the fix, pass after - `pnpm build` and `pnpm vitest run src/gateway/server-cron.test.ts` pass <!-- greptile_comment --> <h3>Greptile Summary</h3> Fixes cron job session key resolution so that jobs with a non-default `agentId` (e.g., `ops`, `content`) correctly route to `agent:<agentId>:cron:<jobId>` instead of always falling back to `agent:main:cron:<jobId>`. - **Root cause**: `resolveCronAgent` previously checked whether the requested agentId existed in `agents.list` before using it. Agents that exist via their directory but aren't explicitly listed got silently dropped back to the default agent. - **Fix**: Removes the `agents.list` membership check and uses the requested agentId directly after normalization. Falls back to default only when no agentId is set. This is safe because `normalizeAgentId` already sanitizes input to path-safe values, and downstream code (`runCronIsolatedAgentTurn`) already handles unlisted agents gracefully. - **Tests**: 4 new tests covering both the isolated-job and system-event code paths, verifying correct agentId passthrough for unlisted agents, listed agents, and default fallback. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it removes an overly restrictive guard that was the root cause of the bug, and the change is well-tested. - The change is minimal, focused, and correct. The removed `agents.list` membership check was the only source of the bug. Input sanitization is handled by `normalizeAgentId` (path-safe, max 64 chars). Downstream code already handles unlisted agents without error. All 4 new tests directly validate the fix across both execution paths. - No files require special attention. <sub>Last reviewed commit: 13bfba2</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs