Why an Agent Canvas Needs a Control Plane

OpenHands Agent Canvas is the current product at the center of the OpenHands frontend repository: a self-hosted control center for starting, watching, and automating work performed by coding agents. The important question here is not how to use one more chat window, but how a single interface can coordinate different agents and different places where those agents run without pretending that the interface owns execution. Understanding that distinction gives the reader a practical way to judge what Canvas makes portable, what remains backend-specific, and why deployment is part of the product’s meaning.

The phrase “control plane” can sound like infrastructure jargon. In this case it names a useful division of labor. A control plane is the place where a person selects an execution target, supplies intent and settings, observes state, and initiates transitions. It does not have to be the place where commands run or files are changed. Agent Canvas is valuable precisely because it sits above those runtime details while remaining accountable for the handoffs that make them coherent.

The product is a coordination surface, not an agent

A coding agent normally arrives with its own interface: a terminal command, a conversation loop, a set of tools, and a way to reach a model. That is enough for a single developer working in a single environment. It becomes less sufficient when work must move between a laptop and a server, when a team uses more than one agent, or when a recurring task should run without someone keeping a browser tab open. The user then needs a stable place to choose the environment, preserve context, inspect progress, and return to the resulting work.

Canvas addresses that coordination problem. Its interface presents conversations, terminals, files, browser-related surfaces, settings, backends, integrations, and automations as parts of one product. It can run the built-in OpenHands agent, connect to external agents such as Claude Code, Codex, and Gemini CLI through the Agent Client Protocol, and work with local, remote, or hosted backends. These options do not mean the agents are interchangeable in every detail. They mean Canvas has a common place to express the user’s intent and a set of adapters that translate that intent into the protocol expected by the selected runtime.

That is a different responsibility from being the agent. Canvas does not decide how an LLM reasons, execute a shell command in the browser, or provide the isolation of a workspace. The active backend does those things. In the local OpenHands arrangement, the Agent Server receives the conversation request and owns the agent, tools, workspace, events, and server API. In an ACP arrangement, the Agent Server may spawn an external command as a subprocess and relay its turns. In an automated arrangement, an Automation service decides when work should be dispatched, while the Agent Server and SDK execute the resulting conversation.

The distinction matters because it prevents a common misunderstanding: a polished interface can make several services feel like one application, but it cannot remove their boundaries. If an agent edits a file, the authority comes from the backend and the workspace it controls. If a model credential is used, it is held and exported by the configured runtime rather than conjured by the screen. If a scheduled task runs, the scheduler and the execution service each own a different part of its lifecycle. Canvas can make those relationships visible and manageable; it cannot honestly collapse them into a single “AI” component.

A map of the actors and their authority

The simplest way to understand Agent Canvas is to follow a user’s intention outward. The person interacts with Canvas. Canvas resolves an active backend and sends a typed request through its service layer. That backend may be local, remote, or hosted. The Agent Server then establishes a conversation and supplies the execution environment. The selected agent—OpenHands directly or an ACP subprocess—acts within that environment. A separate Automation service can initiate the same kind of work from a schedule or event. Workspace files and runtime credentials stay on the backend side of this boundary.

flowchart LR person["Developer"] --> canvas["OpenHands Agent Canvas"] canvas --> active["Active backend"] active --> local["Local host"] active --> remote["Remote host"] active --> cloud["Cloud service"] active --> server["Agent Server"] server --> openhands["OpenHands agent"] server --> acp["ACP agent process"] active --> authority["Workspace and credentials"] canvas --> automation["Automation service"] automation --> server

The diagram is deliberately asymmetric. Canvas points toward choices and requests; the backend points toward authority. The local, remote, and Cloud labels describe where the selected backend is situated, not three versions of the frontend. The Agent Server is shown beneath that backend because it is the runtime boundary that receives agent work. Automation is shown as another entry path into that runtime, not as a second agent that competes with it.

This arrangement also explains why the repository is divided into several projects. Agent Canvas owns the React and TypeScript interface, frontend state, backend selection, and local-stack orchestration. The OpenHands software-agent SDK repository owns the Python SDK, Agent Server, tools, conversations, workspaces, events, and canonical API. The TypeScript client provides the browser-facing typed access to that API. The Automation repository owns definitions, scheduling, webhooks, run history, and dispatching. The Extensions repository supplies reusable skills, plugins, automations, and integrations. A feature that crosses those boundaries must preserve the contract between them rather than quietly reimplementing one layer in another.

For a reader, the practical test is simple: ask where the next state transition occurs. Clicking “start” is a Canvas action, but creating a conversation is an Agent Server or Cloud operation. Choosing a model is a settings action, but obtaining a response is a provider and runtime action. Viewing a run is a Canvas action, but changing a scheduled task from pending to running belongs to the automation and execution services. The question “which layer owns this transition?” is more informative than “where is the button?”

The local launcher makes these layers feel less cumbersome without making them disappear. It can start the frontend, Agent Server, and Automation backend behind one ingress address. Requests for automation paths go to the automation service; API and socket traffic go to the Agent Server; other paths serve the frontend. A user sees one entry point, while the launcher manages several processes, ports, readiness checks, and shared authentication. This is composition, not fusion.

Canvas also passes a structured description of available runtime services into the agent context. The agent can be told which address represents its Agent Server, which address reaches Automation, and which routes are available from inside its environment. It is instructed to trust that description instead of guessing ports. That small mechanism reflects the broader role of a control plane: it turns deployment knowledge into explicit context at the moment it matters, reducing the chance that an agent will confuse the service it runs inside with a neighboring service.

Portability has a cost: the backend remains the boundary

The promise of a common surface becomes meaningful only when we ask what can actually move. A user’s goal can move easily: “review this repository,” “prepare a report,” or “respond to this event” can be expressed through the same Canvas. The runtime state cannot move so freely. A conversation belongs to a backend, a workspace path has meaning on a particular host, and credentials are valid only where the relevant service can use them. Portability is therefore not the elimination of differences; it is the disciplined management of differences.

This is why backend choice changes both capability and risk. A local backend may be convenient because a provider’s existing login is available on the same machine and because the user can reach local files directly. A remote or Cloud backend may be better for always-on work or shared access, but it introduces a different workspace, authentication flow, and recovery lifecycle. Switching backends must invalidate or re-key data so that settings, repositories, conversations, and other cached results from one authority are not interpreted under another. A conversation identifier that looks valid as a string can still be meaningless on the newly selected backend.

The security consequence is even more direct. The source warns that running the Agent Server without a sandbox gives the agent access to the host filesystem, shell, environment, and network. Docker can narrow that reach to the projects directory mounted into the container, but it does not make those mounted projects harmless. A public VM deployment needs network restrictions, loopback-bound internal services, deliberate API-key handling, and transport protection before it is exposed beyond a trusted network. These are not optional decorations around the product. They determine the authority that a successful agent action will have.

The frontend itself has a related boundary. The bundled editor can be routed under the same browser origin as Canvas so that a deployment exposes one public port. A path prefix makes routing convenient, but it does not create an origin-level security wall. The self-hosting guidance notes that script running on that origin may read browser localStorage containing session keys for registered backends. The lesson is broader than this one editor: a clean-looking surface does not prove isolation. Readers must distinguish visual separation, URL routing, process separation, workspace scoping, and security boundaries.

That distinction gives the rest of this series its guiding question: when Agent Canvas makes an action feel simple, which layer owns the next transition, and what authority does that layer possess? The answer will lead from repository boundaries to backend state, from backend state to conversation creation, and from conversation creation to agent choice, automation, and deployment. Canvas is most useful when it makes those handoffs dependable and understandable. It becomes dangerous when the convenience of one interface encourages anyone to forget where the real execution authority remains.

References