One user/business intent with pinned workflow/context/policy/budget. It may have many attempts but one terminal business outcome.
Before the clock
A long agent is a durable workflow—not a long HTTP request.
The browser streams progress but owns nothing. Durable control state, pinned context, budget, leases, checkpoints, approvals, cancellation epoch, and side-effect receipts outlive workers, providers, clients, and regions.
A particular worker execution under a time-bounded lease and monotonic epoch. Attempts are disposable and fenced.
Versioned recoverable workflow state at a safe logical boundary; not an opaque dump of mutable process memory.
Durable intent/result record around an external side effect, keyed so timeout can be reconciled before retry.
Opening promptDesign Runway Control, a multi-tenant durable scheduler for coding agents, subagents, scheduled automations, approval gates, model calls, tests, and external tools. Jobs run for seconds to twelve hours and must survive client/worker/region failure while respecting dependencies, quotas, fairness, cancellation, and ambiguous side effects.
Define logical ownership first
Assume 100,000 runs/day, 10,000 concurrent at peak, 20 steps/run, and workflows that can spawn subagents. Design the full application.
I will separate the workflow authority from disposable execution. A logical run pins tenant/project, workflow version, context manifest, capability profile, budget, priority, and cancellation epoch. Each ready step may have attempts; a scheduler issues a fenced lease. Workers heartbeat, checkpoint, and request model/tool operations through gateways that validate the current run/lease/cancellation state.
I need to clarify DAG expressiveness, dynamic fan-out, maximum recursion, step determinism, checkpoint contract, approval semantics, external-effect risk, ordering, deadlines, tenant priority classes, model/tool quotas, regional/residency constraints, and whether a provider change is allowed. I will optimize useful accepted outcomes—not worker utilization alone.
Actors, states, and boundaries
What functional and nonfunctional requirements do you choose?
Actors are user, project admin, automation owner, agent/subagent, reviewer, scheduler operator, model/tool provider, and auditor. Functional flows: define/version workflow DAG; launch idempotently; compute readiness; reserve quota/budget; run/pause/resume/cancel; spawn bounded subagents; checkpoint; wait for event/time/human approval; stream progress; retry infrastructure failures; reconcile external effects; collect artifacts; and export run lineage.
NFRs: P95 interactive start under 10 seconds when capacity exists, cancellation visible under two seconds and enforced at the next effect boundary, 99.95% control-plane availability, no lost accepted run, 30-second failover detection, tenant fairness, region/residency, and seven-year audit for consequential effects. The scheduler does not implement foundation models, Git providers, or test runners; they are capability-gated adapters.
State transitions need fences
What must never happen?
- Retrying launch returns one logical run and one initial budget reservation.
- Only the current run/step state version and lease epoch may commit progress, checkpoint, or invoke a privileged effect.
- DAG readiness requires every configured predecessor condition; cycles and unbounded dynamic expansion are rejected.
- A checkpoint names exact workflow/context/tool/model artifact versions and the last completed logical boundary.
- Cancellation increments a monotonic epoch checked before model/tool calls and checkpoint commit; terminal cancellation cannot be resurrected.
- External effects are not “exactly once” by messaging claim: intent precedes call, receipt follows, unknown outcomes reconcile.
- Subagents inherit an intersection of parent capabilities and a bounded slice of parent budget/depth/fan-out.
- One tenant’s migration flood cannot consume every interactive slot or provider quota.
The metadata load is modest; state volume is not
Estimate scheduler traffic and checkpoint volume.
Ten thousand active attempts heartbeating every 20 seconds produce 500 heartbeats/s. At 512 KB checkpoints every two minutes, peak ingress is ~42.7 MB/s decimal (about 41.7 MiB/s) and 3.69 TB/day if retained uncompressed—so we checkpoint at logical boundaries, delta/compress, keep latest plus policy milestones, and compact successful runs.
One hundred thousand runs × 20 steps is two million step executions/day, only 23 starts/s average, but fan-out and tenant bursts dominate. If average run duration is 45 minutes, Little’s Law gives ~3,125 average concurrent runs; 10,000 peak is plausible. Queue partitions, provider quotas, long-held approvals, and checkpoint storage—not raw CRUD QPS—drive the design.
checkpoint MB/s = 10,000 × 512 KB ÷ 120 s ÷ 1,000 = 42.7 MB/s
raw checkpoint/day = 42.7 MB/s × 86,400 ≈ 3.69 TB/day
Scheduler control-load lab
Move heartbeat and checkpoint assumptions; watch durability cost.
The raw checkpoint estimate intentionally exposes why delta/checkpoint policy, compaction, retention, and tenant skew matter.
Model workflow, step, and attempt independently
Show the core schema and APIs. How do transitions stay safe?
WorkflowVersion contains a validated DAG and step contracts. Run owns logical intent and monotonic state/cancellation versions. StepRun owns readiness, dependencies, policy, and accepted result. Attempt owns worker, lease epoch/expiry, heartbeat, and failure. Checkpoint owns content digest and resume cursor. EffectIntent, ApprovalGate, BudgetReservation, and SubagentLink keep hard boundaries explicit.
Every command uses idempotency plus expected state version. Claim uses atomic compare-and-set from READY to LEASED with a new epoch. Heartbeat/commit requires run, step, attempt, lease epoch, and cancellation epoch. A transaction changes authoritative state and writes an outbox event; UI streams and search are projections.
A small control plane directs a noisy execution plane
Walk an eight-hour coding agent with two subagents and a human approval gate.
Launch validates workflow/context, reserves parent budget and tenant concurrency, stores Run + initial ready steps + outbox, then returns. The readiness service consumes terminal step events and transactionally enqueues newly satisfied steps. Hierarchical queues classify interactive, automation, migration, and approval-resume work. A scheduler selects by tenant fair share and capability/resource needs, then leases an attempt.
The isolated worker restores a signed checkpoint and fetches only manifest-authorized context. Model/tool gateways enforce run/lease/cancel epochs, data policy, budget, and capability. Spawning a subagent is an authoritative command that checks depth/fan-out and carves a child budget/capability intersection; the parent waits on an explicit join policy. Before a PR/deploy/tool write, the workflow creates an approval task. The reviewer’s signed decision wakes the step or cancels it. Progress streams can fail while durable work continues.
Ready does not mean schedulable
One customer submits 50,000 migration runs. Another needs interactive agents to start in ten seconds. How do DAG readiness and fair scheduling work?
Readiness is a deterministic projection from completed predecessor conditions, workflow version, approvals, cancellation, and artifacts. It produces a ReadyTicket containing tenant, project, class, deadline, resource/capability needs, estimated cost, and enqueue time. It does not reserve a worker indefinitely while waiting for provider quota.
Scheduling is hierarchical: reserved interactive capacity, then tenant weighted fair share, then project/user quotas, priority/deadline, and aging. Migration has a concurrency cap and can use otherwise idle capacity but is preemptible only at checkpoints—not arbitrary process kill. Separate token buckets protect model/provider/tool rate limits. Dominant-resource fairness can account for CPU, memory, model tokens, scarce licensed tools, and regional pools.
Admission controls dynamic DAG expansion: max child count, depth, total steps, estimated token/tool budget, and tenant active-descendant quota. The parent cannot recursively manufacture priority. Metrics include queue age and slowdown by tenant/class, starvation count, and useful completion—not only fleet utilization.
Lease, checkpoint, retry, reconcile
A worker dies after opening a pull request but before recording success. Another worker retries. What exactly happens?
Before the tool call, the gateway transactionally records EffectIntent(effect_key=run/step/pr/repo/branch, REQUESTED) under the current lease/cancel epochs. It passes the key/correlation to the SCM connector. The provider creates PR 184, but response is lost. The worker dies; its lease expires.
A new attempt restores the last checkpoint and sees a REQUESTED effect without receipt. It queries the provider by idempotency/correlation/branch-head. If PR 184 exists with matching request hash, it records OBSERVED and continues. If no lookup exists, the step enters NEEDS_RECONCILIATION for a human rather than opening another PR. A late zombie worker cannot commit because its lease epoch is stale.
Checkpoint state contains completed logical step cursor, artifact digests, conversation/tool summaries needed to resume, pending effect IDs, and provider/model configuration—not raw process memory or hidden model chain-of-thought. Provider failover creates a new attempt/config record and may require re-evaluation or approval.
Cancellation races a privileged action
The user cancels just as the agent starts a deployment. The browser shows canceled, but the worker is partitioned. How do you make cancellation real?
The cancel command transactionally increments run.cancellation_epoch, changes logical state to CANCEL_REQUESTED, appends outbox, and returns. The UI is explicit: requested versus enforced. Workers subscribe, but correctness does not depend on delivery. Every privileged gateway call and checkpoint commit includes the epoch and is rejected if stale; long operations receive cancellation tokens where providers support them.
If the deployment request was recorded before cancel, effect policy decides whether to let it finish, issue compensation/rollback, or pause for reconciliation. Cancellation cannot erase an external effect. The run reaches CANCELED only when active leases are fenced/expired and all effect intents are terminal or explicitly reconciled. Child runs inherit cancellation unless marked independent by approved workflow policy.
CANCEL_REQUESTED is not CANCELED. Show active effect and enforcement progress.
Monotonic cancellation epoch checked at model/tool gateway and checkpoint commit, not only pushed to worker.
Observe, compensate, rollback, or reconcile deployment. Cancellation does not time-travel.
A region fails with 4,000 active attempts
The scheduler region loses network after issuing leases. A standby region starts. Prevent split brain and restore work.
Each scheduler shard has one consensus-backed authority epoch. Failover requires quorum and increments the shard epoch. New leases contain the new shard+lease epoch; model/tool gateways and checkpoint commits reject old-region epochs even if workers keep running. We prefer a write pause over dual authority.
Run/step/effect records replicate with an RPO appropriate to side effects—effect intent must be durable before external call. Checkpoint objects are cross-zone and, where residency allows, asynchronously cross-region. The standby waits for old leases to expire or explicitly fences them, rebuilds ready/leased projections from authoritative state, reconciles in-flight effects, and requeues from latest valid checkpoints. Progress streams and noncritical analytics may be unavailable.
Recovery metrics include fenced-zombie rejections, duplicate attempts, checkpoint loss window, unknown effects, time to useful completion, and tenant fairness after backlog—not merely control-plane HTTP uptime.
Subagents cannot mint authority
How do you isolate tenants, secrets, prompts, tools, and runaway subagents?
Workers are ephemeral, tenant/project/run scoped, without ambient cloud credentials. Context retrieval and every model/tool call pass through policy; retrieved code/doc text is untrusted data, never capability. Secrets are exchanged just-in-time for exact tool/action/resource and are not checkpointed. Sandboxes enforce filesystem, network egress, process, CPU, memory, disk, and time limits.
Subagent creation intersects parent capabilities, restricts source context, allocates child budget, and increments depth/fan-out counters transactionally. A child cannot choose its own tenant/project or promote priority. Tenant IDs and data classes propagate through queue records, object keys, logs, metrics, model caches, and artifacts. Audit records observable inputs/config/tool calls/outputs/approvals—never claims hidden reasoning as reliable evidence.
Measure useful completion under failure
What metrics, chaos tests, and rollout gates do you use?
Health: launch/readiness latency, queue age/slowdown by tenant/class, lease acquisition/expiry, heartbeat load, checkpoint latency/bytes/recovery, zombie rejection, cancellation enforcement, unknown effect rate, provider/tool saturation, budget variance, recursion rejection, and regional failover RTO/RPO. Quality: accepted artifact rate, test/approval pass, retries per accepted outcome, cost and wall time, human reconciliation burden, escaped defects, and fairness.
Rollout begins with short idempotent read-only steps, then checkpoint/retry without external effects, then safe idempotent tools, then approved consequential writes, then multi-region failover. Fault injection kills workers, drops heartbeat/response messages, delays queues, corrupts checkpoints, duplicates events, exhausts providers, races cancel, and partitions scheduler authority. Every phase has per-tenant kill switch and drain mode.
Land the plane
Summarize your design and the hardest trade-off.
Runway Control stores one durable logical run with pinned workflow/context/policy/budget and many fenced step attempts. DAG readiness creates tickets; hierarchical multi-resource fair queues choose work. Workers restore versioned checkpoints, while model/tool gateways enforce current lease and cancellation epochs. Subagents inherit narrower capabilities and bounded budget.
External effects use intent, idempotency/correlation, receipt, and reconciliation; no exactly-once fiction. Regional failover increments authority epochs so zombies cannot act. The trade-off is checkpoint frequency versus cost/recovery: checkpoint at meaningful boundaries with compaction, and accept bounded rework while never replaying an unknown harmful effect blindly.
Complete reference
Data model: keys, invariants, access paths
| Entity | Primary key / fields | Invariant | Primary access path |
|---|---|---|---|
WorkflowVersion | (tenant_id, workflow_id, version); DAG, step contracts, policies, limits | Immutable after use; cycle/resource validation before publish | Launch; audit; replay |
Run | (tenant_id, run_id); workflow/context, state_version, cancellation_epoch, budget, priority | One logical intent; monotonic transitions; one terminal outcome | Status, cancel, lineage |
StepRun | (run_id, step_id, expansion_path); dependency state, accepted result, policy | Ready only when predecessor/join conditions satisfied | Readiness; UI DAG; retry |
Attempt | (run_id, step_id, attempt_no); worker, lease_epoch, shard_epoch, expiry, heartbeat | Only current fenced attempt may commit/call privileged gateway | Claim, heartbeat, recovery |
Checkpoint | (attempt_id, checkpoint_seq); content digest, cursor, manifests, pending effects | Immutable, schema-versioned, authorized, resume-tested | Restore after failure; audit milestones |
EffectIntent | (tenant_id, effect_key); request hash, state, external correlation, receipt | Intent committed before call; UNKNOWN never blindly retried | Tool recovery; reconciliation |
ApprovalGate | (run_id, gate_id, version); required roles, decision, evidence, expiry | Decision append/expected version; exact run context | Pause/resume/deny |
SubagentLink | (parent_run, child_run); depth, budget allocation, capability digest, join policy | Child authority and budget are subsets of parent/policy | Recursive status; cancel; fairness |
Concrete API surface
/v1/runsWorkflow/context/budget/capability + Idempotency-Key → one logical durable run./v1/runs/{id}:cancelExpected state version; increments cancellation epoch; returns requested/enforced status./v1/runs/{id}/events?cursor=Resumable progress stream from durable event log; disconnect does not affect run./internal/ready-tickets/{id}:claimScheduler shard/lease epoch + worker attestation; atomic READY→LEASED./internal/attempts/{id}:heartbeatLease epoch, cancellation epoch, progress cursor, resource counters./internal/attempts/{id}/checkpointsExpected epochs + content digest + logical cursor; stale attempts rejected./internal/runs/{id}/subagentsParent lease + child workflow/budget/context request; enforced depth/fan-out/capability intersection./internal/effects/{effect_key}:invokeCommit intent, enforce epochs/capability/budget, call adapter, store receipt/UNKNOWN.Durable agent scheduling architecture
The authority plane owns intent and transitions. Ready tickets flow through fair queues. Ephemeral workers act only through fenced model/tool gateways.
Attempt failure is not logical failure
Leases and checkpoints permit retry; approvals, unknown side effects, and cancellation create explicit durable states.
Consistency ledger
Operational scorecard
Platform health
Outcome quality
Visual values are illustrative. In production, every metric needs a unit, time window, tenant/slice dimension, owner, alert threshold, and prescribed action.
Phased rollout
Read-only steps
Short deterministic work; validate launch idempotency, queues, leases, cancellation, and tenancy.
Checkpoint retry
Kill workers and resume model/test work without external side effects.
Safe tools
Idempotent reads/writes with effect receipts, rate limits, and reconciliation.
Consequential work
Human gates, multi-region fencing, chaos drills, bounded subagents, per-tenant kill switches.
Interview traps
- 01Treating an eight-hour agent as one HTTP request or binding it to the user laptop.
- 02Conflating logical run with worker attempt and marking the run failed on one node loss.
- 03Using lease expiry without epoch fencing, allowing zombie commits or tool calls.
- 04Blindly retrying an external effect whose outcome is unknown.
- 05Saying “exactly once” without business idempotency, receipts, lookup, or reconciliation.
- 06Using one FIFO/priority queue and letting migration work starve interactive tenants.
- 07Allowing subagents to inherit all secrets, mint priority, or create unbounded descendants.
- 08Stopping at cancel request without enforcing epochs at privileged boundaries.
- 09Checkpointing opaque process/model memory with secrets and no artifact/version manifest.
- 10Measuring worker utilization instead of useful accepted outcomes, fairness, and reconciliation burden.
Glossary
- Cancellation epoch
- Monotonic version invalidating old workers/calls after a cancel request.
- Checkpoint
- Durable, versioned resume state at a known logical boundary.
- DAG
- Directed acyclic graph of step dependencies; dynamic expansion still needs cycle and size limits.
- Dominant-resource fairness
- Scheduling based on each tenant’s largest share of scarce resources such as CPU, memory, or model quota.
- Fencing token
- Monotonic epoch required at commit/effect time so an old lease holder is rejected.
- Heartbeat
- Periodic proof of liveness/progress; absence triggers lease recovery but is not proof the worker stopped.
- Lease
- Time-bounded exclusive right for one attempt to advance a step under an epoch.
- Little’s Law
- Average in-flight work L equals arrival rate λ times average time W; useful for concurrency estimates.
- Outbox
- Transactional record that authoritative state changed and asynchronous consumers must act.
- Reconciliation
- Domain-specific lookup/human process for an external effect with unknown outcome.
- Ready ticket
- Schedulable description produced when dependencies and gates are satisfied; not itself a worker reservation.
- Subagent budget
- Explicit carved-out limits for child depth, fan-out, tokens, tools, time, and capabilities.
One-minute spoken recap
Run ≠ attempt. The transactional control plane owns one logical run, versioned DAG steps, budget, approvals, and monotonic cancellation state. Ready tickets enter hierarchical fair queues; schedulers issue fenced leases. Ephemeral workers restore checkpoints and can only call model/tool gateways with current epochs. Effects: intent → call → receipt, with UNKNOWN reconciliation. Recovery: new shard epoch blocks zombies; retries resume from safe checkpoints. Safety: subagents inherit narrower context, capability, budget, and priority.