All posts

May 26, 2026

What is an execution layer?

An execution layer turns submitted code plus workspace context into an audited run: source resolution, MCP pooling, sandbox isolate, orbit primitives.

By Umang BhallaPublished Updated
  • execution layer
  • sandbox
  • MCP
  • control plane
  • architecture
  • orbit
  • codemode

An execution layer is the server-side code-execution plane of a control plane: the component that takes a submitted program plus workspace context and turns it into an audited run. It resolves which sources and credentials the workspace has enabled, dispatches the program inside an isolated runtime, brokers every outbound tool call, exposes workspace-scoped primitives to the running code, and writes the resulting run and spans back to durable storage. Harbor’s execution layer lives primarily inside the control-plane API — centered on the execute API route, the sandbox host runtime, and the orbit runtime module — and is what the hrbr CLI, the local MCP stdio adapter, and future web-triggered entrypoints all submit work to.

Why an execution layer exists

Without an execution layer, every agent calls every MCP tool from inside its own context. The pattern degrades quickly. The agent has to load the full tool catalogue into its prompt, ship multi-step plans as chains of single tool calls (each round-tripping through the model), and hold raw provider tokens in the same process that is also generating responses. There is no isolation between “the part that reasons” and “the part that writes to GitHub”. There is no shared state across runs and no shared state across agents on the same team. There is no durable shared execution record, because the trace lives inside whatever local logging the agent happens to do.

An execution layer collapses those problems by moving code execution out of the agent context and onto a server-side plane. The agent submits a program; the plane runs it. The program can fan out to a hundred tool calls and return one structured result, which is far cheaper than streaming a hundred tool-call turns back through the model — this is the token-efficiency argument behind the codemode pattern. The program runs in an isolate the agent does not share, so credentials and pooled clients never reach the agent’s heap. Every call inside the program is recorded with workspace, agent, tool, latency, and error metadata, so a security review or a debugger can inspect what actually happened.

Anatomy of Harbor’s execution layer

Five concerns sit inside the layer. Each one has a concrete home in the control-plane API.

Source resolution

A hrbr execcall lands at the execute API route, which scopes the request to a workspace, validates the agent attribution headers against the workspace’s announced agents, and resolves the set of plugin sources enabled for that workspace before any code is dispatched. Source resolution is workspace-scoped on purpose: the same program submitted by the same agent sees a different source list, different policy rules, and different credentials when it executes for a different workspace. Policy preflight runs before the code starts and audits every decision, so denial happens before the isolate boots.

Source resolution
Workspace scope + attributed agent identity + enabled plugin sources + policy preflight, computed before the program runs. Determines which tools the program can even reference and which credentials the host may decrypt on its behalf.

MCP client pooling and host-side dispatch

When the program calls hrbr.plugins.github.repos.get(...), the call does not open a fresh MCP connection per invocation. The host builds one pooled MCP client per resolved source and keeps it alive across calls in the same run. A single host-side dispatcher receives {key, args} from the isolate over structured-clone RPC and routes to the right tool. Connection state stays in the host process; the program only sees a typed proxy.

MCP pooling
One pooled MCP client per source per request, dispatched from a single trampoline function. Avoids per-call connection cost and keeps credential handles confined to the host heap.

Sandbox isolate execution

The program itself runs in a separate Cloudflare Worker V8 isolate, spun up via the workerd LOADER binding and @cloudflare/codemode’s dynamic worker executor, governed by the sandbox host runtime’s contract. This is a process-level boundary, not a JavaScript sandbox: user code cannot access host-side closures, cannot reach the pooled MCP clients or decrypted credentials, and cannot pollute host prototypes. The only channel between the isolates is JSON-RPC over structured cloning. The host hands the isolate a single host binding — a host stub minted per run — which the runner template wraps in proxies so user code sees hrbr.* as ordinary objects. A default execution timeout, memory, and outbound fetch policy are enforced at the isolate boundary by workerd.

Sandbox isolate
Per-run V8 isolate via workerd LOADER + codemode. No filesystem, no ambient network — only the host RPC channel and whatever the runner template injects. Replayable because the inputs (code, plan hash, source list) are content-addressed.

Orbit primitives

Inside the isolate, user code has access to a small set of workspace-scoped runtime primitives. These are hrbr.storage (R2, prefixed {workspaceId}/user/{key}), hrbr.cache (KV, keyed ws:{workspaceId}:{key}), hrbr.db (one D1 database per workspace), hrbr.ai (AI Gateway with workspace/run attribution), hrbr.tools (tool search and signature lookup), and hrbr.jobs (invoking previously published defineJob versions). All of them live in the orbit runtime module and record usage to a usage log so it is accounted to the run. Because every key and call is server-side prefixed by workspace, two agents in two workspaces cannot collide on hrbr.storage.put({ key: "results" }).

Run and invocation logging

Every exec produces one run row plus a tree of spans in D1. The route records the run and its root span before dispatching, then finalizes both on completion. Inside the isolate, each tool call becomes a child span — workspace, agent, plugin, tool, latency, error — and each orbit.* call appends to a usage log. The shape is the same whether the run completes synchronously in exec mode or durably in workflow mode — the route auto-routes to Cloudflare Workflows when the user code references step.do / step.sleep / step.waitForEvent so a long-running pipeline still produces the same audit record. Audit is a first-class output of the layer, not a logging side-effect bolted on.

Execution layer vs gateway vs control plane

These three categories are often collapsed and they should not be. An MCP gateway is a proxy: it forwards tool calls across the wire and adds auth, rate limits, or transport bridging. A control plane is the surrounding workspace infrastructure that owns discovery, credentials, registry, policy, and audit. An execution layer is the runtime — the place where code actually runs after the workspace has decided it is allowed to. The gateway question is “can this call reach the upstream?”. The control plane question is “does this workspace have this tool installed and is this agent authorized?”. The execution layer question is “in which isolate, with which pooled clients, with which primitives, with which audit, does the submitted program now execute?”.

Harbor implements all three. The gateway responsibilities (outbound MCP, transport bridging, OAuth interception) sit beside the control-plane responsibilities (discovery, credentials, policy, runs) and the execution-layer responsibilities (source resolution, pooling, sandbox isolate, orbit, span tree). The execution layer is the deepest of the three and the one a thin gateway product cannot subsume — see control plane vs MCP gateway for the gateway / control-plane breakdown.

What ingress paths feed the execution layer

The execution layer is shared regardless of how work is submitted. Today three ingress paths reach it. The hrbr CLI’s hrbr exec command (in apps/cli) is the primary developer surface and posts to POST /plugins/execute after announcing the agent. The local MCP stdio adapter (packages/sdk/localmcp, exposed via hrbr serve mcp) bridges any MCP-speaking client into the same route. Web-triggered exec entrypoints — buttons in apps deployed via deployApp, scheduled job triggers, workflow resumes from external events — submit work into the same route from the control plane itself.

This separation matters. hrbr and localmcp are ingress; they do not ship a separate local JavaScript runtime. Execution happens server-side in the Harbor execution layer regardless of which client started it, which is why a run launched from a CLI terminal, a docked agent, and a web button all share the same audit shape and the same workspace-scoped state.

Why the execution layer must be on the server

Putting execution on the server is not an arbitrary preference. The MCP client pool has to be shared across runs to amortize connection cost; that pool cannot live inside an agent process that may be killed mid-task. Decrypted credentials cannot reach the agent’s heap if the agent context is also where untrusted model output materializes — the moment a raw token is one prompt-injection away from an exfiltration tool call, the boundary is meaningless. The audit story only works when the audit writer is on the same side as the network calls it claims to be auditing; a client-side log can be tampered with or simply lost when a process crashes.

Server-side execution has costs. A round trip to the plane adds latency over in-process execution. The isolate boots are not free, although codemode amortizes the cost across many tool calls inside one program. Some workloads — small local scripts that touch no team-owned credentials and need no audit — are genuinely worse off paying for the layer. For everything that does touch shared credentials, shared state, or compliance, the tradeoff goes the other way: the latency of a network hop is much smaller than the cost of a credential leak or an unprovable audit gap.

When you don’t need an execution layer

If a single developer is wiring one local MCP server into one personal agent, running it in-process is fine. Scripts that touch only public APIs, do not need durable audit history, and do not need workspace-scoped credentials are not worth the round trip. The execution layer starts paying for itself when more than one agent or more than one human share tools, when memory has to survive a process restart, when credentials must not reach the agent context, or when a security review will ask what every agent did with every credential last quarter.

If your team is past that line, connect a workspace and try hrbr exec against a real plugin source. The full primitive surface lives in the Orbit runtime and Exec docs. If you are still picking between a gateway, a control plane, and an execution layer, the /compare breakdown walks through where each vendor lands.

Keep reading

Evaluating MCP control planes? See the comparisons hub for per-vendor breakdowns, or connect a workspace to try Harbor.