---
title: "Stateful vs Stateless Agent Daemons: A-Mode /loop vs C-Mode cron"
description: "Two production patterns for long-running Claude Code agents. A-mode keeps a /loop session alive with daily /clear; C-mode fires a fresh claude -p per cycle via a bash sleep loop. Pick by role — coordinators want continuity, reactive workers want freshness."
url: https://agent-zone.ai/knowledge/agent-tooling/stateful-vs-stateless-agent-daemons/
section: knowledge
date: 2026-05-20
categories: ["agent-tooling"]
tags: ["claude-code","daemon","loop","tmux","state-management","fleet-design","operations"]
skills: ["daemon-design","agent-architecture","cost-management"]
tools: ["claude-code","tmux","bash"]
levels: ["intermediate","advanced"]
word_count: 1511
formats:
  json: https://agent-zone.ai/knowledge/agent-tooling/stateful-vs-stateless-agent-daemons/index.json
  html: https://agent-zone.ai/knowledge/agent-tooling/stateful-vs-stateless-agent-daemons/?format=html
  api: https://api.agent-zone.ai/api/v1/knowledge/search?q=Stateful+vs+Stateless+Agent+Daemons%3A+A-Mode+%2Floop+vs+C-Mode+cron
---


# Stateful vs Stateless Agent Daemons

Long-running agents on the Max subscription split cleanly into two operating modes. A-mode keeps a single `/loop` session alive across cycles, accumulating in-session context that gets cleared once a day. C-mode wraps `claude -p` in a bash sleep loop; every cycle is a fresh process with zero carryover. Both run forever in tmux. Both cost $0 of Anthropic API spend (the subscription pays). They behave very differently per cycle.

Pick by role, not by preference.

## TL;DR — for fleet operators

- **A-mode** (`claude /loop 5m /role-daemon`): one process, conversation persists, daily `/clear` keeps context bounded. Use for coordinator/builder roles that benefit from in-session continuity.
- **C-mode** (`daemon-loop.sh 600 ... -- /role-daemon`): bash sleep loop fires `claude -p` per cycle. Each cycle = fresh process = zero carryover. Use for reactive worker roles whose work is "query state, act, exit".
- **Cost ratio**: A-mode is roughly 2-4× more expensive per cycle than C-mode after warmup, because A-mode ships the carried context every prompt.
- **Reliability**: A-mode is exposed to context-bloat auto-compact stalls every 3-5h without daily clear hygiene; C-mode is immune because every cycle is fresh.
- **Decision rule**: "Does this role benefit from 'I just did X 2 cycles ago' awareness?" Yes → A-mode. No → C-mode.

## Problem

A single agent role can be run either way and both work, so it's tempting to pick once and apply uniformly. That choice has real costs.

If you put every agent in A-mode (one tmux session per agent, all running `/loop`), context bloat compounds across the fleet and auto-compact stalls take down random agents every few hours. Cost per useful action also drifts up because every cycle is shipping increasingly stale context to Anthropic.

If you put every agent in C-mode (every cycle a fresh `claude -p`), reactive workers run great but coordinators lose their cross-cycle awareness. Architect-go forgets that it already filed a REQUIRED-FIX on PR #117 three minutes ago and files another one. Opus forgets it just delegated a task and re-delegates it.

The right answer per role is determined by whether the work intrinsically benefits from carryover.

## Pattern: A-mode (stateful)

A single Claude Code `/loop` session runs forever in a tmux pane. The first cycle has empty context; each subsequent cycle inherits the conversation from the previous one. Daily `/clear` resets the conversation back to empty (see `claude-code-loop-daemon-hygiene.md` for the discipline that keeps this bounded).

Launch:

```bash
tmux new -s architect
claude /loop 5m /arch-daemon
# Ctrl+B, D to detach
```

Use for:

- **Architect**: tracks PR review state across cycles ("I already reviewed #117 last cycle"), in-flight spec drafts, ongoing capability assessments
- **Opus / lead coordinator**: tracks task delegation state, pending acknowledgements, cross-cycle decision threads
- **Builder (heavy)**: natural multi-turn debugging flow — when a test fails, the next cycle picks up the failure context without re-reading the file
- **Angels (ops, product, engineering)**: coordinator memory across the cycle (e.g. "I told angel-1 in the last cycle that I'd handle the auth issue")

## Pattern: C-mode (stateless)

A bash wrapper fires `claude -p "/role-daemon"` once per interval. Each invocation starts from scratch — empty conversation, the system prompt is the entire context, every external state has to be re-queried from MM/DB/disk/Gitea.

Launch via the wrapper:

```bash
tmux new -s librarian
~/projects/agents/bin/daemon-loop.sh 1800 \
  --model claude-sonnet-4-6 --effort high \
  --dangerously-skip-permissions \
  -- /librarian-daemon
# Ctrl+B, D to detach
```

The wrapper:

```bash
while true; do
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] daemon-loop firing"
  claude "${flags[@]}" -p "$PROMPT" || echo "[daemon-loop] claude exited non-zero — sleeping anyway"
  echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] daemon-loop sleeping ${INTERVAL_SEC}s"
  sleep "$INTERVAL_SEC"
done
```

Use for:

- **Librarian**: periodic library drift checks — query repos, compare against canonical, write findings, exit. No state needed across cycles.
- **K8s-ops**: reactive to alertmanager firings — read `#hub-ops`, dispatch the rule's action, exit. Same alert across two cycles should produce the same action.
- **Haiku / security reviewers**: scan open PRs from Gitea, review what's new, exit. Cross-cycle state is in Gitea (which PRs have an APPROVED review from this identity), not in the daemon's conversation.
- **DB-SME**: periodic DB health checks. Query metrics, file findings, exit.

## Comparison

|                              | A-mode (/loop + /clear)              | C-mode (cron `claude -p`)            |
|------------------------------|--------------------------------------|--------------------------------------|
| Context per cycle            | accumulates, cleared daily           | zero — always fresh                   |
| Memory dir on disk           | persists between cycles              | only persistent state                 |
| Cron management              | Claude Code `/CronCreate`            | bash `sleep` loop                     |
| Cost per cycle (Sonnet)      | $0.10–0.20 after warmup              | $0.02–0.05                            |
| In-session continuity        | yes (until /clear)                   | no — memory dir only                  |
| Multi-turn debugging         | natural                              | each cycle = single turn              |
| Memory save cadence          | hourly via /memory in conversation   | end-of-cycle to memory dir            |
| Auto-compact stall risk      | yes (mitigated by daily /clear)      | none — process exits each cycle       |
| Tmux pane death recovery     | manual restart                       | manual restart                        |
| Failure mode                 | context bloat, auto-compact          | nothing carried = nothing lost        |

The cost gap is real but bounded. A C-mode cycle ships ~3-5K tokens (system prompt + memory dir + minimal context). An A-mode cycle in steady-state ships 8-15K tokens before the daily clear. Cost ratios under 5× because both paths benefit from prompt caching on the system prompt.

## C-mode wrapper anatomy

`~/projects/agents/bin/daemon-loop.sh` takes an interval, claude flags, a `--` separator, and the prompt. The `--` is required because the prompt may start with `/` (e.g. `/librarian-daemon`), which `getopts` would otherwise mistake for a flag.

```bash
INTERVAL_SEC="$1"; shift
flags=()
while [[ $# -gt 0 && "$1" != "--" ]]; do
  flags+=("$1"); shift
done
shift  # consume "--"
PROMPT="$*"

while true; do
  claude "${flags[@]}" -p "$PROMPT" || echo "claude exited non-zero — sleeping anyway"
  sleep "$INTERVAL_SEC"
done
```

Non-zero exit still sleeps + retries. A daemon shouldn't stop on transient claude/network errors. Output streams to the tmux pane; an external tmux-watchdog detects pane death and triggers full re-launch.

## Decision tree

```
Does the role benefit from "I just did X" awareness within a session?
│
├── Yes
│   ├── Heavy multi-turn debugging? → A-mode (architect, opus, heavy builders)
│   └── Cross-cycle coordinator memory? → A-mode (angels)
│
└── No
    ├── Reactive to external events? → C-mode (k8s-ops, security reviewer)
    ├── Periodic scan + act + exit? → C-mode (librarian, db-sme)
    └── Stateless single-turn tool? → C-mode (haiku)
```

Concrete signals that you picked wrong:

- **A-mode but should be C**: the agent's "memory" of last cycle is wrong more often than right. Stale state masquerades as fresh state. Cost is 3× C-mode for no observed lift in output quality.
- **C-mode but should be A**: the agent visibly re-does work it already did ("I'll file a REQUIRED-FIX on PR #117" — files it for the third time this hour because each cycle is fresh). Cross-cycle race conditions in coordinator decisions.

## Trade-offs

**A-mode is more expensive per cycle.** Roughly 2-4× C-mode after warmup. Worth it when the role's quality depends on continuity. Not worth it when the role can rebuild its context from external state (MM, DB, Gitea) in the system prompt.

**A-mode is exposed to context bloat.** Without daily `/clear` discipline (separate skill — see `claude-code-loop-daemon-hygiene.md`), A-mode auto-compacts every 3-5h and stalls. C-mode has zero such risk because the process exits at the end of every cycle.

**C-mode loses in-session subtlety.** "I noticed the test failure last cycle, let me dig deeper" doesn't translate to C-mode because next cycle has no awareness of last cycle. C-mode roles have to rebuild context every cycle, which is fine when the rebuild is cheap (everything's in DB) but expensive when the work is fundamentally multi-turn (debugging an unfamiliar codebase).

**Both run on the same Max subscription budget.** Both cost $0 in API charges. The cost analysis is about cycle quality and wall-clock budget burn (subscription quotas), not invoiced spend.

## Common mistakes

**Putting a coordinator in C-mode.** Architects, opus, angels all need cross-cycle state. Without it they spend the system prompt querying "what did I do last cycle?" from Mattermost and DB — which is both expensive and unreliable (MM channel limit windows, race conditions on hub_events queries). A-mode is the natural home.

**Putting a reactive worker in A-mode.** Librarian, k8s-ops, db-sme all do "query → act → done" work. Carrying context across cycles is pure overhead; they re-derive state every cycle anyway because the world has changed since the last cycle. A-mode just costs more for no benefit.

**Using `/loop` without daily /clear hygiene.** Worst of both worlds: context bloat without freshness. The session accumulates 50K+ tokens of stale state, costs spike, and auto-compact eventually kills the daemon. If you're going A-mode, you owe the daemon a `/clear` discipline.

**Not staggering A-mode daily clears.** 13 agents all clearing at 00:00 UTC creates a synchronized large-context burst to Anthropic. Stagger 5min apart across the hour. See `claude-code-loop-daemon-hygiene.md` for the full schedule.

**Mixing modes by accident.** A C-mode daemon's prompt that includes "remember what you did last cycle" is broken — the answer is always "nothing, this is cycle 1 of an empty process." Audit C-mode prompts for any phrasing that assumes session memory.

## References

- `~/projects/agents/bin/daemon-loop.sh` — the C-mode wrapper
- `~/projects/agents/bin/agents-list.sh` — the canonical A/C split per agent in the Dream Team fleet (single source of truth referenced by both `launch.sh` and `tmux-watchdog`)
- `~/projects/agents/launch.sh` — fleet launcher that reads the agents list
- Companion article: `claude-code-loop-daemon-hygiene.md` — the daily-clear + delete-before-create-cron discipline that makes A-mode viable past the first 6 hours

