What is true regardless of what you pick
- A background agent is the same CLI run without a terminal. Claude Code's claude -p and Codex's codex exec take a task, work, print the result and exit, which is what a scheduler or a webhook handler needs.
- Defaults differ, so read them. codex exec runs in a read-only sandbox unless you pass --sandbox workspace-write. Claude Code in print mode runs the hooks in a project's .claude/settings.json even in a folder you never trusted, unless you pass --bare.
- Plain cron fires only if the machine is awake at that minute. A job scheduled for 3am on a laptop that is asleep at 3am simply does not run.
- Hosted versions exist for every major agent: Anthropic's and OpenAI's GitHub Actions run on GitHub runners, GitHub's Copilot cloud agent opens pull requests from assigned issues, and Cursor's cloud agents (formerly background agents) run in cloud VMs.
- Unattended runs spend with nobody watching. A run that fails every night fails every night, and on a subscription it draws on the same limits as your daytime work.
Your options, and where each one stops
| Approach | Good for | Breaks when |
|---|---|---|
| cron and headless modeA crontab line on an always-on machine that creates a worktree and calls claude -p or codex exec with a fixed prompt. | One or two scheduled chores, such as a nightly dependency audit or a weekly changelog draft. It is free and you can read the whole system in one line. | Runs overlap, several jobs want the same checkout, or you need to find out what happened last Tuesday. Logs, isolation and review are all yours to build. |
| GitHub Actionsanthropics/claude-code-action or openai/codex-action in a workflow, fired by a workflow event such as an @claude comment, a new issue, a pull request or a cron schedule. | Work whose triggers already live in GitHub. The runner, the branch and the pull request come with it. | Triggers come from elsewhere (an alert, a payment, a chat message), or runs need services and state that outlive a job. GitHub-hosted runners also spend your Actions minutes; self-hosted runners avoid that by making you operate them. |
| A hosted background agentGitHub's Copilot cloud agent, Codex cloud, Claude Code on the web or Cursor's cloud agents: assign a task, get a branch or pull request back. | Getting asynchronous work done with nothing to operate, for teams already paying for the product. | Code or keys must stay on your infrastructure, or the event you care about is not one the vendor can trigger on. |
| A webhook receiver you writeA small server that takes a POST from your monitoring or billing system and starts the agent CLI. | One precise trigger from a system you own, with logic no product would ship. | The second week, when you are writing a queue, a concurrency limit, authentication, retries and somewhere to read the logs. That is a product, and now you maintain it. |
| A self-hosted agent workspaceintentic's automations wake an agent on a schedule, a webhook, a connected service's events or the sandbox's own events, each run in a fresh session and worktree on your machine. | Triggers from several places in one view, every run on the board with its transcript, diff and cost, and nothing leaving your hardware. | You have one nightly job and a cron line would do. It also needs a machine that stays on, like everything else here. |
What to actually do
Start with the smallest setup that has all four parts: a machine that stays on, a trigger, a fresh checkout per run, and output that lands as a branch. A cron entry that calls the agent's headless mode in a new worktree is a legitimate first version.
If the events already live in GitHub, the official Actions integrations are the shortest path, because the trigger, the runner and the pull request are there already.
When triggers come from several systems and runs should stay on your machine, intentic covers it: automations on a schedule, a webhook, a service's events or the workspace itself, an optional guard command that skips runs with nothing to do, models chosen per automation, a spend ledger, and review before anything lands.
Four parts, and the model is the least interesting
Every background agent setup that holds up has the same four parts. The agent CLI is interchangeable between them; the parts around it are where setups fail.
- A trigger: what starts the run, and with what input.
- A host: a machine that is awake when the trigger fires.
- Isolation: a fresh checkout or container per run, so runs cannot trip over each other or over you.
- A landing: where the result goes, which should be a branch someone reviews, never the default branch.
Pick the trigger by where the event already is
A schedule suits chores that are worth doing whether or not anything happened: audits, reports, cleanup. A webhook suits systems that can send an HTTP request: monitoring, billing, a pipeline elsewhere. An event integration suits services the agent should listen to directly, such as a chat channel or a failing build.
Whatever the trigger, put a cheap check in front of it. A shell command that asks whether there is anything to do (is the queue empty, did the branch move, does yesterday's report exist) costs nothing, and a run that ends with nothing to do still cost a turn.
Isolate every run
A background run should never work in a checkout you are using. Give each one a fresh worktree or container, so two runs that overlap, or one run and you, cannot overwrite each other.
Isolation is also what makes skipping permission prompts acceptable. Nobody is there to approve a command at 3am, so the boundary has to be the container and the credentials inside it, not a prompt. Keep those credentials scoped to the job: a token for one repository, a read-only database role.
Review before merge, every time
Unattended work should produce a proposal, not a result. The run commits to its own branch and stops; a person reads the diff before anything merges. GitHub designed its Copilot cloud agent the same way: it pushes to its own branch and cannot push to your default branch.
Keep automatic merging off for unattended runs. Work held on a branch costs one click to release, while work that merged unread has to be noticed first, and the person who would have noticed was asleep.
Bound the cost before the first run
Spend is the one resource an unattended run cannot give back, so set the limits before anything fires.
- Cap each run, in dollars or turns, where your tooling allows it.
- Pick the model per job: a cheaper model for triage and summaries, the strongest one only where the work needs it.
- Skip no-op runs with a guard check rather than letting the agent discover there was nothing to do.
- Let one run per trigger go at a time, so a retry storm cannot fan out.
- Read the spend per run weekly. A job that quietly fails every night shows up there first.
Related questions
What is a background coding agent?
A coding agent that runs without anyone at the keyboard: started by a schedule, a webhook or an event, working in its own checkout, and leaving its result as a branch or pull request to review later. The agent is the same CLI you use interactively, run in its non-interactive mode.
Can Claude Code run on a schedule?
Yes. Call claude -p from cron or a CI schedule on a machine that is awake at that time, or use Anthropic's GitHub Action with a cron trigger. Anthropic also offers hosted Routines, a research preview, that run on a schedule, an API call or GitHub events.
Can a webhook start a coding agent?
Yes. Anything that can receive an HTTP request can start an agent CLI with the payload in its prompt. The hard parts are authentication, overlapping runs and logs, which is why most people use CI, a hosted agent, or a workspace with webhook triggers built in.
Is it safe to let a coding agent run unattended?
It is safe when the limits are set beforehand: an isolated checkout or container, credentials scoped to the job, a spend cap, and output that lands on a branch for review. Without those, an unattended agent can spend a lot and change a lot before anyone looks.
How do you stop a background agent from running up costs?
Cap each run, choose a cheaper model for routine jobs, skip runs with nothing to do using a guard check, and let only one run per trigger go at a time. Then read per-run spend weekly, because a job that fails every night shows up there before anywhere else.
Read next
Written against the state of the field in 2026-10. This area moves fast. Spot something out of date or wrong? Open an issue and it is fixed in the next build.