Harnesses
How a project selects its default or experimental runtime, and which session features each supports.
A harness is the agent runtime inside a session’s sandbox. It runs the model loop, calls tools, and produces the transcript. A session uses either the default runtime or the experimental runtime.
Both harnesses read the same project: beeuni.yaml, the agent files in
agents/, the skills in skills/, the root AGENTS.md, and memory/. The
clients (web, CLI, TUI, mobile, SDK) read both through the same session API.
The differences are the session features in the
matrix below and the files each harness reads
for its own configuration.
How a session selects its harness
Beeuni decides when a session starts, restarts, or resumes. A running session keeps its harness until then.
| Rule, in order | Harness |
|---|---|
The project’s llm_gateway flag is off |
default runtime |
The project’s pi_harness flag is on |
experimental runtime |
beeuni.yaml sets runtime: pi |
experimental runtime |
| Anything else | default runtime |
- The experimental runtime calls models only through the Beeuni LLM gateway. A project with
llm_gatewayoff uses the default runtime, whatever the flag or the manifest says. See Models. runtimeis abeeuni_version: 2manifest key. A legacybeeuni.tomlproject cannot set it. See the manifest reference.pi_harnessis a per-project feature flag, off by default. See Feature flags.
To see which harness a session runs, read harness.id in the sandbox
daemon’s GET /beeuni/health answer: opencode or pi.
What each harness supports
A harness lists the optional session features it serves in the capabilities
array of GET /beeuni/health. A client hides a control when the session’s
capabilities lacks the id. The SDK check is
runtimeSupports.
Both harnesses
| Feature | default runtime | experimental runtime |
|---|---|---|
| Chat turns, streaming, stop | Yes | Yes |
Agent .md: prompt, model, variant, mode, permission, temperature, top_p, steps |
Yes | Yes. The experimental runtime does not apply options (provider options). |
Tool access per agent (agents.<name>.tools in beeuni.yaml: all, none, a list, exclude) |
Yes | Yes |
Per-agent permission rules and permission requests |
Yes | Yes |
Questions (question tool) |
Yes | Yes |
The project’s root AGENTS.md rules file, or CLAUDE.md when the root has no AGENTS.md |
Yes. The default runtime also reads the file in parent directories of /workspace, and reads /workspace while it runs a config release. |
Yes, the root file only. It is part of the system prompt of the session and of each subagent. The experimental runtime reads the release copy. |
Subagents (task tool), session.subagents |
Yes | Yes: general, explore (read-only), and each project agent with mode: subagent or all. A subagent cannot start another subagent. |
Skills (skills/ and the managed beeuni-* skills), with the agent’s skills grant |
Yes. The agent loads a skill with the skill tool. |
Yes. The system prompt lists each granted skill; the agent reads the file. |
Beeuni tools: web_search, image_search, scrape_webpage, memory, show. All five with no tools: key in beeuni.yaml; with one, the ones it lists as beeuni:<name> |
Yes | Yes |
Project tools (tools: in beeuni.yaml) |
Yes | Yes |
Config releases, config.release.v1 |
Yes | Yes |
Compact (summarize) the conversation, on demand and by itself near the model’s context window, session.compact |
Yes | Yes. A model request that overflows the window compacts and retries once. |
Project slash commands, session.commands |
Yes, from commands/ in the default runtime config directory. |
Yes, from the prompt templates in prompts/ in the experimental runtime config directory and in experimental runtime packages. The experimental runtime does not read the default runtime’s commands/. |
| Terminal in the sandbox (PTY) | Yes | Yes |
bash, read, write, edit, glob, grep tools; secrets in the shell; the beeuni CLI |
Yes | Yes |
The Beeuni tools and the project tools are harness-neutral:
the sandbox daemon runs one module per tool for both harnesses, with the same
names, arguments and output. The experimental runtime calls them in the daemon’s process; default runtime
calls them through a plugin the daemon writes. Both harnesses get the same
list: a Beeuni tool the project’s tools: key does not list is on neither. A
project that still has copies of the Beeuni tools in harnesses/opencode/tools/
keeps its copies on the default runtime until it deletes them.
The web tools follow the websearch (web_search, image_search) and
webfetch (scrape_webpage) permission keys on both harnesses. on the default runtime
these tools cannot ask: an ask rule denies them. on the experimental runtime an ask rule raises
a permission request. on the experimental runtime a memory command that changes a file follows
edit and view follows read; on the default runtime only a memory rule governs
the tool.
AGENTS.md on the experimental runtime
The experimental runtime puts the project’s root AGENTS.md in the system prompt as one section,
<project_instructions path="AGENTS.md">, after the agent’s prompt. A root
with no AGENTS.md gives CLAUDE.md instead, as on the default runtime. The experimental runtime reads no
AGENTS.md in a subdirectory or a parent directory.
- Source. experimental runtime reads the copy in the
config release and never the one in
/workspace: an edit in/workspacereaches the session after it merges to the base branch. With no release to serve (config.source: image-default), experimental runtime reads noAGENTS.md, as it reads no project skill. - When. experimental runtime reads the file when the runtime starts, when its configuration
reloads (a new release, a
/beeuni/envpush), and after a repository refresh. It does not read it before each turn. A new release reaches the next turn without a restart; a turn in flight keeps the old file. - Skipped. An empty file, a file that is not a regular file, and a symbolic link that resolves outside the repository add nothing. The last two write one warning to the daemon log.
- Check.
harness.details.agentsMdin the daemon’sGET /beeuni/healthnames the file experimental runtime loaded:source(releaseorworkspace),path,bytes, andsha(the first 12 hex characters of its sha256). It isnullwhen experimental runtime loaded none.
Standard harness only today
| Feature | Capability | default runtime | experimental runtime |
|---|---|---|---|
| Rewind to a message and restore it. Edit-and-resend uses rewind. | session.rewind |
Yes | No |
MCP servers (mcp in opencode.jsonc) |
session.mcp |
Yes | No MCP client. Connectors work on both harnesses through the beeuni connectors CLI. |
Todo list (todowrite tool) and the plan card |
session.todo |
Yes | No. The plan card stays empty. |
Attach the harness’s own terminal client (beeuni connect, TUI Alt+o) |
session.attach |
Yes | No. See TUI. |
Runtime config document (/global/config) |
session.config |
Yes | No. Agents and models come from the project on both. |
| Fork a session at a message | session.fork |
Yes | No |
| A shell command run as a turn | session.shell |
Yes | No |
| Model providers without the LLM gateway | — | Yes | No. The experimental runtime needs llm_gateway on. |
A experimental runtime session answers a request for a feature it does not serve with
501 feature_not_supported, or 404 for a document it does not have
(/global/config). It does not ignore the request.
Harness configuration files
Each harness has one directory for the files only that harness reads.
| default runtime | experimental runtime | |
|---|---|---|
| Directory | harnesses/opencode/, or opencode.config_dir |
harnesses/pi/, or pi.config_dir |
| Legacy directory | .beeuni/opencode/ |
.beeuni/pi/ |
| Contents | opencode.jsonc, plugins/, tools/, commands/ |
settings.json, extensions/, skills/, prompts/ |
| Extensions | Plugins and default runtime-only tools in that directory | experimental runtime packages in harnesses.pi.packages, and extension files in extensions/ |
A experimental runtime session does not read opencode.jsonc, plugins/, tools/, or
commands/. An default runtime session does not read the experimental runtime directory. A tool both
harnesses need is a project tool, declared in
beeuni.yaml, not a file in either directory.
The experimental runtime packages come from packages. A package can add tools that experimental runtime does not have, for example an MCP adapter or a todo tool. Beeuni loads the package; it does not test third-party packages.