The default Oban worker for agent turns: runs Codex, then routes the
outcome back to the owning ObanCodex.Agent.Instance.
The owning agent's id, instance generation, and logical turn id ride in the
job's meta, where ObanCodex.Agent.Instance puts them at enqueue time. The
generation prevents a job from an earlier same-id process from controlling
its replacement. The turn id keeps retries attached to one logical turn and
fences late or duplicate callbacks. A job without an "agent_id" (enqueued
by hand) runs normally and reports to no one.
Retry-awareness
The routing is terminal-aware, so a worker with retries reports one logical turn, not one event per attempt:
- a success, a
{:cancel, _}verdict, or an{:error, _}on the final attempt is terminal ->ObanCodex.Agent.job_finished/3 - an
{:error, _}with attempts remaining, or a{:snooze, _}, means Oban will re-run the job ->ObanCodex.Agent.job_retrying/3, which keeps the machine in:runningand re-arms its watchdog
This worker itself stays at max_attempts: 1 -- every retry is a fresh paid
Codex call, so retrying is an explicit opt-in, not a default. To opt in,
point the agent's :worker config at your own worker and delegate the
callbacks here:
defmodule MyApp.RetryingAgentJob do
use ObanCodex.Worker, queue: :agents, max_attempts: 3
@impl ObanCodex.Worker
def handle_result(result, job), do: ObanCodex.Agent.Job.handle_result(result, job)
@impl ObanCodex.Worker
def handle_error(verdict, payload, job),
do: ObanCodex.Agent.Job.handle_error(verdict, payload, job)
end