GO TO A SECTION

↑ ↓ to navigate · Enter to openExplore all sections →
FDEInterviews logo
MLSys 2026

The OpenHands Software Agent SDK: A Composable and Extensible Foundation for Production Agents

OpenHands rebuilt its agent core around one event log and immutable configuration. In a 15-day side-by-side rollout, infrastructure-caused failures fell 61%.

Breakdown by FDE Interviews · 16 min read · Updated

About the original · 2025
AUTHORS
Wang, Rosenberg, Michelini, Smith, et al.
FROM
OpenHands
PUBLISHED
Nov 2025 · MLSys 2026
CITED BY
47Semantic Scholar · Oct 2026
IN THIS BREAKDOWN · 10 SECTIONS

You can read 18% of this breakdown.

01

The paper in one minute

OpenHands is an open-source platform for software agents. Its first architecture, which the authors call V0, assumed every tool call ran inside a sandboxed Docker container, separate from the process running the agent. That meant every conversation spanned two processes whose state could diverge. When the sandbox crashed and the agent kept going, or the reverse, the session was corrupted. Local execution, which the Model Context Protocol assumes, had to be bolted on with duplicate tool and MCP code. Configuration had grown to more than 140 fields across 15 classes and 2,800 lines, spread over separate hierarchies for the CLI, web UI, GitHub App and hosted service.

V1, the Software Agent SDK, rests on four rules. Isolation is optional: the agent runs in-process by default and moves into a container when you need one. Everything is immutable except one object: agents, tools and model settings are frozen Pydantic models, and a single ConversationState holds all mutable data. The agent core is a library that applications import rather than a codebase they share. Components are typed and replaceable, so a new tool or agent does not touch the core.

The state is event-sourced. Every message, tool call, observation, pause and condensation is an immutable event appended to a log, with each event persisted as its own JSON file and metadata in one base_state.json. Resuming a conversation means loading the metadata and replaying the events. The same Conversation(...) call runs locally against a folder, or, given a Docker or hosted workspace, serializes the agent to an agent server that runs it in a container and streams events back over WebSocket.

The paper backs this with production data. V0 and V1 served users side by side for 15 days, and failures attributable to the system rather than to model providers fell from 78.0 to 30.0 per 1,000 conversations.

THE IDEA, VISUALLY
ONE MUTABLE OBJECT, EVERYTHING ELSE CONFIG Immutable Agent, LLM, Tool specs, validated at construction (Pydantic) ConversationState base_state.json: status, stats, policy events/0001.json, 0002.json, ... append-only; only new events written AN AGENT STEP, AS EVENTS ActionEvent tool call risk check analyzer execute executor Observation result Resume = load base_state.json, replay events, find an action with no observation. Whether to re-run it is your problem. SAME CODE, LOCAL OR REMOTE LocalWorkspace in-process; subprocess on the host; no sandbox Docker / API workspace agent JSON → agent server REST + WebSocket events or Packages: sdk, tools, workspace, agent_server. MIT license. Docker image bundles the server, VS Code Web, VNC, Chromium. Sandboxing is opt-in; multi-tenant security audit is future work. ERRORS PER 1K CONVERSATIONS, 15 DAYS (TABLE 2) V0 total (printed) 78.0 V0 infrastructure 69.8 of which 401 auth 43.0 V1 total (printed) 30.0 V1 SDK errors 29.7 −61%; rows do not sum to the printed totals (gaps 8.2, 0.3) EVENT-SOURCING COST, 433 CONVERSATIONS (TABLE 3) median p95 358 events persist one event 0.20 0.31 — full replay 4.1 9.7 18.9 crash recovery 7.4 14.9 32.1 storage 380 KB 1.4 MB 3.4 MB milliseconds; text says recovery is under 20 ms at max SWE-BENCH VERIFIED, MATCHED MODELS (TABLE 4) Sonnet 4 V0 68.0 V1 68.0 Sonnet 4.5 V0 64.6 V1 72.8 the +8.2 is credited to extended thinking; no ablation
The SDK keeps one mutable object, the conversation state, and writes every step to an append-only event log, so a crashed run resumes by replay. The production gain came from removing a network hop between two pods, not from the log itself.
Research notes: the problem, approach and results
78.0 → 30.0

system-attributable errors per 1,000 conversations, V0 against V1, in a 15-day parallel production rollout

0.20 ms

median time to persist one event, on 39,870 events from 433 SWE-Bench Verified conversations

43.0 / 1k

V0 failures from one cause alone: authentication errors between two pods, removed by co-locating them

THE PROBLEM

OpenHands V0 grew from a research prototype into a product with a CLI, a web app, a GitHub integration and a hosted service. Every tool call ran in a separate sandbox process, configuration lived in four parallel hierarchies with 140+ fields, and benchmark code shared a repository with production. Sessions corrupted when one of the two processes crashed, and two runs with the same settings could behave differently.

THE IDEA

Make every component except one immutable. Agents, tools and model settings are validated, serializable configuration; a single ConversationState holds all mutable data as metadata plus an append-only event log, persisted one event per file. Run the agent in-process by default and move it into a container by swapping the workspace object, with a REST and WebSocket agent server doing the remote half.

THE RESULT

In a 15-day parallel rollout, system-attributable errors fell from 78.0 to 30.0 per 1,000 conversations. Persisting an event took a median 0.20 ms. With Claude Sonnet 4 on SWE-Bench Verified, V0 and V1 both scored 68.0%, so the redesign did not cost capability.

02

Why it matters to an FDE

If you have built an agent demo, you have built the V0 problems in small. A loop calls a model, a tool runs somewhere, and the only record of what happened is a list in memory. That works until the process dies halfway through a two-hour job, a customer asks why the agent deleted a file, or a second entry point (a Slack bot, a scheduled job) needs the same agent with slightly different settings.

The paper is a worked answer to three questions you will face when a pilot becomes a service.

Where does the truth live? One append-only log per conversation, written as it happens. It is your resume point, your audit trail and your debugging tool, and the paper measures its cost as negligible next to model calls.

What may change at runtime? Nothing except that log and a few status fields. Freezing configuration at construction is what made two runs with the same settings behave the same.

Where does the code run? Locally by default, in a container when a customer's security team or a multi-tenant service requires it, with the same agent code in both.

Read the production numbers carefully. Most of the 61% came from removing network calls between two Kubernetes pods. The authentication failures between those pods alone were 43.0 per 1,000 conversations. The lesson for your own deployment is to count the processes and network hops each agent step crosses. Each one is a failure mode that a better model cannot fix.

THE FULL BREAKDOWN

Understand the mechanism. Try it on a real problem.

Unlock this breakdown and 149 more papers.

Premium opens every paper in full, plus every answer, concept, course and guide on the site. One payment for six months of access.

6 months · One payment · No auto-renewal

Get Premium · ₹2,000 / $25
  • ◇1 architecture diagram
  • </>1 runnable code experiment
  • ▦3 results tables
  • ?5 interview questions with answers
  1. 03Key takeaways

    The design rules, the measured costs, what the numbers do and do not show, and three misreadings

    Free account
  2. 04How it works

    The event hierarchy, one agent step, the tool contract, condensation, security and the remote path

    Premium
  3. 05The numbers that matter

    The rollout, the persistence costs, the matched-model comparison and the benchmark table

    Premium
  4. 06Try it yourself

    Check the paper's arithmetic, then crash an event-sourced agent 2,000 times and resume it

    Premium
  5. 07Where it breaks

    What the rollout measures, the attribution gaps, the comparisons and the open security questions

    Premium
  6. 08Using it on a deployment

    Adopting the pattern or the SDK: prerequisites, a worked example and what to measure

    Premium
  7. 09Interview angles

    Five questions this paper prepares you for, with answer hints

    Premium
Back to the paper library →