Cost engineering

Scheduled agents re-learn the job every run. Replay the part that never changes.

Claude Code Routines, Actions crons, and OpenClaw heartbeats made recurring agent runs normal. The token bill compounds on the part that never changes.

The short version
  • 01Claude Code Routines, GitHub Actions crons, and OpenClaw heartbeats all bill a full model session per run.
  • 02A scheduled task was chosen because it repeats, so the agent re-derives the same N-step sequence every time.
  • 03Record, compile, replay, diff. Level 0 replays the deterministic core at 0 tokens; drift fails loudly with exit 1.

Recurring headless agent runs stopped being exotic this year. Three separate substrates now ship them as a first-class primitive, and all three bill the same way: a full model session, every run, whether or not anything changed since the last one.

This post is about the part of those runs that never changes — and why replaying it costs 0 tokens instead of re-deriving it costs thousands.

Scheduled agent runs are now a normal primitive

Claude Code Routines (in research preview as of July 2026) are saved Claude Code configurations — a prompt, repositories, connectors — that run on Anthropic-managed cloud infrastructure, so they keep going while your laptop is closed. Schedule triggers come as hourly, daily, weekday, and weekly presets, with custom cron expressions via /schedule update (minimum interval: one hour). Per the docs, routines draw down subscription usage the same way interactive sessions do, plus a daily cap on runs per account. (code.claude.com/docs/en/routines)

GitHub Actions crons around anthropics/claude-code-action predate routines and are still the workhorse. Anthropic's own solutions guide ships a scheduled-maintenance example on cron: "0 0 * * 0" — a full agent session every Sunday that checks outdated dependencies, runs npm audit, and reviews stale issues.

OpenClaw heartbeats are the highest-frequency of the three: per the docs, a heartbeat "runs periodic agent turns in the main session" — default cadence every 30 minutes (60 on Anthropic OAuth), configurable via heartbeat.every, optionally driven by a HEARTBEAT.md checklist the agent re-reads each turn. At the default cadence that is up to 48 model turns a day, per agent, before you've asked it anything.

Three different products, one shape: the schedule fires, a model session spins up, tool definitions load, the agent re-reads its instructions, re-derives its plan, re-executes its tool calls, re-summarizes, exits. Tomorrow: same thing.

The waste compounds because the workflow doesn't

Here's the uncomfortable property of a scheduled agent specifically: the task was chosen for the schedule precisely because it's repeatable. Check the same endpoints. Pull the same metrics. Diff the same feeds. The workflow is the same N-step tool sequence every run — but the agent doesn't know that, so it pays to re-derive it from scratch every time.

This isn't a fringe critique; it's the vendor's own analysis. Anthropic's engineering post Code execution with MCP walks through a single tool-heavy workflow whose tool definitions and intermediate results consumed about 150,000 tokens flowing through context, restructured down to about 2,000 — a 98.7% reduction. Their point was about how tool results move through context; the underlying admission is bigger: on tool-heavy workflows, the overwhelming majority of what the model processes is plumbing, not judgment.

We measured our own version of this. In the Reelier benchmark, the agent arm — a real model doing a small two-step npm metadata lookup, live — averaged 18,390 input tokens per run at $0.019068 per run. The task never changed between runs. Run that nightly and it's roughly 550k input tokens a month (30 × the measured average — arithmetic, not a new measurement) for a workflow that was identical every single night. Scale the schedule up to heartbeat frequencies and the multiplier does the rest.

Per run, it's noise. On a cron, it's a subscription to re-deriving the same answer.

Record once. Replay the part that never changes.

The alternative loop is: record → compile → replay → diff.

Fig. 1Record once, replay the part that never changes
recordtool calls capturedcompileSKILL.md + assertionsreplayLevel 0 · 0 tokensdiffSAME / DRIFTED0 tokens✓ SAMEelse DRIFTED → exit 1

Record captures the real tool calls once. Every subsequent run replays them at Level 0 (0 tokens), emits a receipt, and diffs the result. Drift fails loudly. Source: the reelier benchmark.

  1. Record the agent run that worked, once. Reelier captures the actual tool calls — requests, responses, ordering — into a trace.
  2. Compile the trace into a skill: a markdown file in your repo. Typed JSON in, typed JSON out, an assertion on every step. It's reviewable like code, because it is code.
  3. Replay with reelier run at Level 0: no model call at all. 0 tokens by construction — the skill re-executes the recorded tool calls and checks each assertion.
  4. Diff with reelier diff: SAME or DRIFTED, per step. Exit code 1 on drift, with the failing assertion printed.

Two honest boundaries, stated plainly because they're the whole design:

Replay covers the deterministic core, not the judgment. Fetch-extract-assert workflows — status checks, metrics pulls, feed diffs — replay perfectly. Triage, synthesis, writing prose: those genuinely need a model every run, and replay is the wrong tool for them. Most scheduled jobs are a deterministic core wrapped in a thin layer of judgment; replay the core, spend tokens only on the layer. Escalation to a model (--max-level 1|2) is opt-in and BYOK — Level 0, the default, never calls one.

Drift fails loudly. That is the feature. When an upstream API changes shape, the replay does not improvise around it the way an agent quietly would. The assertion fails, diff prints which step and why, and the job exits 1. A scheduled agent that silently adapts to a changed API is a schedule you can't audit; a replay that goes red with a named failing assertion is a regression test.

The measured numbers

From the published head-to-head benchmark — same task, same live data, full methodology and raw tables in examples/benchmark:

Agent re-run Reelier replay
Tokens per run 18,390 in / 136 out (avg) 0 / 0 — verified from the run record, not assumed
Cost per run $0.019068 (avg) $0.000000
Latency per run 2,842 ms (avg) 48 ms (avg), ~59× faster
Output stability no structural guarantee 1,000 / 1,000 byte-identical (N=1000 tail-variance test)

Notes that matter, because "measured" has to mean something:

  • The 0-tokens claim is asserted from each replay's run record (llmInputTokens === 0 && llmOutputTokens === 0) on every one of the 1,000 replays — checked programmatically, not eyeballed.
  • Replay latency varies with your network (Level-0 replay re-executes real tool calls). What doesn't vary: 0 tokens, the same steps, the receipt.
  • Honesty note from the benchmark itself: in the N=1000 sample, the agent arm produced no wrong outputs on this task. The claim here is cost, speed, and a byte-identical guarantee by construction — not an observed model-drift rate. We report what we measured.

Independently, arXiv 2605.14237 studied the same record-and-replay pattern for periodic agent tasks — record the tool calls once, replay deterministically without invoking the LLM — and reports monthly token reductions of 93.3%–99.98%. Different team, different implementation, same shape of result.

A worked recipe: cron + replay + exit-1 gate

Take the nightly check you'd otherwise hand to a scheduled agent, record it once with a real agent, and commit two files: the compiled nightly-check.skill.md and the recorded baseline run record .reelier/runs/nightly-check.jsonl. The baseline matters — reelier diff compares the last two runs in that file, so a fresh CI checkout needs the committed baseline plus the replay it just wrote. Skip it and every run fails with a run-count error instead of a drift verdict. Then put this in .github/workflows/nightly-check.yml:

yaml
name: nightly-check
on:
  schedule:
    - cron: "0 6 * * *" # nightly, 06:00 UTC
  workflow_dispatch: {}

jobs:
  replay:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22

      # Level-0 replay: no model call, so no LLM key in this workflow.
      - name: Replay the recorded workflow
        run: npx -y reelier run nightly-check.skill.md

      # SAME or DRIFTED, per step. Exits 1 on drift -> the job goes red.
      - name: Gate on drift
        run: npx -y reelier diff nightly-check

What to notice:

  • No LLM key anywhere in the workflow. If the recorded tool calls hit authenticated APIs, those credentials still come from your repo secrets as usual — what's absent is the model. Nightly runs cost 0 tokens against any plan, cap, or invoice.
  • The cron is the same one you'd give a scheduled agent. You're not giving up the schedule; you're swapping what runs on it.
  • reelier diff exits 1 on drift, so the failure mode is a red workflow run naming the step and the failing assertion — the morning the upstream API changes, you find out from CI, not from a quietly wrong report.
  • The committed baseline is what the diff runs against. Each night's checkout starts from the baseline .reelier/runs/nightly-check.jsonl you committed; the replay step appends tonight's run, and the diff compares the two. That keeps the comparison anchored to the run you reviewed, not to whatever happened last night.

The pattern composes with the substrates above rather than replacing them: keep the routine or heartbeat for the judgment work, and let it call the replay for the deterministic core instead of re-deriving it (reelier serve exposes exactly this over MCP).

Run your own numbers

Your schedule, your token prices, your run count: the agent cost calculator does the arithmetic for re-run vs. record-once-replay-forever. For the heartbeat-specific version of this math — 48 turns a day is its own story — see What OpenClaw heartbeats actually cost.

Or skip the arithmetic and check the receipt:

sh
npm i -g reelier && reelier init

60 seconds: record → compile → replay → your first receipt. Docs · GitHub