Back to blog

July 19, 2026Ceren Kaya Akgün

Background Coding Agents: Cheap, Sandboxed, Running 24/7

What a background coding agent is, what one costs to run 24/7, and how a sandbox keeps your GitHub token safe. With real prices and three recipes. →

background-coding-agentcoding-agentopencodeself-hostedai-agentgithub-automationai-workflow
Background Coding Agents: Cheap, Sandboxed, Running 24/7

TL;DR: A background coding agent is an AI agent that writes code while nobody is watching: an event starts it, a sandbox contains it, and a diff or pull request comes out the other end. Budget models have made this cheap enough to run around the clock. DeepSeek V4 Flash costs $0.14 per million input tokens on the OpenCode Zen gateway, which puts a month of nightly repo maintenance under $8. This post explains the architecture using Heym's new OpenCode Go node as the working example: a trust ladder of seven publish modes, a container design that never sees your GitHub token, and screenshots that land in the pull request by themselves.

Key Takeaways:

  • Background coding agents differ from IDE copilots in one fundamental way: they run unattended, so trust, isolation, and cost dominate the design instead of latency and autocomplete quality
  • Publish modes form a trust ladder. diff_only changes nothing remotely; direct_commit pushes straight to main. Teams should climb the ladder as agent output proves itself
  • The GitHub token and the coding sandbox must never meet. Host-side git plus a throwaway hardened container is the pattern that makes unattended runs safe
  • Budget models changed the economics: at DeepSeek V4 Flash prices, always-on repo maintenance costs less per month than a single hour of engineer time
  • Any event can be the trigger. Webhooks, cron, Slack, email, and kanban cards all work; none of them require CI/CD pipelines or YAML

Table of Contents

What Is a Background Coding Agent?

A background coding agent is an AI coding agent that works on a repository without a human at the keyboard. Something happens, a schedule fires or a webhook arrives, and the agent clones the repo, edits files in an isolated environment, and hands back a diff, a commit, or a pull request for a person to review.

The contrast is with the copilot in your editor. An IDE assistant optimizes for latency and suggestion quality because you are sitting there waiting. A background agent optimizes for three different things: how much you trust it to publish, how well it is contained while it works, and what each run costs, because unattended runs multiply.

That last word, unattended, is what makes this a systems design problem rather than a prompting problem. The same shift shows up across agentic tooling; our post on agentic workflows covers the general pattern. This post stays narrow: code in, code out, nobody watching.

Heym, the self-hosted AI workflow automation platform this blog belongs to, ships this pattern as the OpenCode Go node: an open source background coding agent building block that runs the OpenCode CLI (source on GitHub) inside a hardened container from any workflow. I co-founded Heym, and this post is written from the builder's side of that node: the design calls below, from the publish modes to the fail-closed sandbox, are decisions we debated while shipping it, not features I am describing from a distance. The node is the working example through the rest of this post, but every design decision in it applies to any background coding agent you might build or buy.

Why Run a Coding Agent 24/7?

Because a large share of real repository work is small, mechanical, and endlessly renewable. Lint debt accumulates. Dependencies drift. Test flakiness creeps in. Docstrings rot. None of it justifies an engineer's focused hour, and all of it fits in a coding agent's context window.

An always-on agent turns that backlog into a queue. A cron trigger drains a little of it every night. A webhook picks up each new crash report as it arrives. The unit of work stops being "sprint task someone remembers to file" and becomes "event that fires whether or not anyone remembers."

The reason this was rare until recently is cost. Running a frontier model on maintenance chores around the clock burned money faster than the chores were worth. Budget coding models flipped that math, which is the next section, with real numbers.

What Does a 24/7 Coding Agent Actually Cost?

The OpenCode Go node authenticates against the OpenCode Go model gateway, and the published Zen pricing makes the economics concrete. Prices below are per million tokens as listed on that page in July 2026:

ModelInput / 1MOutput / 1MCharacter
DeepSeek V4 Flash$0.14$0.28Budget workhorse for mechanical tasks
MiniMax M3$0.30$1.20Cheap generalist
Qwen3.7 Plus$0.40$1.60Balanced mid-tier
Kimi K2.7 Code$0.95$4.00Code-tuned mid-tier
GLM 5.2$1.40$4.40Stronger reasoning, still affordable
Qwen3.7 Max$2.50$7.50Top of the budget tier
Claude Sonnet 5$2.00$10.00Frontier comparison point
GPT 5.5$5.00$30.00Frontier comparison point

Here is a worked example rather than an adjective. Suppose a nightly maintenance run reads about 1.5M tokens of repository context and produces 150K tokens of reasoning and code. On DeepSeek V4 Flash that is 1.5 × $0.14 plus 0.15 × $0.28, roughly $0.25 per run. Thirty nightly runs cost about $7.60 a month. The same schedule on GPT 5.5 would run about $12 per night, roughly $360 a month, which is why model choice is the first architectural decision for a background agent, not an afterthought.

Two footnotes belong next to any cost table. First, token consumption varies wildly with repo size and task scope, so treat the example as arithmetic you should redo with your own numbers. Second, the gateway also lists limited-time free variants such as DeepSeek V4 Flash Free, with the explicit caveat that collected data may be used to improve the model during the free period. Fine for open source repos, wrong for anything private.

The deeper practice of budgeting agent workloads has its own post, AI agent cost optimization. The short version for coding agents: match the model to the task tier, and let the cheap model fail upward to an expensive one rather than defaulting everything to the frontier.

Model rosters on the gateway change often, which is why the node populates its Model dropdown from the live list (GET https://opencode.ai/zen/go/v1/models) instead of hardcoding names. Leave the field empty and it uses the runner default, currently Kimi K3.

How Much Should You Trust an Agent With Your Repo?

Trust is not a yes or no question; it is a ladder, and each publish mode is a rung. The OpenCode Go node makes the ladder explicit with seven modes:

Publish modeWhat touches your remoteTrust levelTypical use
diff_onlyNothingNone requiredEvaluation, code review prep
patch_artifactNothing, diff saved as downloadable fileNone requiredAudit trails, air-gapped review
draft_prBranch + draft pull requestLowDefault for new automations
open_prBranch + review-ready pull requestMediumProven task types
commit_pushBranch push, no PRMediumFeeding other tooling
update_existing_prNew commit on an existing PRMediumIterative fix loops
direct_commitCommit straight to the base branchHighMechanical work guarded by tests

The ladder gives a team a rollout policy for free. Week one, run everything as diff_only and read the patches. When the patches are consistently sane for one task type, promote that task to draft_pr. Formatting fixes with a solid test suite behind them can eventually earn direct_commit, and nothing else should.

The two bottom rungs deserve emphasis because most hosted agents skip them. A mode that provably cannot write to your remote is what makes it safe to point an agent at a repository you do not own the politics of yet. It converts "should we let AI touch our code" from a meeting into an experiment.

Review discipline still applies above the bottom rungs. Pull requests written by an agent deserve the same adversarial reading as human ones, and our AI code review post argues agents should do part of that reading too. The pipeline composes: one workflow writes the PR, another reviews it.

How Do You Sandbox a Coding Agent?

The rule that makes unattended coding safe is simple to state: the credentials that can publish must never exist in the environment where generated code runs. Everything else in the design follows from that rule.

In the OpenCode Go node, the run is split across a boundary:

  • On the host, Heym clones the repository, runs the optional setup command, and later commits, pushes, and opens the pull request. The GitHub token lives here and only here.
  • In a throwaway container, the OpenCode CLI edits files. The container gets the repository files and the model API key, nothing else. It is created for the run and destroyed after it.
One background coding run, host vs container
Trigger
Event starts the workflow
A webhook, cron tick, Slack message, or kanban card calls the OpenCode Go node.
Host
Clone and setup
Heym clones the repository and runs the optional setup command. The GitHub token lives here and only here.
Container
opencode run edits files
A throwaway hardened container holding the repo files and the model API key, nothing else.
Host
Diff computed from git
Changed files and the patch come from the repository state, not from what the model claims it did.
Host
Publish
Commit, push, pull request, and screenshot upload, per the chosen publish mode.
The boundary that makes unattended coding safe: the credential that can publish never enters the environment where generated code runs.

Here is the same anatomy as a table, split by where each step executes and which secret it can see:

StepRuns whereSecrets present
Clone repositoryHostGitHub token (host only)
Optional setup commandHostGitHub token (host only)
opencode run edits filesThrowaway containerOpenCode API key only
Compute diff and changed filesHostNone needed
Commit, push, open PRHostGitHub token (host only)
Upload PR screenshotsHostGitHub token (host only)

The container itself is hardened the way you would harden any untrusted workload: all Linux capabilities dropped, no privilege escalation, a read-only root filesystem with the workspace as the only writable mount, a tmpfs /tmp, and pid, memory, and CPU limits. Network egress stays open because the agent must reach the model gateway, and that is precisely why the GitHub token cannot be inside: an agent that hallucinates or gets prompt-injected into running curl with stolen credentials finds no credentials to steal.

One more property matters for operators: the sandbox is fail-closed. We made that call while designing the node because the OpenCode CLI, unlike Codex, brings no OS-level sandbox of its own, so silently degrading to host execution would undo the entire isolation story. If Docker or the runner image is unavailable, the node errors instead of quietly falling back to running the agent on the host. An explicit opt-out exists for operators who accept host execution, but it is a decision someone has to make, not a default anyone can stumble into.

If you have read our Codex node deep dive, the philosophy will look familiar: Heym owns every git and GitHub action, the agent only ever edits files on disk. In fact the two nodes share the same publish pipeline: while building OpenCode Go we extracted the Codex node's workspace and git-publish logic into shared services, so both coding agents go through one audited path for cloning, committing, and opening pull requests. The OpenCode Go node adds the container jail on top, since the OpenCode CLI does not bring its own OS-level sandbox. The agent's result is not scraped from stdout either; the runner parses OpenCode's structured JSON event stream for the final summary and then computes the diff from git on the host, so the reported change list comes from the repository itself, not from what the model claims it did.

What Can Trigger a Background Coding Agent?

Anything that can start a workflow. That sounds trivial and is actually the point: coding agents have historically lived inside CI/CD, which only reacts to repository events, or inside chat UIs, which only react to a human typing. A workflow platform removes both constraints.

Concretely, the same OpenCode Go node runs unchanged behind:

  • A cron trigger for nightly or hourly maintenance sweeps
  • A webhook from a bug tracker, an error monitor, or any service that can POST JSON
  • A Slack message or inbound email, with the text flowing into the task prompt as $input.text
  • A kanban card, where dragging a card into a column starts the chain, a pattern we unpacked in the agentic kanban board post
  • Another workflow, composing the agent into larger pipelines

No YAML files, no pipeline configuration, no runner fleet to maintain. If you are new to event-driven automation as a category, what is AI workflow automation covers the foundations.

Three Recipes You Can Copy

Three concrete wirings show the range. Each is a small workflow you can rebuild in a few minutes, and the OpenCode Go PR Fix Agent template gives you the core of all three as an importable starting point. Explore it below the way you would on the Heym canvas: click a node to inspect its configuration, then copy or download the JSON and import it as a new workflow. It ships without credentials, so after import open the OpenCodeFix node and select your own OpenCode Go and GitHub credentials.

opencode-go-pr-fix-agent.json
View template JSON
{
  "heym": true,
  "nodes": [
    {
      "id": "opencode_pr_setup_note",
      "type": "sticky",
      "position": {
        "x": 400,
        "y": 500
      },
      "data": {
        "label": "SetupNote",
        "note": "### Before you run\n- Add an OpenCode Go credential with a gateway API key.\n- Add a GitHub credential with repository access.\n- Set Repository URL on OpenCodeFix.\n- Choose the OpenCode model and optional reasoning variant.\n- Review the setup command and publish mode."
      }
    },
    {
      "id": "opencode_pr_task",
      "type": "textInput",
      "position": {
        "x": 60,
        "y": 220
      },
      "data": {
        "label": "CodeTask",
        "inputFields": [
          {
            "key": "text",
            "defaultValue": "Fix the failing tests, keep the patch focused, run the relevant checks, and open a pull request with a concise summary."
          }
        ]
      }
    },
    {
      "id": "opencode_pr_fix",
      "type": "opencodeGo",
      "position": {
        "x": 400,
        "y": 220
      },
      "data": {
        "label": "OpenCodeFix",
        "credentialId": "",
        "githubCredentialId": "",
        "repositoryUrl": "https://github.com/your-org/your-repo",
        "baseBranch": "main",
        "taskPrompt": "$CodeTask.body.text",
        "publishMode": "open_pr",
        "branchName": "opencode/$executionId",
        "opencodeModel": "opencode/kimi-k3",
        "opencodeVariant": "",
        "timeoutSeconds": 3600,
        "setupCommand": "npm install && npm test"
      }
    },
    {
      "id": "opencode_pr_result",
      "type": "output",
      "position": {
        "x": 760,
        "y": 220
      },
      "data": {
        "label": "FixResult",
        "outputSchema": [
          {
            "key": "summary",
            "value": "$OpenCodeFix.summary"
          },
          {
            "key": "validation",
            "value": "$OpenCodeFix.validation"
          },
          {
            "key": "changedFiles",
            "value": "$OpenCodeFix.changedFiles"
          },
          {
            "key": "pullRequestUrl",
            "value": "$OpenCodeFix.pullRequestUrl"
          },
          {
            "key": "pushedBranch",
            "value": "$OpenCodeFix.pushedBranch"
          },
          {
            "key": "diff",
            "value": "$OpenCodeFix.diff"
          }
        ]
      }
    }
  ],
  "edges": [
    {
      "id": "opencode_pr_e1",
      "source": "opencode_pr_task",
      "target": "opencode_pr_fix"
    },
    {
      "id": "opencode_pr_e2",
      "source": "opencode_pr_fix",
      "target": "opencode_pr_result"
    }
  ]
}

Nightly lint and type debt sweep. Cron trigger at 03:00, OpenCode Go node on DeepSeek V4 Flash, task prompt asking it to fix outstanding linter and type-checker complaints without changing behavior, publish mode draft_pr, setup command installing dependencies so the agent can run the linters itself. Cost per the arithmetic above: about a quarter per night. You arrive each morning to either a green draft PR or nothing.

Slack bug report to proposed fix. A Slack trigger listens for messages in a bugs channel. The message text becomes the task prompt through $input.text, the model is a mid-tier like Kimi K2.7 Code because diagnosis is harder than formatting, and publish mode diff_only returns the patch and summary to the thread for a human verdict. Nobody merges anything an agent inferred from a two-line bug report, but the investigation is already done.

Kanban card to pull request. A board column named Implement carries a chain ending in the OpenCode Go node with publish mode open_pr. Dragging a card with a written spec into the column produces a review-ready pull request, and the card records the PR URL in its outputs. Paired with a planning column that drafts the spec first, this is the full loop from idea to reviewable code.

The node reports summary, diff, changedFiles, and pullRequestUrl as outputs, so every recipe can route its result onward: post the summary to Slack, file the diff, or gate a follow-up workflow on the PR URL existing. For observability across many such runs, OpenTelemetry tracing for AI agents shows how Heym exposes execution spans.

Screenshots in the Pull Request

Reviewing UI changes from a diff alone is miserable, and it is where unattended agents lose reviewer goodwill fastest. The node closes that gap mechanically. For frontend tasks, the agent is instructed to save PNG screenshots of its result under a gitignored path during the run. After Heym opens or updates the pull request, it uploads those images to a shared GitHub prerelease as assets and embeds them into the PR description.

The reviewer experience changes completely: the pull request opens with the rendered result at the top, before the file list. No checkout, no local build, no guessing whether the agent's CSS actually renders. Screenshots never enter git history, so the repository stays clean, and because the upload happens host-side after the sandboxed run, the pattern respects the token isolation rule from earlier.

The prerelease detour exists because GitHub's API has no way to attach binary files to a pull request description directly. Release assets do get stable download URLs, so a single shared prerelease acts as the image bucket and each PR embeds its own assets by URL. It is an unglamorous trick, and it is exactly the kind of plumbing a background agent needs solved once, centrally, rather than by every workflow author.

A Coding Agent as a Tool for Another Agent

The most interesting configuration is not the coding agent alone; it is the coding agent as a delegate. The OpenCode Go node attaches to an AI Agent node's tool handle, which means a higher-level agent can decide mid-task that something needs code and hand the job off.

The division of authority is deliberate. The workflow author fixes the credentials, the model, the timeout, and the publish mode, the things that control blast radius. The calling agent supplies the task prompt and optionally the repository URL at call time, the things that require judgment about the current situation. A triage agent reading incoming issues can route one to the coding tool with a precise brief, then read the returned summary and diff and decide what to tell a human.

This composes with everything in the trust ladder: an orchestrating agent calling a diff_only coding tool is a research assistant, the same agent calling open_pr is a junior engineer. If multi-agent structure is new territory, multi-agent AI systems maps the patterns.

How This Compares to Hosted Background Agents

Hosted background agents such as Devin, Cursor's background agents, GitHub Copilot's coding agent, and Codex Cloud all deliver a similar surface: task in, pull request out. They are polished, and for a team that wants zero infrastructure they are the shortest path. It would be dishonest to claim otherwise.

The self-hosted approach trades that polish for four properties the hosted tier does not sell:

  • Model freedom. The hosted agents run their vendor's models. The gateway approach runs whatever the roster offers, including budget models that make 24/7 operation rational, and the roster updates without waiting for a vendor release.
  • Trigger freedom. Hosted agents react to their supported surfaces, typically GitHub events, a web UI, and Slack. A workflow node reacts to anything the platform can receive, which includes your internal systems.
  • Custody. Your repository is cloned onto infrastructure you control, the sandbox policy is inspectable in the open source code, and the token isolation is verifiable rather than promised.
  • Cost shape. No per-seat pricing and no per-task premium. You pay tokens at gateway list price plus your own compute.

The honest caveat: you also inherit the operational work, keeping Docker healthy, watching runs, and reviewing output quality. Heym compresses most of it into the node and the execution history, but a hosted agent's SLA is someone else's problem, and self-hosting makes it yours. If your repos cannot leave your infrastructure anyway, the decision makes itself; our migration guide covers moving existing automations over.

Getting Started

The node ships in current Heym releases. The path from zero to first run:

  1. Create an OpenCode Go credential with an API key from opencode.ai, and a GitHub credential whose token can push branches and open PRs on the target repo.
  2. Add the OpenCode Go node to a workflow and select both credentials.
  3. Point Repository URL at the repo, pick a model from the live dropdown or leave the default Kimi K3.
  4. Write the task prompt, set publish mode to diff_only, and run it once manually to read what comes back.
  5. Attach a real trigger, cron or webhook or board column, and climb the trust ladder as the output earns it.

If you would rather start from a working workflow than an empty canvas, import the OpenCode Go PR Fix Agent template: it wires the task input, the node, and the result output, and you only supply credentials and a repository. The node documentation covers every field, and the Heym repository has the full source, including the sandbox wrapper, if you want to verify the isolation claims rather than take them on faith.

FAQ

What is a background coding agent?

An AI coding agent that works on your repository unattended. An event starts it, it edits code in an isolated environment, and it delivers a diff, commit, or pull request for human review. The defining constraint is that nobody is watching while it works, which makes trust, isolation, and cost the core design axes.

How much does it cost to run one 24/7?

At OpenCode Zen list prices, DeepSeek V4 Flash costs $0.14 per million input tokens and $0.28 per million output. A nightly run consuming 1.5M input and 150K output tokens is about $0.25, under $8 monthly. The same workload on a frontier model can exceed $300 monthly, so model selection is the main cost lever.

How does the sandbox protect my GitHub token?

The token never enters the container where generated code runs. Heym performs all cloning, committing, pushing, and PR creation on the host, while the agent edits files inside a throwaway hardened container holding only repository files and the model API key. Even a fully compromised agent process has no push credentials to steal.

Can it run without CI/CD?

Yes, that is the point. Any workflow trigger starts it: webhooks, cron schedules, Slack messages, inbound email, or a kanban card moving between columns. CI/CD reacts only to repository events, so decoupling the agent from the pipeline is what enables always-on and event-driven operation.

What is the OpenCode Go node in Heym?

A workflow node that runs the OpenCode CLI against a GitHub repository inside an isolated container. It authenticates to the OpenCode Go model gateway, offers seven publish modes from diff-only to direct commit, and can be attached to an AI Agent node as a callable tool, so any workflow or agent can delegate coding tasks to it.

What models can the OpenCode Go node use?

Whatever the OpenCode Go gateway currently serves. The node fetches the live model list and shows it as a searchable dropdown, with Kimi K3 as the default and options including DeepSeek V4 Flash, DeepSeek V4 Pro, Qwen3.7 Max, GLM 5.2, MiniMax M3, and Grok 4.5. The roster changes often, which is why it is not hardcoded.

Which publish mode should I start with?

diff_only. It cannot touch your remote, so evaluating the agent is risk-free. Promote proven task types to draft_pr, use open_pr once a task type is boringly reliable, and reserve direct_commit for mechanical changes that a test suite fully guards.

How do screenshots end up in the pull request?

The agent saves PNGs under a gitignored path during UI tasks. After the PR is opened, Heym uploads them as assets to a shared GitHub prerelease and embeds them in the PR description. Reviewers see the rendered result without checking out the branch, and the images never pollute git history.

References

Ceren Kaya Akgün
Ceren Kaya Akgün

Founding Engineer

Ceren is a founding engineer at Heym, working on AI workflow orchestration and the visual canvas editor. She writes about AI automation, multi-agent systems, and the practitioner experience of building production LLM pipelines.

Enjoyed this post? Get the next one in your inbox.

A monthly note with practical ideas for building AI workflows that hold up in production. No noise, and you can unsubscribe anytime.

No spam, no marketing fluff