Engineering the Agentic Stack · Deel 5

Long-Running AI Agent Runtime: Sessions and Checkpoints

Automatische vertaling Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.

Een agent run kan uren duren, terwijl het workerproces op elk moment kan herstarten. Het model kiest nog steeds de volgende actie, maar de runtime moet de state behouden, de uitvoering aansturen en herstellen van een failure midden in een tool call. In deze post definiëren we de runtimegrens. Deel 6 opent vervolgens het component daarbinnen dat beslist — de harness, de plek waar memory, tool-contracten en permission checks ophouden drie onderwerpen te zijn en één programma worden.

Wat is een AI agent runtime?

Een AI agent runtime is de infrastructuurlaag die een tool-using agent actief, geïsoleerd, observable en hervatbaar houdt nadat de model call is afgelopen. De runtime beheert session state, tool execution, checkpoints, secrets, traces, cost limits en de deploymentvorm. Het model kiest de volgende actie; de runtime bepaalt waar die actie wordt uitgevoerd, hoe ze wordt vastgelegd en hoe de run na een failure wordt hervat. De harness beslist of de actie is toegestaan. De harness is geen storage layer; het is het programma dat op deze onderdelen steunt, en daarom staat het ook in de tabel hieronder: je moet het eveneens plaatsen.

Te plaatsen primitiveProduction jobVeelgebruikte implementatie
SessionDe run log behouden na process restartsAppend-only event log, thread ID, conversation store
HarnessModel/tool turns aansturen tot de task klaar isLangGraph graph, Agents SDK runner, custom loop
SandboxCode, files, network en tools isolerenHardened container, VM, browser sandbox, managed workspace
CheckpointHervatten zonder de hele run te replayenPostgres, Redis, durable workflow state
TraceLong runs achteraf debuggen en auditenOpenTelemetry spans, LangSmith, vendor traces

Vier van deze vijf — session, sandbox, checkpoint en trace — slaan state op of beperken de uitvoering. De harness is het onderdeel dat beslist; daar komen alle beslissingen over memory, tool-contracten en permissions samen. Dit artikel behandelt de harness als één box en beschrijft waarop die steunt. Deel 6 opent de box en ordent dezelfde vijf opnieuw in het ene component dat beslist en de vier waarop het draait.


Long runs doorbreken stateless-aannames over processen

Een stateless chat endpoint kan request state in één proces bijhouden en die na de response weggooien. Een long agent run loopt echter over worker restarts, deploys, context resets en approval pauses heen. Het workerproces kan niet langer de source of truth zijn.

Het OpenAI Codex-team beschrijft hoe lang deze runs worden in zijn harness engineering write-up:

“We regularly see single Codex runs work on a single task for upwards of six hours (often while the humans are sleeping).”

Het engineeringteam van Anthropic beschrijft het bijbehorende state-probleem in Effective harnesses for long-running agents:

“The core challenge of long-running agents is that they must work in discrete sessions, and each new session begins with no memory of what came before.”

Beide observaties wijzen op hetzelfde runtime-design: persist state buiten de worker en maak workers vervangbaar.

De session moet buiten het workerproces leven. Een durable store registreert model calls, tool results en approvals, zodat een andere worker na een crash vanaf het laatste veilige punt kan hervatten. Checkpoints maken het bovendien mogelijk om een nieuwe model session te starten wanneer het context window vol raakt, zonder de volledige history opnieuw af te spelen. In Anthropic’s formulering worden harness-instanties disposable en restartable; durable state leeft elders.


Plaats vijf primitives voordat je shipt

Anthropic’s Scaling Managed Agents-write-up biedt een bruikbare vocabulary voor vijf runtimeverantwoordelijkheden. De harness stuurt de agent vooruit, terwijl de session vastlegt wat de agent heeft gedaan en de sandbox commands uitvoert. Het checkpoint geeft de volgende worker een resume point; de trace bewaart evidence voor latere debugging. Een implementatie kan componenten samenvoegen, maar de verantwoordelijkheden en failure boundaries moeten nog steeds benoemd worden.

De vijf runtime-primitivesDe vijf runtime-primitives

Session. Een append-only log van alles wat er is gebeurd: model calls, tool calls, results, errors en approvals.

Het woord is overloaded, dus definieer drie spans die session worden genoemd. Een thread is de conversation van een gebruiker over meerdere dagen. Dit is de langstlevende van de drie, en LangGraph houdt die bij met een thread_id.

Een model session is het kortst: één ononderbroken periode van model context. Compaction — de stap die het window samenvat zodat het werk kan doorgaan — verlengt een model session in plaats van die te beëindigen. Een restart of een bewuste fresh start beëindigt de session. Deel 6 gebruikt “model session” in deze betekenis.

In dit artikel betekent “session” de durable log van één run. Die staat tussen de twee in: meerdere model sessions schrijven naar één log, en één thread verzamelt meerdere logs. Recovery is wake(sessionId) → getSession(id) → resume from last event.

In LangGraph gebruikt recovery een thread_id plus een Postgres checkpointer (zie LangGraph persistence). De OpenAI Agents SDK levert tien ingebouwde session backends, waaronder SQLiteSession, RedisSession, SQLAlchemySession, MongoDBSession en EncryptedSession (zie de Sessions docs).

Harness. De orchestration loop en de enige primitive hier die beslissingen neemt. De harness assembleert de prompt uit memory, roept het model aan, controleert de voorgestelde tool call aan de hand van de permission rules, dispatcht wat is toegestaan, schrijft results terug naar de session, past retry rules toe en beslist of de task klaar is. Elk van deze stappen encodeert een aanname over wat het model niet zelfstandig kan. Anthropic formuleert dat rechtstreeks — het citaat staat in de sectie over failure modes hieronder, die vooral gaat over wat er gebeurt wanneer zulke aannames verouderd raken.

Het Codex-team van OpenAI noemt dit harness engineering: software schrijven vereist nog steeds engineering effort, maar steeds meer daarvan gaat naar de scaffolding in plaats van naar de code zelf. LangGraph’s CompiledStateGraph, LangChain’s Deep Agents en het create_deep_agent-entrypoint, en Claude Code zelf zijn in deze betekenis allemaal harnesses.

Sandbox. De geïsoleerde execution environment waarin commands daadwerkelijk draaien. De pagina sandbox concepts van de OpenAI Agents SDK trekt de grens helder:

“The outer runtime still owns approvals, tracing, handoffs, and resume bookkeeping. The sandbox session owns commands, file changes, and environment isolation.”

“Outer runtime” betekent daar de harness samen met zijn state stores. In de vocabulary van deze serie zijn approvals en handoffs harness-beslissingen (Deel 4 en Deel 6); tracing en resume bookkeeping zijn de session- en checkpoint-primitives.

Sandboxes verschillen in hoelang ze blijven bestaan en wat ze tussen runs onthouden. De eenvoudigste vorm is fresh ephemeral: je start er één voor één task, vernietigt hem wanneer de task klaar is en betaalt bij elke run de cold-startkosten.

Persistent paused-sandboxes bewaren het filesystem en een memory snapshot tussen runs. De volgende resume kan een volledige boot overslaan. Snapshot or fork maakt een copy-on-write image vanuit een voorbereide parent, zodat veel tasks geïnstalleerde dependencies en warme caches delen zonder hun writable state te delen.

Per-worktree-sandboxes geven elke task een eigen workspace en observability stack. Afzonderlijke logs, metrics en traces laten je één run debuggen zonder dat state naar een andere run lekt. De providertabel verderop in dit artikel vergelijkt cold-start- en persistencegedrag.

Checkpoint. Hervatbare state.

LangGraph’s PostgresSaver schrijft bij elke super-step boundary een Checkpoint. Een super-step is één ronde van de graph: een enkele node of een batch die parallel draaide. Writes per task gaan naar checkpoint_writes, zodat succesvolle node outputs niet opnieuw worden berekend wanneer een sibling faalt.

Een checkpoint is een gewone dict (v, id, ts, channel_values, channel_versions, versions_seen, updated_channels). LangGraph serializeert die met zijn msgpack-gebaseerde JsonPlusSerializer in plaats van met JSON. datetime, set, Decimal en dataclasses kunnen allemaal round-trippen. Het format is gedocumenteerd op de langgraph-checkpoint-postgres-PyPI-pagina en in de LangGraph checkpoints reference.

StateSnapshot is de afzonderlijke, uitgebreidere view waarop graph.get_state() boven op een checkpoint bouwt. Dat is het object waarvan de .values later de debug bundle dumpt.

Trace. De replay- en debug surface. Elke model call, tool call en sub-agent step wordt een span met timing, inputs, outputs, token counts en cost. Wanneer een run van zes uur faalt, lees je de trace om te achterhalen wat er misging. De terminaloutput van de run is dan al lang verdwenen. OpenTelemetry’s GenAI semantic conventions standaardiseren de namen van attributen: welk model, welke provider, hoeveel tokens, welke conversation en welke workflow. Voor een OTLP-compatible destination die deze conventies ondersteunt, kan dezelfde instrumentation de trace exporteren naar systemen zoals Tempo, Jaeger, Honeycomb of LangSmith, hoewel backend adapters of destination-specifieke configuratie nog steeds nodig kunnen zijn.

Policy en secrets lopen door alle primitives heen

Twee boundaries lopen door alle vijf primitives heen. Ze zijn de runtimeversie van het securityargument uit Deel 4. De permission decision zelf hoort bij de harness; hieronder gaat het om waar de machinery die deze decision afdwingt en voedt fysiek zit.

Permission enforcement

De permission ladder uit Deel 4 moet ergens worden uitgevoerd. De check wordt vóór elke tool call uitgevoerd en beslist of die doorgaat. In productie komen twee patronen vaak voor. Deep Agents laat elke subagent declareren welke file paths die mag lezen of schrijven, waarna de middleware alles buiten die declaratie blokkeert. Anthropic Managed Agents routeert elke tool call via een Model Context Protocol (MCP)-proxy, zodat de proxy de permissions afdwingt in plaats van de agentcode. Wanneer voor een gevoelige call human approval nodig is, pauzeren LangGraph’s interrupt() en de approval hook van Deep Agents de graph totdat iemand akkoord geeft.

Secret broker

Het model hoort geen long-lived secrets te zien, en meestal hoort de sandbox dat evenmin. Het Managed Agents-patroon is het patroon om over te nemen:

“For Git, we use each repository’s access token to clone the repo during sandbox initialization and wire it into the local git remote. Git push and pull work from inside the sandbox without the agent ever handling the token itself. For custom tools, we support MCP and store OAuth tokens in a secure vault. Claude calls MCP tools via a dedicated proxy; this proxy takes in a token associated with the session. … The harness is never made aware of any credentials.”

In de market-analyst-agent-reference stack — een kleine LangGraph-agent die market data ophaalt en een analyst report schrijft, opgebouwd doorheen deze serie — bevat de MCP sidecar de API keys van de data provider en exposeert die alleen het tool surface aan de LangGraph-worker. In het lokale composebestand lezen beide containers dezelfde .env, wat een development shortcut is en niet het aanbevolen patroon. In productie komt de environment van de sidecar uit een secret store — Docker secrets of HashiCorp Vault — waar de worker geen toegang toe heeft. De worker roept de tool vervolgens aan zonder ooit het credential erachter te bezitten.

Controleer de plaatsing

Een praktische sanity check is om elk component en de primitives die het implementeert op te schrijven. Postgres kan session en checkpoint afdekken. De workercontainer is de harness. Een service zoals Daytona, Modal of E2B levert de sandbox, terwijl Tempo of LangSmith de trace opslaat.

Onderzoek vervolgens gekoppelde failures. Als twee primitives in hetzelfde proces leven, haalt één crash ze allebei onderuit. Als ze een credential delen, overschrijdt één leak beide boundaries. Veelvoorkomende voorbeelden zijn een worker die ook trace durability beheert, of een sidecar-token dat ook toegang geeft tot de checkpoint database.


Failure modes van een production AI agent runtime

De runtime beheert retries, herstelt eerder werk, isoleert workspaces en dwingt budgets af. Naarmate runs zich over workers en context windows uitstrekken, verschuiven failures naar state, duplicate side effects, sandbox drift en budgetoverschrijdingen.

De failures vallen in vier groepen:

  • Quality-of-output failures: de agent verklaart de task voltooid voordat het werk echt klaar is, vergeet wat hij deed na een context-window reset of vertrouwt op zijn eigen self-evaluation en levert defecte output.
  • Cost-control failures: de agent raakt vast in een retry loop of verbruikt een token- of tool-call-budget zonder iets nuttigs te produceren.
  • State- en crash failures: workspaces driften omdat één run files aanraakt die eigendom zijn van een andere run, tool calls worden meer dan één keer uitgevoerd doordat retries ze opnieuw afspelen, of werk gaat verloren wanneer een worker tussen events sterft.
  • Context-window failures: het model vat samen en stopt vroegtijdig omdat het denkt dat de ruimte bijna op is, terwijl het window nog voldoende headroom heeft.

De tabel koppelt elke failure aan een mitigation, de basis voor de aanbeveling en de runtime hook die deze afdwingt. Modelspecifiek gedrag kan veranderen, dus behandel observaties van vendors als aanleiding om de aanname opnieuw te testen, niet als permanente regels.

Failure modes en hun mitigationsFailure modes en hun mitigations

Failure modeMitigationEvidence noteRuntime hook
Premature completion: agent verklaart de task te vroeg voltooidGenerator/evaluator split: een evaluator in een fresh context — een tweede model session die zonder history van de run start — leest files (niet chat) en stemt “done” of “not done.” Fail closed bij elke acceptance check.Anthropic’s cwc-long-running-agents quick-start bevat een evaluator subagent; valideer het patroon op je task suite.Sub-agent zonder Write/Edit-tools en met een eigen context window
Feature amnesia across context windowsInitializer-agent schrijft PROGRESS.md, feature-list.json, init.sh. De coding agent leest ze bij elke cold boot.Vereiste voor harness design; meet task completion bij cold boot vóór en na het toevoegen van de artifacts.Boot hook vóór de eerste model call van elke session
Duplicated work after session resetAppend-only event log plus een structured handoff file. Elke nieuwe session start met pwd → read PROGRESS.md → review tests.Vereiste voor durable-log- en checkpoint-design; test door dezelfde session handoff te replayen.LangGraph PostgresSaver checkpoint plus PROGRESS.md artifact
Context anxiety: model vat samen en stopt vroegtijdigCap de actieve session en bouw opnieuw op vanuit een handoff wanneer het model de resterende context niet meer effectief gebruikt. Cognition’s workaround voor Sonnet 4.5 schakelde een groter window in, maar capte effectief gebruik op 200k.Vendorobservaties verschillen tussen Sonnet 4.5 en latere generaties. Test opnieuw voordat je de workaround naar een ander model of een andere harness overbrengt.Harness capte sessionlengte, start de volgende en hervat vanaf checkpoint
Self-evaluation optimism: model keurt eigen werk goedFresh-context evaluator plus Playwright/MCP-grounding in de echte DOM, niet in screenshots. Anthropic’s harness design-frontendrubric bestraft “AI-style” defaults.Anthropic frontend-harness-patroon; valideer met task-level acceptance tests op de gerenderde applicatie.Evaluator draait in een afzonderlijke sandbox session zonder write tools
Stuck loops en retry stormsIteration cap per turn, exponential backoff, circuit breaker bij een hoge tool-error rate. Hard budget voor tool calls.Vereiste voor runtime control; injecteer herhaalde tool failures en controleer de cap, backoff en circuit breaker.Decorator op de tool-execution node; RetryPolicy op Temporal Activities (zie Temporal OpenAI Agents SDK contrib)
Workspace drift: agent wijzigt niet-gerelateerde filesGit commits als checkpoints, file-permission middleware, per-session workspace mount. Deep Agents-middleware laat je read/write paths declareren.Vereiste voor isolation; voer gelijktijdige sessions uit op fixtures en inspecteer cross-run file changes.LangGraph file-permission middleware of Daytona/Runloop per-task fork
Runaway token- of toolkostenToken budget per run, budget per tool, kill switch gekoppeld aan een Prometheus-counter.Aanbeveling voor cost control; Addy Osmani’s verslag over long-running agents illustreert het risico, terwijl de werkelijke spend afhangt van model- en toolprijzen.Cost-attribution span attributes plus Alertmanager rule
Non-idempotent tool callsIdempotency key per tool call. In durable workflows kunnen retries dezelfde tool call meer dan één keer uitvoeren; een deduplication key blokkeert de duplicate.At-least-once retry property; verifieer dit door een Activity retry te forceren nadat het side effect is geslaagd.Temporal Activity met start_to_close_timeout en idempotency key
Verloren werk na process- of sandbox-crashDurable session log buiten het proces; checkpoint na elke super-step. wake(sessionId) → getSession(id) → resume.Recoveryvereiste; kill een worker tussen events en vergelijk de hervatte state met de durable log.PostgresSaver bij elke super-step, of verpak het als een Temporal Workflow

Twee ideeën liggen aan de basis van de meeste rijen. Anthropic over harness-staleness in Harness design for long-running application development:

“Every component in a harness encodes an assumption about what the model can’t do on its own, and those assumptions are worth stress testing, both because they may be incorrect, and because they can quickly go stale as models improve.”

Vercel over het verwante probleem dat te veel tools te veel aannames coderen, in We removed 80% of our agent’s tools:

“We deleted most of it and stripped the agent down to a single tool: execute arbitrary bash commands. We call this a file system agent.”

Het citaat beschrijft de bash core; de agent die Vercel shipte behield twee tools, ExecuteCommand en ExecuteSQL, tegenover vijftien voordien. Deel 3 behandelt de volledige before-and-after. Hun gerapporteerde resultaat over vijf representatieve queries: success ging van 4/5 naar 5/5, en het worst-case-resultaat daalde van 724 s / 100 steps / 145,463 tokens (failed) naar 141 s / 19 steps / 67,483 tokens (succeeded). Die worst-case-rij is de spectaculaire; gemiddeld over de vijf queries bedroeg de tokensaving 37%. De les is niet “verwijder je tools.” De les is dat elke primitive in je runtime, inclusief het tool surface, een half-life heeft. Test de aanname opnieuw wanneer het model verandert.

Cognition zag dezelfde bewegende target bij sessionlengte met Sonnet 4.5. In Rebuilding Devin for Claude Sonnet 4.5 beschrijven ze een model dat proactief SUMMARY.md / CHANGELOG.md schrijft zodra het context exhaustion aanvoelt, maar onderschat hoeveel tokens het nog over heeft. Hun oplossing was het 1M-token context window inschakelen en gebruik op 200k capten, zodat het model nog steeds denkt dat het headroom heeft. Dat was een beta flag toen ze dit schreven.

Anthropic’s huidige context-window-documentatie vermeldt Sonnet 4.5 in augustus 2026 nog steeds op 200k. Het 1M-window wordt standaard geleverd, zonder beta header, op Opus 4.6 en later en Sonnet 4.6 en later. De cap is het deel om in de gaten te houden. Die bestaat alleen omdat Sonnet 4.5 zijn resterende context verkeerd inschat; zodra een model dat niet meer doet, houdt de cap op een fix te zijn en wordt hij een kunstmatige ceiling. Modelgeneraties zijn meer dan één keer gewisseld sinds Cognition die post schreef; controleer de cijfers opnieuw tegen de huidige modellijst voordat je dit overneemt.

Het harness-team van OpenAI heeft de versie in één zin: “Humans steer. Agents execute.” Wanneer iets faalt, is de nuttige vraag welke capability ontbreekt en hoe je die capability zowel legible als enforceable maakt voor de agent.


De gezonde run lifecycle

Een goed beheerde run is saai. Het is een keten van kleine, recoverable steps, waarbij elke step het resultaat naar durable storage schrijft voordat de volgende begint.

Het schrijven van elk resultaat voordat de volgende step begint, beperkt de schade door crashes. Bij een failure gaat alleen de step die in uitvoering was verloren, en de volgende worker hervat vanaf de laatste voltooide step in plaats van het volledige request opnieuw te starten.

De lifecycle van een gedeployde agent runDe lifecycle van een gedeployde agent run

  1. Boot vanuit een nieuwe of een hervatte session. Bij resume mount je de workspace vanuit de laatst bekende state, lees je progress files die de vorige poging heeft achtergelaten (PROGRESS.md, feature-list.json) en laad je het laatste checkpoint uit de database. Hier geeft de harness de agent alles wat de vorige worker in memory had voordat die stierf.
  2. Plan voordat er tool calls worden uitgevoerd. Leg vast hoe “done” eruitziet, hoeveel de run mag besteden, welke tools de agent mag aanroepen en wat de run vroegtijdig moet stoppen. Deze planwaarden worden runtime checks; zonder die checks heeft execution niets om zich tegen af te zetten.
  3. Voer één tool call per keer uit. De permission check van de harness beslist of de call wordt toegestaan, dispatcht hem vervolgens, vangt het resultaat op en schrijft één event naar de session log. Eén step, één event. Een crash tussen events is recoverable omdat de log — niet de memory van de worker — de source of truth is.
  4. Maak checkpoints bij super-step boundaries, of na elk event in een eenvoudigere harness. Persist de graph state, de workspace diff en references naar geproduceerde artifacts. Dit checkpoint leest step 1 bij de volgende resume. Als het checkpoint ontbreekt of stale is, degradeert recovery naar het vanaf nul replayen van de volledige session log, wat veel trager is.
  5. Evalueer de artifacts wanneer de agent denkt dat hij klaar is: tests, een fresh-context evaluator, schema validation en browser checks. Als de check slaagt, eindigt de run succesvol. Als de check faalt, hervat de run vanaf het laatste schone checkpoint, met de failure message toegevoegd aan de context, en probeert hij opnieuw.

Geen enkele stap in deze lijst vereist dat de agent tussen runs iets onthoudt. De state leeft in de session en het checkpoint, en de agent leest die bij elke resume opnieuw in.

Elke tool met side effects heeft een idempotency key nodig die is afgeleid van de session ID en tool-call-ID en wordt opgeslagen voordat het side effect wordt uitgevoerd. send_email(session_id, tool_call_id, message_hash). create_pr(session_id, tool_call_id, branch_name). charge_customer(session_id, tool_call_id, invoice_id). At-least-once execution is de default in queues en workflow engines, dus de duplicate zal optreden. Als een tool call bij herhaling echte schade kan veroorzaken en je die niet op basis van een key kunt dedupliceren, is de tool nog niet klaar voor agents.

Evaluation moet evidence buiten de producerende context omvatten. Een evaluator in een fresh context vermindert shared-context bias, terwijl tests, lints, browser checks en schema validation deterministische evidence leveren. De check kan pass, fail of needs_human teruggeven. Voor code agents kan de reviewer een andere model session met read-only tools zijn. Combineer voor data- en report agents deterministische validation met een reviewer model wanneer nog judgment nodig is.


Elf AI agent deploymentpatronen en wat de keuze bepaalt

Zodra de vijf primitives benoemd zijn, is de vraag welke deploymentvorm ze uitvoert. Met “vorm” bedoel ik een arrangement van die primitives: waar de harness draait, waar state persistent wordt en welk type sandbox het werk uitvoert. Een vorm is een wiring-beslissing, geen vendor-keuze. De chart hieronder toont waar elke vorm comfortabel is op de run-length-as. De tekst erna bespreekt wat de keuze bepaalt.

Als je maar één van de elf leest, lees dan vorm 2: queue + worker + checkpoint DB. Dit is de default die ik voor de meeste teams aanbeveel, de vorm die de reference repo gebruikt en het skeleton waarop de meeste andere vormen variëren: queue → worker → durable state, waarbij de sandbox source, harness owner of state engine wordt vervangen. Door eerst vorm 2 te lezen, scan je de rest sneller.

Deploymentvormen en hun sweet spots qua runlengteDeploymentvormen en hun sweet spots qua runlengte

De chart vergelijkt vormen op runlengte. De matrix hieronder vergelijkt ze op ownership: elke omlijnde cel noemt het component dat die primitive levert.

Waar elke primitive leeft in elke deploymentvormWaar elke primitive leeft in elke deploymentvorm

1. SDK in een app server (synchroon, request-scoped)

De oorspronkelijke vorm. De agent SDK draait in een request handler. Goed voor tasks onder de 30 seconden, demos en interne tools. Slecht voor alles waarvan een HTTP-client kan disconnecten. Cloud Run’s HTTP timeout loopt maximaal tot 60 minuten, en elke panic in de weblaag beëindigt de run. De SDK is de harness, het webproces fungeert ook als sandbox en state leeft meestal in process memory tenzij je die expliciet elders opslaat. Gebruik dit niet voor werk van meerdere uren.

2. Queue + worker + checkpoint DB

De default die ik voor de meeste teams aanbeveel en de production shape in market-analyst-agent: een Python-worker met een PostgreSQL checkpointer, Redis Streams (of RabbitMQ) voor de inbound queue en een MCP sidecar voor tools. Goed voor runs van 10 minuten tot meerdere uren met idempotente steps. De lokale runner kan de queue omzeilen voor synchrone development, maar de queue maakt deel uit van de production shape zodra je async submission en backpressure nodig hebt.

De app accepteert een request, maakt een session row aan, pusht een job en retourneert een run ID. De worker haalt de job op, draait de harness, schrijft checkpoints, streamt status en slaat artifacts op terwijl de run vordert. Postgres blijft beschikbaar, workers zijn cattle en de queue depth geeft backpressure. Spot/Preemptible compute werkt zolang de checkpointer klaar is met schrijven naar disk voordat hij success rapporteert.

In deze vorm is de worker de harness. De container en per-thread workspace bieden een execution boundary, maar untrusted code heeft nog steeds een hardened sandbox of VM nodig. Postgres is eigenaar van session- en checkpoint-state. Traces gaan via OpenTelemetry naar de observability stack die je gebruikt.

3. Durable workflow engine (Temporal-style)

Agent-orchestrationcode draait binnen een Temporal Workflow; model calls en tool calls draaien als Activities. Workflow state leeft in een event-history log die wordt ondersteund door Cassandra, MySQL of Postgres, zodat state tijdens deploys clean kan worden gereplayed. De Temporal × OpenAI Agents SDK integration, algemeen beschikbaar sinds maart 2026, levert een OpenAIAgentsPlugin en een activity_as_tool-helper. De agentic sandboxes write-up beschrijft hoe je een draaiende agent midden in een conversation naar een andere sandbox provider forkt. Idle workflows verbruiken geen compute. De caveats zijn reëel: realtime agents worden niet ondersteund en streaming is nog steeds als experimental gemarkeerd; LocalShellTool en ComputerTool zijn uitgeschakeld omdat ze niet passen bij een distributed model.

Gebruik deze vorm wanneer de run echte waiting points heeft: human approvals, external callbacks, lange sleeps, retries met business rules en deploy windows. Een human approval wordt een durable sleep die geen compute verbruikt, niet een polling loop die dat wel doet.

De Workflow-code is de harness. De sandbox leeft meestal buiten Temporal en wordt vanuit Activities aangeroepen. Session- en checkpoint-state vallen samen in Temporal’s event-history log, terwijl trace visibility afkomstig is van Temporal UI plus OpenTelemetry-spans op elke Activity.

4. Sandbox provider per session

Een nieuwere vorm. Elke agent run krijgt een eigen microVM of container van een sandbox-as-a-service-provider. De harness leeft ergens durable; de sandbox is de disposable execution environment.

ProviderIsolationMax sessionConcurrencyPersistenceCold start
E2BFirecracker microVM1 h Hobby / 24 h Pro20 / 100 (tot 1.100 add-on)Pause/resume, ~4 s/GiB pause, ~1 s resume (public beta)~150 ms
Vercel SandboxFirecracker microVM45 min Hobby / 24 h Pro/Ent10 / 10,000Persistent sandboxes of snapshots; snapshots verlopen 30 dagen na laatste gebruikniet gepubliceerd
DaytonaDocker (optioneel Kata)configureerbare auto-stop/archivetier-basedStop → Archive → Delete; fork ondersteund~90 ms (sommige configs 27 ms)
Modal SandboxesgVisor5 min default, 24 h maxhoogVolumes voor persistence; memory snapshot in preview”ongeveer één seconde” volgens Modal docs
Runloop DevboxesmicroVM (custom hypervisor)suspend/resume; snapshot+branch”meer dan 30.000 concurrent instances” volgens de AWS Marketplace-listingSnapshot + branch vanuit disk statesub-1 s

Cold starts zijn hier end-to-end provisioning, niet raw boot: E2B’s ~150 ms komt boven op de ~125 ms Firecracker-boot die Deel 4 voor de hypervisor zelf noemt. De tabel combineert de E2B vs Daytona comparison, Daytona’s sandboxes documentation en fork/snapshot changelog, Modal’s sandboxes en cold-start-guides, de Runloop AWS Marketplace listing en Vercel Sandbox pricing.

Daytona registreert voor elke onafhankelijke fork een parent-child-link, waarmee de lineage van afgeleide sandboxes behouden blijft. OpenAI’s Codex harness gebruikt de per-worktree-variant: “Codex works on a fully isolated version of that app, including its logs and metrics, which get torn down once that task is complete.”

Kies deze vorm wanneer de agent untrusted code, browser automation, tests of package installs uitvoert. De trade-off is hogere cost en provider coupling dan bij shared workers.

De provider bezit alleen de sandbox. Harness, session, checkpoint en trace blijven aan jouw kant, meestal verbonden volgens de queue + worker-vorm uit #2.

5. Anthropic Managed Agents (hosted harness)

Anthropic lanceerde Managed Agents op 8 april 2026 in public beta, achter de managed-agents-2026-04-01 beta header. De service levert een hosted session, harness, sandbox en vault-backed MCP proxy. wake(sessionId) kan de harness op een nieuwe worker initialiseren zonder durable session state te verliezen.

Anthropic factureert Managed Agents tegen standaard token rates plus $0.08 per session-hour. Billing gebeurt op millisecondeniveau en geldt alleen zolang de session status “running” is; idle time is gratis. Een runaway retry loop voegt dus session-hourkosten toe boven op de tokenkosten.

Lees de caveats. De korting van de Batch API is niet van toepassing (“Sessions are stateful and interactive. There is no batch mode.”). Managed Agents is niet beschikbaar via AWS Bedrock of Google Vertex AI. Binnen de beta zijn MCP tunnels en agent “dreaming” bovendien onderdeel van een verdere research preview waarvoor je toegang moet aanvragen; multi-agent coordination en rubric-graded self-evaluation zijn gedocumenteerde onderdelen van de beta. Lock-in is hoog: je ruilt harness-vrijheid in voor het niet zelf hoeven draaien van de loop.

Anthropic host alle vijf primitives: session, harness, sandbox, checkpoint en trace. Jij levert de runtime uit handen en krijgt de outputs terug.

6. LangChain Deep Agents Deploy (managed open harness)

deepagents deploy verpakt een deepagents.toml in een LangSmith Deployment met durable execution, memory, multi-tenancy, human-in-the-loop, observability, sandboxed code execution en scheduled runs. Cloud-, hybrid- en self-hosted deployment modes worden ondersteund. Sandbox providers (LangSmith Sandboxes, Daytona, Modal, Runloop of custom) zijn via één configwaarde verwisselbaar. State leeft in een virtual filesystem met pluggable backends; memory wordt gescoped op user, assistant of beide. Lock-in is lager dan bij Managed Agents: de harness is MIT-licensed, instructions gebruiken de open AGENTS.md-standard en agents zijn beschikbaar via MCP, het A2A (Agent2Agent)-protocol en Agent Protocol. Zie LangChain’s runtime-behind-production-deep-agents-write-up.

Standaard worden alle vijf primitives gehost, maar elk ervan is via configuratie verwisselbaar. De sandbox zit achter één configwaarde. Session en checkpoint leven op een virtual filesystem met pluggable backends. Trace gaat naar LangSmith.

7. Google Cloud Run service of job

Cloud Run heeft twee verschillende runtime modes, en welke het beste past hangt af van hoe de agent wordt aangeroepen. Services zijn HTTP-bound en schalen naar nul tussen requests; de harness draait als request handler die terugkeert wanneer de run klaar is. Jobs draaien tot completion zonder HTTP-entrypoint; de harness draait als een one-shot worker die stopt wanneer de task klaar is. Beide kunnen de harness hosten, maar geen van beide houdt state tussen runs vast. Sessions en checkpoints moeten in Postgres, Spanner of een vergelijkbare external store leven.

De harde limieten verschillen sterk. Cloud Run service request timeout: default 300 s, maximum 3.600 s (60 min). WebSockets krijgen dezelfde timeout. Cloud Run jobs: default 10 min per task, maximum 168 h (7 dagen); voor tasks met GPUs maximaal 1 uur. Services schalen naar nul tenzij je always-on CPU inschakelt; jobs hebben geen HTTP en autoscalen niet.

Gebruik een service voor synchrone runs tot 60 minuten. Gebruik een job voor langer one-shot- of async werk. Cloud Run Jobs kunnen een task dagenlang actief houden, maar bieden geen durable replay over deploys, version changes of worker replacement heen. Gebruik Cloud Run niet boven 7 dagen.

Cloud Run host de harness. Session- en checkpoint-state leven in Postgres, Spanner of een andere external store; traces kunnen via Cloud Logging en OpenTelemetry lopen. De servicecontainer is een execution environment; voeg een afzonderlijke sandbox toe wanneer de agent untrusted code uitvoert.

8. AWS Lambda (waarom dit de verkeerde tool is)

Lambda’s maximum function timeout is hard begrensd op 900 s (15 minuten). Als API Gateway vóór de function staat, hangt de integration limit af van het API-type. HTTP APIs staan 30 seconden toe; REST integrations hebben standaard 29 seconden, terwijl Regional en private REST APIs een langere timeout kunnen configureren. Geen van deze paden maakt van Lambda een worker voor runs van meerdere uren. Een long-running harness heeft nog steeds external state en re-invocation nodig, waarmee je de queue + worker-vorm opnieuw bouwt. Gebruik Lambda voor bounded tool calls, zoals file fetches of S3 uploads, aangeroepen door een langer draaiende orchestrator. Plaats de orchestrator daar niet.

Lambda kan hooguit één tool call uitvoeren binnen zijn limiet van 15 minuten. Harness, session, checkpoint, sandbox en trace moeten allemaal elders leven.

9. AWS ECS / Fargate-task per run

Fargate documenteert geen harde limiet op de task runtime, anders dan Lambda. Fargate throttling quotas staan een launch burst van 100 toe en vullen aan met 20 per seconde, met afzonderlijke on-demand- en spot-budgets. ECS service quotas beperken services die AWS Cloud Map discovery gebruiken tot 1.000 tasks per service en EC2-backed clusters tot 5.000 container instances.

Fargate vereist de awsvpc-mode, dus elke task krijgt een network interface en private IP. Dat past bij VPC-interne data access. Fargate Spot voegt interruption risk toe, en durability blijft jouw verantwoordelijkheid omdat het platform geen Temporal-style replay biedt.

Fargate host de harness en geeft elke run een eigen task. Dat scheidt workspaces en task credentials, maar is op zichzelf geen complete sandbox voor hostile code. Session, checkpoint en trace gaan naar external services zoals RDS of DynamoDB plus CloudWatch/X-Ray.

10. Kubernetes Job of namespace per session

Goed wanneer je al Kubernetes beheert en sandbox-per-session met clusterbrede controls wilt. Slecht wanneer je sub-seconde startup nodig hebt, omdat het pullen van de container image en het initialiseren van de pod te lang duren bij een cold start. Het patroon is één Job per agent run, met activeDeadlineSeconds, een PersistentVolumeClaim voor de workspace en een sidecar voor de MCP-server. Crash recovery moet je zelf bouwen. Kubernetes alleen adopteren om agents te hosten is duur door configuration overhead en operational burden. Het is alleen de moeite waard als je K8s al om andere redenen draait.

Kubernetes host de harness en de per-run execution environment, meestal als één Job en soms met een dedicated namespace. Sterke isolation hangt nog steeds af van runtime class, network policy, pod security en de onderliggende container- of VM-boundary. Session- en checkpoint-state leven in een external database of op een PersistentVolumeClaim.

11. Local Docker Compose (alleen voor development)

De reference voor de volgende sectie. Het doel van deze vorm is dat hij de production topology één-op-één weerspiegelt (dezelfde primitives, dezelfde network shape) terwijl alles op één machine draait. Wat hij niet weerspiegelt, is de isolation: één shared workspace mount, één Postgres, geen hardened sandbox en geen afzonderlijke failure domains tussen worker en state. Ship niets dat hierop lijkt.

Compose weerspiegelt shape #2 op één host. Postgres bevat session- en checkpoint-state en de workercontainer is de harness. De shared workspace mount is handig voor development, maar isoleert untrusted runs niet. De optionele OpenTelemetry-stack registreert traces.


Reference stack: Docker Compose

De reference topology in slavadubrov/market-analyst-agent bestaat uit een LangGraph-worker, een Postgres checkpointer, Qdrant voor retrieval, een MCP sidecar, een Redis queue voor async production-like runs en een optionele Prometheus / Grafana / Loki / Tempo / OTel-observability stack. In local compose is Redis alleen optioneel omdat de synchrone runner de worker rechtstreeks kan aanroepen. docker compose up brengt de core topology lokaal omhoog; de MCP sidecar en observability stack zijn opt-in profiles (--profile mcp, --profile observability).

De reference Docker Compose-topologyDe reference Docker Compose-topology

Het enige onderdeel dat het waard is om inline te tonen, is de canonical LangGraph wiring. Dit is een illustratief excerpt, geen repository-runnable example. Om het uit te voeren heb je langgraph, langgraph-checkpoint-postgres en psycopg[binary,pool] nodig, een bereikbare PostgreSQL-database met permission om de checkpointer tables te creëren, POSTGRES_PASSWORD en een eerder gebouwde StateGraph in builder; zie LangGraph’s Postgres checkpointer setup.

import os
from urllib.parse import quote

from langgraph.checkpoint.postgres import PostgresSaver

password = quote(os.environ["POSTGRES_PASSWORD"], safe="")
DB_URI = f"postgresql://agent:{password}@postgres:5432/agent"
# `builder` is your StateGraph, already built
session_id = "session-123"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
    checkpointer.setup()  # creates tables on first run
    graph = builder.compile(checkpointer=checkpointer)
    result = graph.invoke(
        {"messages": [{"role": "user", "content": "Continue the task"}]},
        {"configurable": {"thread_id": session_id}},
    )

Observability die de run overleeft

Korte request handlers zijn eenvoudig te debuggen: bij een failure lees je de response en de live log. Long-running agents hebben die luxe niet. Tegen de tijd dat een run van zes uur faalt, gebeurde de interessante event vijf uur eerder, is de live terminaloutput verdwenen en is de worker die hem produceerde vervangen. Niemand gaat de run uit het geheugen reconstrueren. Je debugt dus aan de hand van durable artifacts die werden geschreven terwijl de run nog actief was.

Production stacks dekken doorgaans vier soorten artifacts in twee groepen. Twee daarvan lees je na afloop van de run, voor postmortems en replay: een queryable event log van elke step en OpenTelemetry traces die tonen waar tijd en tokens naartoe gingen. Twee lees je tijdens de run. De ene is een live tail van wat de agent in de workspace produceert. De andere is een per-worktree observability stack die de agent zelf kan raadplegen terwijl hij nog werkt.

Structured event log (lezen na de run)

Elke model call, tool call, result, error en approval wordt naar durable storage geschreven, met session ID en timestamp als key. Zodra de run eindigt, query je dit als een gewone databasetabel. Addy Osmani legt de lat duidelijk in Long-running Agents: “If you can’t reconstruct what the agent did in the last 24 hours from durable storage, what you have is a long-running shell script that happens to call an LLM, not a long-running agent.”

OpenTelemetry GenAI traces (lezen na de run)

Dezelfde stapsgewijze data wordt emitted als spans met de standaardattributen uit de gen_ai.* semantic conventions: model name, provider, input- en output-token counts, conversation ID en workflow name. De conventions hebben nog steeds Development stability.

In 2026 verhuisden ze uit OpenTelemetry’s hoofdrepository voor semantic conventions naar hun eigen GenAI semantic conventions repo. De attribuutnamen zijn bruikbaar voor instrumentation, maar pin de revision die je hebt gevalideerd in plaats van een version number uit de main repo. Provider-specific fields leven in subnamespaces (anthropic.*, openai.*), keyed off gen_ai.provider.name. De reden om de standard te gebruiken is portability: op OTLP-compatible destinations die deze conventions ondersteunen, hoef je bij het wisselen van backend mogelijk niet opnieuw te instrumenteren, hoewel backend adapters of destination-specific configuration nog steeds vereist kunnen zijn.

Tool-call timeline plus workspace diffs (lezen tijdens de run)

De snelste manier om te weten wat een agent nu doet, is tailen wat hij in de workspace produceert, niet greppen door een session log. Anthropic’s Harness Primitives for Long-Running Claude Agents-quick-start levert hiervoor een two-pane watch loop: watch -n 5 'git log --oneline -8' toont de laatste commits die de agent heeft gemaakt en watch -n 5 'find screenshots -name "*.png" | tail -5' toont de laatste screenshots die hij heeft genomen. Twee terminal panes die elke vijf seconden refreshen volstaan om te zien of een run echte progress maakt of rondjes draait.

Ephemeral stack per worktree (door de agent zelf gelezen tijdens de run)

Volgens OpenAI’s harness post: “Logs, metrics, and traces are exposed to Codex via a local observability stack that’s ephemeral for any given worktree.” Elke agent worktree krijgt een eigen short-lived Loki + Prometheus + Tempo, uitsluitend voor die run. De agent queryt deze stack terwijl hij werkt. Daardoor kan een prompt als “geen span in deze vier user journeys duurt langer dan twee seconden” iets worden wat de agent direct kan verifiëren, in plaats van iets wat hij moet raden.

(De fresh-context evaluator uit de failure-modes-tabel leest deze artifacts om “done” te bepalen. Dat hoort bij evaluation, niet bij observability; zie § healthy run lifecycle. De evaluator is afhankelijk van alle bovenstaande surfaces.)

Een minimale self-hosted observability stack

Voor iets als market-analyst-agent:

  1. OpenTelemetry Collector met de GenAI Normalizer Processor (contrib, alpha) voor ondersteunde GenAI-attributen. Gebruik de generieke Attributes- of Transform-processors om gen_ai.*-velden te filteren of te herschrijven.
  2. Tempo (of Jaeger) voor traces, keyed by gen_ai.conversation.id / thread_id.
  3. Loki voor structured event-log entries.
  4. Prometheus voor gen_ai.client.token.usage, gen_ai.client.operation.duration en gen_ai.client.operation.time_to_first_chunk — de gen_ai.server.*-metrics komen van de model server, dus je krijgt ze alleen wanneer je de weights zelf host (zie de GenAI metrics conventions).
  5. Grafana-dashboards keyed by gen_ai.agent.name en gen_ai.request.model.

Hosted alternatives (kies er één, niet drie):

  • LangSmith: native LangGraph integration; ook de deployment target voor Deep Agents Deploy.
  • Braintrust: sterkste fit wanneer eval-first regression suites prioriteit hebben.
  • Arize Phoenix: OSS, native voor OTLP (het OpenTelemetry wire protocol), in combinatie met OpenInference-instrumentation.
  • OpenAI’s tracing dashboard: automatisch wanneer je de OpenAI Agents SDK of de Temporal integration ervan gebruikt.
  • Anthropic’s Claude tracing: voor sessions die binnen Managed Agents draaien.

Instrumenteer de LangGraph-node

Dit is een illustratief excerpt en wordt overgeslagen door de example runner van de repository. Het gaat ervan uit dat de LangGraph-node al een actieve OpenTelemetry span, de huidige thread_id en een provider response usage-object met input_tokens en output_tokens heeft; tracer setup, export configuration en provider-specific usage mapping vallen buiten het snippet.

# In the LangGraph node, around the model call:
span.set_attribute("gen_ai.operation.name", "chat")
span.set_attribute("gen_ai.provider.name", "anthropic")
span.set_attribute("gen_ai.request.model", "<your-model-id>")
span.set_attribute("gen_ai.response.model", "<your-model-id>")
span.set_attribute("gen_ai.conversation.id", thread_id)
span.set_attribute("gen_ai.agent.name", "market-analyst")
span.set_attribute("gen_ai.workflow.name", "research_then_write")
span.set_attribute("gen_ai.usage.input_tokens", usage.input_tokens)
span.set_attribute("gen_ai.usage.output_tokens", usage.output_tokens)

Attribuutnamen zijn letterlijk overgenomen uit het OpenTelemetry GenAI semantic conventions registry.

Drie queries die op een dashboard thuishoren

# Loki: token usage per agent over 1h
sum by (gen_ai_agent_name) (
    rate({service_name="market-analyst-agent"} | json | unwrap gen_ai_usage_output_tokens [1h])
)
# PromQL: p95 model latency per model
histogram_quantile(0.95,
    sum by (le, gen_ai_request_model) (
        rate(gen_ai_client_operation_duration_bucket[5m])
    )
)
# TraceQL: long-running tool calls
{ span.gen_ai.operation.name = "execute_tool" && duration > 30s }

Het debug-bundlepatroon

Wanneer een run faalt, moet de worker een /workspaces/${THREAD_ID}/_debug/ aanmaken met de artifacts waar je in een postmortem om zou vragen:

  • session.jsonl: volledige event-log dump uit de PostgresSaver (checkpointer.list({"configurable": {"thread_id": ...}})).
  • last_state.json: StateSnapshot.values uit de laatste succesvolle super-step.
  • trace.json: OTLP-geëxporteerde spans voor de run.
  • tool_calls.csv: (ts, tool, input_hash, latency_ms, status, error).
  • workspace.tar.zst: de workspace directory plus git diff tegen de initializer commit.
  • screenshots/*.png: wat de agent zag.
  • PROGRESS.md, feature-list.json en andere door de agent geschreven progress files.
  • env.txt: image tags, model version, harness commit SHA.

Deze bundle geeft een human of reviewer agent voldoende evidence om de failure te reconstrueren. “De agent kwam vast te zitten” is vaag. Een illustratief report is concreet: session s_123 besteedde 71 procent van zijn tokens aan het herhalen van drie commands nadat npm install faalde.


De juiste vorm kiezen: een decision guide

De meeste bovenstaande vergelijkingen komen neer op een handvol beslissingen.

Begin met runlengte

Gebruik runlengte als eerste filter:

  • Minder dan 30 seconden, idempotent: request-lifecycle SDK in een app server.
  • 30 s tot 60 min: queue + worker + checkpoint DB.
  • 60 min tot 24 h: dezelfde queue + worker, of een Cloud Run Job voor one-shot-werk. Gebruik een durable workflow engine als je ook versioning en replay nodig hebt.
  • Meer dan 24 h, moet deploys overleven: durable workflow engine (Temporal-style). Cloud Run Jobs kunnen lang werk uitvoeren tot hun task limit, maar bieden geen replay semantics.
  • Multi-day reinforcement-learning-training loops: K8s Job + volume + Temporal.

Controleer na deze grove filter side effects, recovery, replay, isolation, data location en het team dat het systeem gaat beheren.

Platform fit per use case

Platform fit per use casePlatform fit per use case

De matrix is dense, en geen enkele groene cel bepaalt de architecture; meestal zijn het de gele cellen — waar een platform iets alleen met een caveat ondersteunt — die de keuze bepalen. Brede workload coverage is nuttig, maar toont geen data residency, replay semantics, provider dependence, operational maturity of de cost van state later verplaatsen.

Deep Agents Deploy is de enige kolom in de matrix zonder rode of gele cel: korte synchrone runs, multi-hour batch, sandbox forking, GPU work en de laagste lock-in komen allemaal groen uit. Dat maakt het een kandidaat wanneer één platform al je workloads moet bedienen. Die breedte gaat wel samen met een kortere production track record dan een queue + worker + Postgres-stack. Behandel de groene cellen als capability claims die je moet valideren en vergelijk vervolgens de operationele constraints die de matrix niet kan coderen.

Anthropic Managed Agents past óf volledig bij je workload óf helemaal niet. Het product heeft twee harde constraints: het is hosted-only en Claude-only. Als je workload aan beide voldoet — Claude is al het model dat je wilt gebruiken en je beheert liever niet zelf een harness — is Managed Agents een sterke fit. Een internal coding agent die in bursts van twee tot zes uur draait, past hier het best bij; een groot deel van het platformwerk verdwijnt uit je team. Als één constraint faalt omdat je een non-Claude-model of self-hosted compliance nodig hebt, past Managed Agents niet. Geen enkele configuration change verandert dat.

Modelleer de pricing vóór je commit, niet erna. De session-hourregel is 0.08/hourontopofstandardtokencosts.Ifasinglesessionrancontinuously,thatisabout0.08/hour on top of standard token costs. If a single session ran continuously, that is about 58/maand per session. Bij 100 sessions die continu draaien komt dat neer op ongeveer 5,800/monthbeforetokens.Multiply5,800/month _before tokens_. Multiply 0.08 maal je verwachte concurrent-session hours. Tel dit op bij je token bill en vergelijk het met de kosten van een queue + worker-stack op je eigen infra. Later migreren van Managed Agents is een re-platforming exercise, geen config change.

Hosted harness versus owned harness

Het onderscheid gaat hier over wie de harness beheert, niet over wie de code heeft geschreven. Hosted betekent dat de vendor de harness loop op zijn infrastructuur draait en dat jij een API aanroept. Owned betekent dat jij de loop op je eigen infrastructuur draait, zelfs als de harnesscode zelf van een vendor afkomstig is.

LangChain verschijnt aan beide kanten van deze grens, wat mensen vaak in verwarring brengt. Ze leveren LangGraph, een MIT-licensed library die je zelf host (owned), en Deep Agents Deploy, een managed product dat standaard een Deep Agents harness draait op LangSmith Deployment in de cloud (hosted). Zelfde bedrijf, twee verschillende operational models. Je kiest wie de loop draait, niet wiens logo op de library staat. (Deep Agents Deploy heeft ook een self-hosted mode voor teams die de harness-ergonomie zonder de cloudcomponent willen; die mode valt onder owned.)

Kies een hosted harness wanneer model support, data boundary, recovery behavior en extension points al passen. Kies een owned harness wanneer die constraints requirements zijn waarvan je verwacht dat ze veranderen. Migratie tussen beide verandert state, observability en execution boundaries; test daarom het exit path voordat production data ervan afhankelijk wordt.

Hosted sandbox versus een owned execution environment

Kies een hosted sandbox wanneer de isolation-, pause/resume- of fork-semantics van de provider passen bij je threat model en startup budget. Docker of Fargate kan geschikt zijn voor trusted internal workloads die VPC access of strikte data residency nodig hebben, maar een standaardcontainer is geen voldoende boundary voor hostile code. Deel 4 bespreekt in dat geval de isolation-opties.

State stores: Git, DB en object storage naast elkaar

Long-running agents gebruiken meestal drie state stores tegelijk, omdat elke store eigenaar is van een ander artifact.

Git bewaart workspace state: de code, documenten en progress files die de agent wijzigt. Elke commit geeft de harness een stabiel recovery point en de volgende session een compacte history.

De checkpoint database bewaart graph state: wat is beslist, welke nodes hebben gedraaid, welke results zijn teruggekomen en wat er vervolgens moet draaien. De artifact store bevat grote final outputs zoals PDFs, Parquet-files en screenshots. Die artifacts horen niet in Git of in de checkpoint database.

Wanneer gebruik je git als state

Gebruik git wanneer de workload code-shaped is (multi-file edits, refactors, app generation) of voldoende document-shaped is dat file history van belang is. Het patroon is eenvoudig: maak een run branch, maak een initializer commit en commit vervolgens op betekenisvolle boundaries: na setup, na elke feature, nadat tests slagen en na de laatste cleanup. Bewaar de laatste workspace commit SHA naast de checkpoint row. Bij resume checkt de volgende worker de branch uit, leest git log --oneline -8, inspecteert git status en de nieuwste diff en leest vervolgens PROGRESS.md of het handoff-bestand dat de vorige session heeft geschreven.

Zo wordt git een recovery surface voor het artifact dat wordt bewerkt, geen vervanging voor de checkpoint DB. Git kan twee vragen beantwoorden: wat is er veranderd en welke versie slaagde voor de tests. Git kan de harness niet vertellen welke graph node vervolgens moet draaien, welke tool call op approval wacht of welke retry zijn idempotency key al heeft gebruikt. Anthropic’s harness gebruikt initializer commits plus per-feature commits als source of truth voor workspace recovery; het model leest git log --oneline -8 om state te herstellen. Sla git over wanneer het work product één conversational answer is. De overhead betaalt zich dan niet terug.

Wanneer gebruik je DB checkpointing

Gebruik PostgresSaver-style checkpointing wanneer de agent een graph structure heeft met meerdere nodes waarvan de intermediate state van belang is (planner → researcher → writer → verifier). De reference repo gebruikt dit precies om die reden. Plaats geen workspace artifacts op terabyteschaal in het checkpoint; die horen in object storage.

Wanneer gebruik je een artifact store (S3 / GCS)

Gebruik object storage wanneer:

  • de output groter is dan de checkpoint database zou moeten dragen;
  • downstream consumers een URL-addressable artifact nodig hebben zonder via de agent te gaan; of
  • het deliverable en de run state verschillende retention windows hebben.

Je kunt bijvoorbeeld de session log na 30 dagen verwijderen, maar het final report jarenlang bewaren. Key de layout op (thread_id, checkpoint_id, artifact_name), zodat de producerende run reconstructable blijft.

Wanneer voeg je human approval gates toe?

Voeg gates toe wanneer de tool call destructive en irreversible is (DB writes, money movement, external comms versturen), wanneer de tool call buiten de blast radius van de agent komt (production deploys, customer-facing publishes) of wanneer regulators review vereisen. LangGraph’s interrupt() en Deep Agents’ approval middleware ondersteunen deze gates ingebouwd. Deel 4 behandelde waarom deze gates een permission concern zijn en geen prompt concern.


Een praktische production checklist

Beantwoord voordat je een long-running agent shipt de volgende vragen in concrete infrastructuurtermen.

  1. Welke store is eigenaar van session events en checkpoints?
  2. Wat gebeurt er wanneer de worker halverwege een tool call sterft?
  3. Kan één run de workspace van een andere run corrumperen?
  4. Voor welke acties is approval nodig?
  5. Kunnen het model of de sandbox raw credentials lezen?
  6. Welke tool calls kunnen veilig worden geretried?
  7. Waar wordt de cost cap per run afgedwongen?
  8. Welke fresh-context evaluator beslist “done”?
  9. Waar leven final outputs nadat de sandbox is verdwenen?
  10. Kunnen we morgen een gefaalde run uitleggen zonder die opnieuw te draaien?

Als het antwoord op één van deze vragen “de prompt zegt tegen de agent dat hij voorzichtig moet zijn” is, is het systeem nog niet gedeployed. Het is nog steeds een demo.

De volgende laag is de harness loop

Deze runtime kan een run actief en recoverable houden, maar durability bewijst niet dat het werk correct is. Deel 6, Harness Engineering for AI Agents, opent de harness-primitive uit de tabel hierboven: hoe een trace je vertelt welke van meerdere failures je werkelijk hebt, waar retry- en stopregels leven, wat een handoff moet behouden en hoe een externe acceptance check beslist dat een run klaar is. Dit is ook de laatste post in de serie.

References

Engineering write-ups

LangGraph en Deep Agents

OpenAI Agents SDK

Temporal

Anthropic platform

Sandbox providers

Cloud platform timeouts and quotas

Observability


De Market Analyst Agent-code (LangGraph-worker, Postgres checkpointer, Qdrant memory, MCP sidecar en de hierboven beschreven Docker Compose-topology) staat op GitHub.