R&D Management 18 min read

Pi vs OpenCode vs DSH: Where Does the Harness Put the Complexity?

A recent Agent Harness test comparing Pi, OpenCode, and DSH shows Pi completing 20 of 30 tasks at $0.028 per task versus OpenCode's 14 tasks at $0.195, while the article analyzes how each system distributes complexity, handles extensions, server boundaries, and runtime composability, highlighting trade‑offs for real‑world migrations.

Architect
Architect
Architect
Pi vs OpenCode vs DSH: Where Does the Harness Put the Complexity?

Recent Agent Harness testing with DeepSeek V4 Flash and a shared MCP toolset ran 30 cross‑application tasks: Pi completed 20 tasks (≈$0.028 per task), OpenCode completed 14 tasks (≈$0.195 per task). DSH was not part of this round.

These tasks involve multi‑system data flows (e.g., extracting Gmail tickets, writing to Google Sheets, supplementing account info, and posting summaries to Slack) with constraints such as bait tickets, immutable records, and required state tracking. Differences in tool descriptions, prompts, timeouts, caching, retries, and state recovery cause the same model to follow divergent execution paths, and the Harness outside the model determines those paths.

Complexity Placement

Think of an Agent as a continuously working developer colleague; the model decides the next step but knows nothing about who created a file handle or whether a Slack message was delivered. Harness supplies context, executes tools, and handles failure recovery.

The three systems distribute complexity differently:

Pi keeps the inner loop short, focusing on per‑task inner ring and Extension runtime.

OpenCode packages common paths as a product, using Server, Instance, and Session to organize multiple clients.

DSH pushes responsibility further down, covering Provider, Consumer, scope, replacement, and exit within the runtime.

Pi: Short Inner Ring

Pi’s default tools are read, bash, edit, and write. MCP, sub‑Agent, planning mode, and approval UI are added via TypeScript Extensions.

Extensions can register tools, commands, providers, UI, modify prompts, listen to session events, and persist state. Example: a code‑review extension launches a language server; a file‑watch extension monitors changes. No long framework chain exists between the call point and execution.

Pi leaves workflow differences to Extensions. Four default tools cover read, modify, execute, and verify; additional capabilities are added per project.

Mario Zechner reported a Pi run with DeepSeek V4 Flash processing ~1 billion input tokens, cache hit rate 99.93 %, total cost $2.65. Stable request prefixes improve cache hit and reduce cost more than changing the model.

Short inner‑ring costs appear in resources created by extensions (language server, file watcher, PTY, temporary directories, network connections). Pi’s lifecycle events ( /reload, session_shutdown, session_start) illustrate boundary handling; reload does not automatically discard old command stacks, so the docs require treating reload as the end of the current handler and cleaning resources in session_start / session_shutdown.

Session records are JSONL with id and parentId. Commands /tree, /fork, and /clone create new session files for history navigation, not for plugin dependency graphs.

OpenCode: Server Holds the Boundary

OpenCode’s core choice is to expose the Agent as a stable service product. Running opencode starts a TUI client; the server provides Agent, tools, session, and project state. opencode serve offers an OpenAPI 3.1 interface for desktop, IDE, scripts, or SDKs, and /event streams SSE events so clients need not block a terminal process.

The server maintains an InstanceStore per project directory, caching the Instance with configuration, plugins, LSP, formatter, snapshot, VCS, etc. Disposing an Instance clears its state. Plugins attach to this boundary, exposing hooks such as chat.message, chat.params, tool.execute.before/after, permission.ask, and shell.env. Their state is scoped to the Instance; disposal calls dispose().

Permission handling returns allow, deny, or ask based on tool and path rules; approval and rules belong to the current Instance. Plugins run in the same Node.js process, so external resource access depends on deployment and plugin code.

Session persists messages, parts, tool calls, cost, token usage, permissions, and parent‑child relations. The HTTP API supports continue, abort, fork, revert, and recovery. Unlike DSH’s “model‑visible means logged” model, OpenCode’s session events are defined by its own projection layer.

Composio testing showed OpenCode completing 14 tasks with median latency 129.7 s, while Pi took 132.2 s; success‑rate differences likely stem from tool orchestration, prompts, retries, or state recovery. A single public test cannot label a product permanently.

DSH: Runtime Composable

DSH treats the entire Agent Loop as plugins. Core kernel includes Context, Service, Fiber, Event, and Loader; most Agent capabilities are mountable, replaceable, and revocable.

Three concepts can be confused:

Plugin tree – what is actually loaded. dsh --profile web --dump-config prints the tree; presence in source does not guarantee activation.

Capability map – who provides and who consumes a capability (e.g., ctx.fs, ctx.shell, ctx.llm, ctx.web).

Session event log – records execution facts ( turn/start, step/start, assistant/*, tool/call, tool/result, agent/*, llm/stream, tools/*). The invariant “Model‑visible means logged” requires that anything sent to the model be reconstructable from logs, though not every log event is sent to the model.

Runtime profiles ( web, headless) decide process shape; Agent presets ( standard, code, minimal, cordis) decide which tools and prompts are active in a session. Multiple presets can coexist in the same process, each session using its own preset.

Provider replacement handling depends on whether the Consumer holds the Provider long‑term. Stateless providers (e.g., web search) are registered in a WebRuntime map and selected at call time; removing a provider does not require a full restart. Stateful services (shell, file system) require ctx.effect() registration and explicit disposal; effect can revoke listeners, handles, subprocesses, but cannot roll back already sent Slack messages, database writes, or file modifications.

Plugins and host run in the same Node.js process; inject declares dependencies but does not provide isolation. Profiles, patches, and capability maps cannot replace containers, VMs, remote sandboxes, or approval systems. DSH is still in Developer Preview; interfaces may change.

Migration Path

Replacing a local bash with a remote sandbox is a common migration. The three Harnesses differ in entry replacement, resource cleanup, session facts, and isolation boundaries, as summarized in the comparison table.

Typical pitfalls include avoiding duplicate Slack messages, ensuring old Provider connections and subprocesses are closed, and making sure Consumers exit before a new Provider starts. Documentation’s “hot‑replace support” is insufficient; lingering PTYs cause real failures.

Selection Rationale

Pi offers a short, transparent inner loop, suitable for teams willing to maintain Extension lifecycles. OpenCode provides a stable server API and shared entry point, reducing integration effort. DSH’s plugin tree, capability map, and event log are worth the learning cost when Provider, host, session scope, and dynamic replacement become primary concerns.

The Composio numbers remind us that Harness behavior—not just the underlying model—affects real‑world performance. Failure recovery, Provider turnover, and plugin over‑reach are often more important than raw ranking.

Composio numbers reflect the specific test configuration; DSH remains in Developer Preview; architecture judgments are based on verified source, official docs, and public discussions.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

pluginExtensionServerAgent ArchitecturePiOpenCodeHarnessDSH
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.