June 5, 2026 · Changkun Ou
Agent harness design: the execution runtime
June 5, 2026
This is a companion to Agent harness design: trade-off analysis, which frames the agent platform as a small set of separable primitives connected by contracts. The overview names the harness itself as one of those primitives and gives it a deceptively small contract: a session API (create, resume, interrupt, fork) wrapped around a loop that turns model output into tool calls and tool results back into model input. This post is about the inside of that contract: the per-session execution runtime, the part of the harness that actually drives the loop.
The runtime is the primitive that owns mechanism. It does not decide who may call (identity), where the model comes from (model access), or which actions require a human (the governance fabric). It decides how a session is instantiated, how a stateful tool connection survives a turn, what happens when the context window fills, how a scheduled tick fires exactly once, how composed agents share or isolate state, and, most consequentially for everything built on top of it, how a running loop is paused or killed. The governance fabric's approval gates are policy. The pause they fire is a runtime verb, and it lives here.
The contract
The execution runtime resolves a small set of session verbs and one inner loop.
Create a session bound to an agent definition. Drive its loop: send context to the model, dispatch the tool calls it returns, append the results, repeat until done or interrupted. Resume it after a crash or a wait. Interrupt it mid-flight. Fork it at a checkpoint.
Everything in this post is a way of making one of those verbs survive contact with production. The loop sounds trivial when drawn as a flowchart. It stops being trivial the moment a tool holds a connection across turns, the moment two replicas both think they own the same scheduled tick, the moment a user hits cancel while a sandbox command is mid-execution. The runtime is where those frictions are absorbed or leaked.
Agent instance lifecycle: when the definition is resolved
The first decision is when an agent definition (a prompt, a tool set, a model binding) becomes a live instance. A runtime can instantiate it once at process start and share it across every session, or resolve it per request from a registry of versions. The choice is independent of where the harness sits relative to the sandbox.
The singleton is the obvious starting point: runner and agent are application-lifetime objects, sessions are isolated only by a session_id, allocation per request is zero. The hidden cost is not performance, it is the rollout granularity. When the instance is a singleton, a prompt is a deploy-time constant, and changing it is a redeploy of the whole runtime. There is no per-agent canary, no gradual rollout, no A/B of two prompt versions side by side. The mechanism turns every behavioral change into an all-or-nothing event: a bad prompt regresses 100% of sessions for that agent type until rollback completes. OpenAI's GPT-4o sycophancy episode is the textbook shape of this, the update rolled out on April 25, 2025, rollback began April 28, and the full revert took roughly a day [1]. ZenML's analysis of more than 1,200 production deployments catalogs prompt and configuration changes among the recurring causes of unexpected behavior [2], and Deepchecks documented a single instruction ("be more empathetic and engaging") weakening content filters enough to pass policy-violating output [3]. The common thread is that the blast radius equals the rollout unit, and a singleton makes that unit the entire fleet.
The runtime registry breaks the coupling by resolving a prompt version per request. MLflow's prompt registry [4] and Portkey's canary pattern [5] both implement this, with rollouts that start at a small fraction of traffic and revert on a measured quality regression. The reason this works is not that it makes prompts safer in isolation, it is that it decouples the blast radius from the deploy: a regression touches the canary slice, the eval signal fires, and the stable version keeps serving everyone else. The cost is real and worth naming precisely. The registry adds a resolution hop on every request (cacheable, but now a cache to reason about), a cross-replica consistency story (two replicas must not disagree about which version is canary), and a new variable in every incident (behavior now depends on which version a session resolved, which the operator has to reconstruct after the fact).
Per-request instantiation, building a fresh agent for every call, is almost never worth it for stateless text agents, where it buys runtime flexibility at a per-request allocation cost no one needs. It earns its keep only in agent-factory patterns, where each session's tool set is genuinely derived from caller metadata and cannot be precomputed.
The pressure curve is predictable. A singleton is fine at one or two agent types and starts hurting past three or four. The forcing function is almost always the same incident: a prompt regression in one agent forces a rollback that also reverts an unrelated critical fix in another, because they shared a deploy. That is the moment versioning stops being optional.
Stateful tool connections: pooling, reconnect storms, and token races
Most of the loop's tool calls are stateless: a web fetch, a sandbox exec given a sandbox ID, a plain REST call. The runtime can dispatch them from any replica at any time with no setup or teardown. The interesting failures are at the other end of the spectrum, where a tool holds a connection that carries negotiated capabilities, cursor positions, and server-side context across calls. MCP (the Model Context Protocol) is the canonical case, and it is not a stateless HTTP call dressed up.
The simplest design holds connections in memory per replica, keyed by (session_id, server_url), opened lazily on first use. It works until the platform scales horizontally, and then the statefulness fights the load balancer. The MCP 2026 roadmap names this directly: stateful sessions are the primary scaling bottleneck, because horizontal scaling requires workarounds and stateful sessions fight with load balancers [6]. The concrete failure has two shapes. The first is silent staleness: when an SSE-based MCP server restarts, every session that held a connection to it goes stale, the tools still appear in the catalog but every call fails [7]. The second is the reconnect storm, and its mechanism is worth spelling out because the fix follows directly from it. When a replica holding N sessions, each connected to M servers, dies, recovery is not N reconnections, it is N times M simultaneous reconnections against the surviving infrastructure, and every reconnection has to renegotiate capabilities and lose whatever cursor state the old connection held [8]. The MCP Python SDK's multi-worker failure is the same problem one level down: a session created in one worker process is invisible to a request routed to another [8].
The mechanism dictates the mitigation. The storm is a synchronized thundering herd, so the answer is to desynchronize and to make routing sticky. Session affinity (consistent hashing or load-balancer stickiness) keeps a session's connection on one replica so a rebalance does not orphan it. Reconnect backoff with jitter spreads the herd across time so the surviving servers are not hit by N times M requests in the same instant. And resumable streams make the reconnection cheap rather than lossy: the MCP spec deprecated HTTP+SSE in favor of Streamable HTTP, and resumable streams replay from a cursor using Mcp-Session-Id plus Last-Event-ID, so a reconnect resumes where the old connection left off instead of restarting [9] [10].
OAuth tokens add a concurrency hazard that pooling alone does not touch, because the hazard is on the token, not the connection. A single-use refresh token is, by construction, a resource that exactly one caller may consume. Run several concurrent sessions for the same user and they race to refresh it; the winner gets a new token, the losers present an already-consumed one and get a hard failure with no automatic recovery [11]. Users running five to a dozen concurrent sessions report being forced to re-authenticate multiple times a day [12], which is exactly what a refresh race looks like from the outside. The runtime therefore owes explicit answers to three questions that the happy path never raises: whether a connection that is active when its token is refreshed carries the old token or has the new one swapped in; whether a mid-session revocation surfaces to the model as "retry" or as "stop"; and how consent is orchestrated when two servers demand different OAuth flows for the same user. The 2026 spec adds one structural answer here, mandating RFC 8707 resource indicators so a token cannot be redeemed against the wrong server [13].
Context management: compaction, externalization, and convention-driven honesty
A long-running loop eventually hits the context window. The runtime has to answer two questions that do not answer themselves: what gets preserved, and who decides.
Automatic compaction summarizes older turns into a compressed form and lets the session run past the hard limit. Its failure mode is structural, not occasional: the loss is invisible to the agent. Summarization discards detail, and the agent has no signal about what it lost. Anthropic's own cookbook measured this directly, compaction preserved three of three high-level facts and zero of three obscure specifics [14]. A two-week test across coding tools logged 23 context-loss events in one tool alone, including an agent recommending an approach it had explicitly rejected before compaction [15]. The subtler finding is from Lindenbauer et al., who showed that simply masking old tool outputs with placeholders matches LLM summarization on solve rate at the lowest cost per instance in four of five settings, and, more pointedly, that summaries cause "trajectory elongation": agents persist 13 to 15% longer than optimal because the summary masks the failure signals that would have told them to stop [16]. ACON reports that compaction done well can cut peak tokens by 25% on one benchmark and 54.5% on another while surpassing the no-compression baseline, which says the technique is salvageable, not that it is safe by default [17].
Externalization moves the decision to the agent: it writes what it wants to keep to the filesystem (a progress.md, a plan.md, a structured journal) and reloads from the file after compaction. The strength is that the agent controls what persists; the weakness is that the agent's self-documentation is uneven. Cognition reported that Sonnet 4.5 in Devin frequently writes summaries without being asked, but that the summaries lack comprehensiveness because the model did not know what it did not know, and in some cases the agent spent more tokens writing summaries than solving the task [18]. Externalization trades the compaction summary's blindness for the agent's blindness about its own future needs.
Larger context windows look like they sidestep the whole problem, and they do reduce compaction frequency, but they do not remove the underlying degradation. Du et al. showed a 24.2% accuracy drop on MMLU for a small model as input length grows, even with perfect retrieval [19], and Chroma's study across 18 models and nearly 200,000 calls found performance degrading as context grows even under minimal conditions [20]. "Just fit everything in" is not a robust strategy for a persistent agent, it only moves the failure from "context overflowed" to "context is full and the model is quietly worse." This is a place where the runtime is consuming a model property it does not own: the model it is handed degrades with length, and the runtime's job is to keep sessions inside the band where that degradation is tolerable, not to fix the model.
The honest statement, and it is honest in a way that does not improve with engineering, is that context management is convention-driven in every production harness the ecosystem has documented. Long-session quality rests on three things the runtime cannot guarantee mechanically: the model writing a good summary when asked, the model interpreting its own or another model's summary on reload, and the runtime's willingness to enforce an externalization pattern rather than hope the agent maintains one. The runtime can fire compaction at the right moment and reload the right file. It cannot make the summary true.
Execution mode and session mode: who calls the loop
A request-driven session has a client to call /resume. The harder modes do not, and that absence is the whole design problem.
Four trigger shapes exist: request-driven (a user or system calls in), scheduled (a cron tick fires), event-driven (a webhook or queue message arrives), and hybrid (both request and schedule for the same agent). Request-driven is the simplest because the platform processes work exactly when asked and can fail by simply returning an error to the caller. Scheduled is strictly harder because there is no client to retry, so the platform itself must self-heal on crash. Hybrid is harder still: a user session and a scheduled tick for the same agent can collide on shared external state with neither aware of the other. Event-driven adds ingestion, filtering, and deduplication as first-class concerns, and it introduces a load shape cron never produces, a webhook firehose (dependabot, repository notifications) can drive orders of magnitude more ticks than any interval, which is why admission control at the event layer is load-bearing rather than defensive.
Scheduled and event-driven modes are what "autonomous agent" usually means in production, and they all need the same machinery: somewhere to store what is scheduled for when, agent-level locking so two replicas do not run the same tick, tick timeouts that are distinct from session idle timeouts, circuit breakers on consecutive failures, and an explicit recovery policy for in-flight ticks at restart.
A scheduled agent then faces a second choice, persistent versus ephemeral sessions, and it is a genuine trade-off, not a technical constraint. A persistent session is created on the first tick and reused indefinitely, so the agent accumulates context, a monitoring agent remembers last week's baseline and notices this week's drift. The price is that events accumulate without bound, which makes context management mandatory rather than optional, the externalization pattern above becomes load-bearing. An ephemeral session is fresh per tick with no accumulated context, which means the tick prompt has to be self-contained, and which is exactly right when each tick is independent (scan a repo, send a digest). Persistent is correct when the agent's value comes from remembering; ephemeral is correct when it does not. Choosing persistent for a stateless job buys unbounded storage growth for nothing; choosing ephemeral for a job that needs memory throws away the memory on every tick.
Scheduler design: in-process, external, or durable
If execution mode includes scheduled or event-driven work, the scheduler is a subsystem with its own axes. Treating "we will just use cron" or "we will use Temporal" as a single decision hides the trade-offs that surface at scale.
An in-process scheduler is a priority queue of next-fire-times inside the harness with a goroutine that sleeps until the next fire. It is the simplest deploy and shares the harness's session store and sandbox manager, but its state has to survive a restart, which in practice means it is backed by the database anyway. An external scheduler (one Kubernetes CronJob per agent) is familiar to operators but rigid: no dynamic schedules, one pod per fire, no cross-tick state without external storage, and a poor fit for high-frequency or many-agent workloads. A durable execution framework (Temporal [21], Inngest [22], Restate [23]) treats each fire as a durable workflow and is the right fit when a tick needs multi-step choreography with external side effects; the cost is an operational dependency and a programming model. The reason this category exists at all is that probabilistic model behavior makes naive retry insufficient, which is precisely the case durable journaling is built for. The circuit-breaker requirement is not theoretical: a 13-hour AWS Cost Explorer outage in December 2025 was linked in incident reporting to an autonomous agent acting with broad permissions and no circuit breaker [24].
The cross-replica coordination problem is where most schedulers get subtly wrong. Every replica runs its own scheduler loop, so without coordination every replica fires every tick. The usual fix is an agent-level distributed lock acquired before the run and released after, which distributes work naturally because whichever replica acquires the lock wins. It is simple and correct for overlap, and it has two sharp gotchas that come straight from the locking literature. Kleppmann's Redlock critique means Redis-based locks need fencing tokens to be safe under network partitions [25]. And with PgBouncer transaction pooling, pg_advisory_lock releases when the connection returns to the pool, so callers that expect a session-scoped lock must use pg_advisory_xact_lock (or a dedicated session pool) or the lock silently evaporates mid-tick. The alternatives trade coordination cost against other complexity: shard assignment (consistent-hash agents to replicas, only the owner fires) lowers per-tick cost but adds rebalance complexity on churn; a single elected leader reduces duplicate-fire risk to zero but creates a leader dependency.
The lock is the place a critical distinction hides: it prevents two replicas from firing the same tick concurrently, but it does not make the tick's side effects exactly-once. If a tick posts to Slack, opens a ticket, or writes to a database and the replica crashes before recording "done," recovery replays the tick and duplicates the side effect. Locking prevents overlap; idempotency keys or a step-log boundary prevent duplication. They are different guarantees, and a scheduler that has the first does not have the second. The rest of the runaway-protection toolkit follows from the same mechanical reasoning: jitter prevents a thundering herd when many agents share a schedule, a per-tick wall-clock timeout hard-kills a tick that overruns, exponential backoff keeps a failing tick from retrying in a tight loop, a circuit breaker disables an agent after N consecutive failures so it cannot burn tokens indefinitely, and self-healing at startup replays ticks whose end was never recorded. The failure modes are the inverses: a lock held by a dead replica stalls the agent unless it has a TTL or heartbeat, clock skew across replicas produces double-fires or missed fires without NTP discipline, and a five-minute interval with a seven-minute tick produces either overlapping ticks or stretched intervals, neither of which is what the operator meant.
Multi-agent composition: shapes, shared state, and loops
A single agent is the simple case. Real workloads compose, and how they compose is a runtime design axis with two largely independent dimensions: the shape of the composition and whether the composed agents share state.
The shapes are familiar. A sequential pipeline fixes the ordering and feeds each stage's output to the next (ADK's SequentialAgent, LangGraph's graph primitives, CrewAI's task pipelines [26]). A supervisor with workers has a coordinating agent decide which worker to invoke per subtask (LangGraph's supervisor and swarm packages, the OpenAI Agents SDK [27]; OpenAI's earlier Swarm was explicitly experimental and is superseded [28]). It is flexible and harder to reason about because routing is dynamic. Peer delegation hands tasks between agents on different platforms over a protocol like A2A [29], which requires identity propagation and agreement on task and result schemas. Parallel fan-out runs subtasks concurrently and reduces the results, cutting latency while multiplying cost and adding a result-merging problem. None of these shapes is free, and the literature is sharp about when not to compose at all: one benchmark shows framework-level design choices alone causing more than 100-fold latency variance and coordination success swinging from 90% to 30% by shape [30], and another finds single-agent models matching or beating multi-agent systems on multi-hop reasoning under equal thinking-token budgets [31].
The state-sharing dimension is orthogonal and is where the runtime actually earns or loses correctness. Shared session and sandbox is cheapest and most composable, and it pays for that with races on external effects and prompt contamination between agents that see each other's context. Isolated sub-sessions under a shared parent give each sub-agent its own session with the parent coordinating, which is safer at the cost of more plumbing. Isolated sub-sessions in separate sandboxes is full worktree isolation, and Geng and Neubig's result is the strongest evidence for it: worktree isolation substantially outperforms shared-workspace approaches on coding agents [32]. The cost is the highest and the safety is the strongest, and the ordering of the three is a direct trade of plumbing for blast-radius containment.
The composition failure modes are the ones a single agent never has. Prompt pollution: a supervisor's instructions leak into a sub-agent's context, or a sub-agent's failure propagates to its siblings, mitigated only by explicit prompt boundaries. Identity confusion across delegation: when agent A on one platform delegates to agent B on another, B's view of the user identity is whatever the propagation contract makes it, and poorly specified propagation has produced real incidents. And the one with a dollar figure attached: loops. A supervisor calls worker A, which calls worker B, which calls the supervisor, and without a hop limit this is the $47,000 loop, two agents that ran for eleven days because neither had a ceiling [33]. The structural taxonomy is blunt about where the risk lives, the top failure categories in multi-agent systems are system-design issues and inter-agent misalignment, and neither is solved by a composition framework alone [34].
Tool dispatch by statefulness
The connection-pooling discussion above is one instance of a broader axis: tools come in three statefulness classes, and a runtime that dispatches all of them through one mechanism has implicitly chosen the class of its dominant tool and mishandled the rest.
Stateless tools (web fetch, sandbox exec given a sandbox ID, simple REST) hold no state on the harness side; the tool function looks up any handle it needs from context and calls, and it scales trivially across replicas. Stateful-connection tools (MCP, WebSocket APIs, gRPC streams) carry negotiated capabilities and cursors in a connection the harness holds for the session's lifetime, dispatched through the session-scoped pool described above. Stateful-resource tools (databases with session state, distributed locks, rate-limited APIs with per-key state, long-running jobs whose status lives externally) keep their state in the external system, but the harness still has to correlate calls to the same resource across turns, handle partial failures, and coordinate with concurrent sessions.
The classification matters because each class answers the same operational questions differently. Where is the state: nowhere, the harness pool, or the external system. What happens on harness restart: nothing, reconnect, or rediscover. What happens on the external system's restart: the next call sees fresh state, the pool is lost and must reconnect, or the job may be lost or duplicated. The failure modes are the cross-class confusions. Treating a stateful-resource tool as stateless, dispatching a long-running job and then forgetting its ID, produces the symptom of an agent that "said it kicked off a deploy but has no idea if it finished." Treating a stateless tool as stateful, pooling connections to a plain HTTP API, pays the complexity cost with no benefit. And a single logical operation that mixes all three, a stateless fetch, a stateful-connection MCP call, and a stateful-resource database write, has three different failure and recovery modes packed into one tool call, which is the hardest variant to reason about because the partial-failure space is the product of the three.
Interruption and steering: the runtime verb the rest of the platform depends on
The runtime is driving a long loop, and something outside it sometimes needs to redirect that loop mid-flight: pause for approval, inject new information, cancel entirely, or rewind and re-run with a nudge. These are runtime mechanics, deliberately separate from the policy that decides when an interrupt should happen. The governance fabric owns that policy; conflating the two produces both weak enforcement and weak user control, so this post owns only the mechanism.
There are four mechanisms, in increasing order of usefulness and difficulty. Hard cancel is kill(session) with no state preservation, workspace and sandbox torn down. It is simple and brutal, and it makes every user correction a context-losing event. Cooperative pause and resume checks an interrupt flag at step boundaries (between model calls, between tool calls), serializes state on interrupt, and waits for a resume command. LangGraph's interrupt() implements this as a first-class graph primitive [35]. It is worth being precise about what is and is not a pause primitive here, because the distinction is load-bearing: the OpenAI Agents SDK's RunHooks and AgentHooks are lifecycle observability callbacks, not a pause or resume mechanism, so on that stack the pause has to be built around them rather than assumed [27]. Queued steering appends user input to the next turn's context without pausing the current step (Devin's "Ask" mode [36]); it is fast and has one inherent flaw, the current step may commit a stale decision before it ever sees the steering message. Resume-at-point combines steering with a rewind: the user sends a new instruction and rewinds to an earlier checkpoint, and the runtime replays forward from there with the new instruction in context.
Cooperative pause exposes the runtime's deepest coupling, the cancellation-awareness cascade, and its mechanism is the reason cancellation is so often only partly effective. Cancellation is exactly as effective as its most-blind hop. The harness can see the flag instantly, but the flag has to travel down every layer that might be mid-execution: the model call has to honor its context deadline, the tool dispatch layer has to propagate cancellation into the tool, the sandbox command has to respect SIGTERM, and the MCP call has to respect RPC-level cancellation. A model call that ignores its deadline holds the session for tens of seconds past cancel. A sandbox command that ignores SIGTERM holds it for the full grace period. An MCP server with no cancellation support either blocks until the RPC times out or leaks an orphaned call. The practical consequence is that "the runtime supports cancellation" is a claim about every hop in that cascade, not just the top one, and a single uncooperative layer makes the cancel cosmetic.
The failure modes follow from the mechanism. Stale steering: a queued message becomes meaningless when the current step ships the very decision the user was trying to redirect. Leaked resources on hard cancel: a kill that does not unwind leaves orphaned sandbox pods, MCP connections, and temp files. The interrupt handler as an attack surface: an interrupt flag any caller can set, without authentication, lets a compromised tool or MCP server denial-of-service the harness, which is why the verb has to be authenticated even though enforcement policy lives elsewhere. And approval latency: a cooperative pause that waits synchronously for a human holds compute for the entire wait, which for an overnight approval is a real cost and failure-mode problem (long-held connections, model keep-alives) rather than a free pause.
This is why interruption is a primitive and not a feature. The decision about what requires approval belongs to the governance fabric. The pause that lets the approval happen is this runtime's verb. A platform that bolts approval onto a harness without a first-class pause ends up with one of two bad outcomes: hard-cancel-and-restart on every approval (expensive and user-hostile), or policy checks that only fire at the step boundaries convenient for the harness rather than the ones the policy actually wanted. The quality of human-in-the-loop control is bounded by the quality of this primitive.
Tool registry and per-turn selection
Dispatch is how a tool runs; the registry is how the model learns the tool exists. The question every runtime has to answer is which tools the model sees in a given turn, and how they were chosen. It is orthogonal to transport (MCP versus HTTP versus local function) and to statefulness.
A static flat list registers every tool at agent creation and sends them all in every system prompt. It is simple and runs out at roughly 30 to 50 tools, because context cost and model attention both degrade as the catalog grows, function-calling accuracy falls off as the tool count rises, and robustness suffers specifically when irrelevant tools are present [37] [38]. Dynamic tool-RAG embeds the schemas and retrieves the top-k most relevant per turn, which scales to thousands of tools at the cost of a retrieval layer with its own error modes (the wrong tool retrieved, the right tool not retrieved). Hierarchical namespacing with mount and unmount shows the model a pruned subset per phase (read-only tools while understanding the problem, write tools while making the fix), which requires the runtime to track phase and swap lists explicitly. Model-driven discovery gives the model a list_available_tools tool and lets it ask, which raises the ceiling but makes discovery quality a function of model capability the runtime does not control.
The reason selection is its own concern, separate from the gateway that aggregates transports, is that aggregation and curation are different jobs: a runtime can have a perfect MCP gateway and still fail by presenting all 400 aggregated tools to every turn. The failure modes are concrete. Tool-name collisions, two servers both exposing list_issues, force the model to disambiguate by guessing, mitigated only by forced namespacing (github.list_issues, linear.list_issues). Schema bloat, 400 descriptions dominating the cost of every turn, is what tool-RAG and mount/unmount exist to fix; this is the one place the consumed model property bites the registry directly, because the bloat lands on the same attention budget the model needs for the task. Tools that exist but the model never calls, because the description is too abstract to pattern-match, are visible only through selection-rate observability. And the security-flavored one, tool-poisoning: Invariant Labs' mcp-injection-experiments showed that a malicious tool description at the catalog layer can inject instructions into the model through the system prompt, bypassing the user prompt entirely. That last one is why the registry is not a neutral lookup table, what it admits to the catalog is what it admits to the model's instructions.
Where this leaves the human
The thread running through why Latere exists is that the most important intelligence in an autonomous system is the one you cannot see: the person who set the direction and drew the boundaries. The execution runtime is where one of those boundaries becomes a concrete verb. Every other primitive can describe authority in policy; the runtime is the only place that can actually stop the loop. The pause that a human-in-the-loop approval depends on is not a configuration flag and not a feature layered on top, it is a first-class primitive that has to be threaded through every hop of the cancellation cascade or it is cosmetic.
That is the bet this primitive makes. The agent runs the loop at full speed. But the verbs that let a person interrupt it, redirect it, fork it to try another path, or kill it outright are built into the runtime from the start, not retrofitted after the first runaway. Human authority over a running agent is exactly as real as the runtime's ability to pause, and that is a property you design in or do without.
Latere's Wallfacer is the surface that turns this runtime's pause-and-resume verb into a product, a person reviewing and redirecting agent work at every step; the hub places it among the other primitives.
References
[1] OpenAI. "Sycophancy in GPT-4o: What happened and what we're doing about it." 2025. OpenAI
[2] ZenML. "What 1,200 Production Deployments Reveal About LLMOps in 2025." ZenML
[3] Deepchecks. "How Prompt Updates Drive Most Incidents." 2025. Deepchecks
[4] MLflow. "Prompt Registry for LLM and Agent Applications." MLflow
[5] Portkey. "Canary Testing for LLM Apps." 2025. Portkey
[6] Model Context Protocol. "The 2026 MCP Roadmap." MCP Blog
[7] Claude Code Issue #30224. "Auto-reconnect SSE MCP servers after server-side restart." GitHub
[8] MCP Python SDK Issue #520. "MCP Server Session Lost in Multi-Worker Environment." GitHub
[9] Model Context Protocol. "MCP Transport Future: Streamable HTTP Replaces SSE." December 2025. blog.modelcontextprotocol.io
[10] Model Context Protocol. "Transports, Mcp-Session-Id and Last-Event-ID." Spec 2025-11-25. modelcontextprotocol.io
[11] Claude Code Issue #27933. "OAuth token refresh race condition with multiple concurrent CLI processes." GitHub
[12] Claude Code Issue #24317. "Frequent re-authentication required with multiple concurrent sessions." GitHub
[13] IETF RFC 8707. "Resource Indicators for OAuth 2.0." RFC Editor
[14] Anthropic. "Context Engineering: Memory, Compaction, and Tool Clearing." Claude Cookbook, 2026. Anthropic
[15] "Cursor vs Claude Code vs Windsurf: Which One Handles Context Loss the Worst?" dev.to, 2026. dev.to
[16] L. Lindenbauer et al. "The Complexity Trap: Simple Observation Masking Is as Efficient as LLM Summarization for Agent Context Management." JetBrains Research / TU Munich, 2025. arXiv:2508.21433
[17] "ACON: Context Compaction for Long-Horizon Agentic Tasks." October 2025. arXiv:2510.00615
[18] Cognition. "Rebuilding Devin for Claude Sonnet 4.5: Lessons and Challenges." 2025. Cognition
[19] R. Du et al. "Context Length Alone Hurts LLM Performance Despite Perfect Retrieval." 2025. arXiv:2510.05381
[20] N. Hong et al. "Context Rot: How Increasing Input Tokens Impacts LLM Performance." Chroma Research, 2025. Chroma
[21] C. Davis. "Durable Execution meets AI." Temporal, 2025. Temporal
[22] C. Poly. "Durable Execution: The Key to Harnessing AI Agents in Production." Inngest, 2026. Inngest
[23] S. Ewen, G. van Dongen, I. Shilman. "Durable AI Loops: Fault Tolerance across Frameworks." Restate, 2025. Restate
[24] "AWS Outage and the Kiro AI Bot: A Post-Mortem." December 2025. singhajit.com; InfoQ
[25] M. Kleppmann. "How to do Distributed Locking." 2016. martin.kleppmann.com
[26] CrewAI. "Multi-Agent Framework." crewai.com
[27] OpenAI. "Agents SDK: Lifecycle Hooks and Handoffs." 2025. openai.github.io
[28] OpenAI. "Swarm: Educational Framework for Multi-Agent Orchestration." github.com/openai/swarm
[29] Google, Microsoft et al. "Agent-to-Agent (A2A) Protocol." 2025. a2aprotocol.org
[30] "Understanding Multi-Agent LLM Frameworks: A Unified Benchmark and Experimental Analysis." 2026. arXiv:2602.03128
[31] "Single-Agent LLMs Outperform Multi-Agent Systems on Multi-Hop Reasoning Under Equal Thinking Token Budgets." April 2026. arXiv:2604.02460
[32] J. Geng, G. Neubig. "Effective Strategies for Asynchronous Software Engineering Agents." CMU, 2026. arXiv:2603.21489
[33] DEV Community. "The $47,000 Agent Loop." 2025. dev.to
[34] M. Cemri et al. "Why Do Multi-Agent LLM Systems Fail?" NeurIPS 2025 Datasets and Benchmarks Track. OpenReview
[35] LangChain. "LangGraph Interrupts." 2025. LangChain Docs
[36] Devin Docs. "Ask Devin." Devin
[37] F. Yan et al. "The Berkeley Function Calling Leaderboard (BFCL): From Tool Use to Agentic Evaluation of Large Language Models." ICML, 2025. OpenReview
[38] "ACEBench: A Comprehensive Evaluation of LLM Tool Usage." Findings of EMNLP, 2025. ACL Anthology