# Remote Toolsrv Architecture Ollie keeps the agent loop local and moves tool execution to a remote host when a session has a `remote` target. The remote boundary is the same authenticated 9P `toolsrv` protocol used for local execution. There is no separate `ollie-remote` binary, JSON-RPC protocol, or in-process `Runner` adapter. ## Architecture ```mermaid flowchart LR A[olliesrv agent loop] --> C[ToolsrvConn] C -->|local Unix socket or SSH-forwarded Unix socket| T[toolsrv] T --> R[remote registry] T --> E[remote tool execution] E --> S[remote sandbox] E --> W[remote working directory] ``` The agent uses `ToolsrvConn` for both local and remote sessions. It lists tools, loads and unloads tools, calls tools, reads background-process output, and handles cancellation through the same 9P client methods. Only the process and socket setup differ. ## Session configuration A session’s `remote` value is an SSH target. It may be supplied during session creation or as a session configuration value: ```text remote=user@devbox ``` The target may include a port in `host:port` form. `session.SetupToolServer` selects `SpawnRemote` when the target is non-empty. The session stores the target and reuses the resulting `ProcessKeeper` and connection when agents are created or reloaded. Remote execution therefore moves: - the toolsrv process; - tool metadata and installed tool commands; - the working directory used by tool calls; and - sandbox enforcement. The following remain local: - the agent loop and conversation history; - LLM backend calls and credentials; - prompt assembly and agent configuration; - session persistence and the local 9P control namespace; and - GUI or other local interaction layers. ## Startup and deployment `toolclient.SpawnRemote` performs the following sequence: 1. Validate that the local Ollie configuration directory exists. 2. Create a local forwarded socket path and a temporary remote socket path. 3. Start `ssh` with local Unix-socket forwarding (`-L`). 4. Stream a gzipped tar archive of the local Ollie configuration directory to the remote shell; the archive contains the toolsrv binary and configuration, but no external sandbox executable. 5. Run a remote bootstrap script through `bash -s`. 6. Extract the archive into `${XDG_CACHE_HOME:-$HOME/.cache}/ollie`. 7. Set remote `XDG_CONFIG_HOME` and prepend the cached `bin` directory to `PATH`. 8. Start the cached `toolsrv` with the requested working directory, remote socket, session ID, and optional `--yolo` flag. 9. Wait for the toolsrv listening message and the local forwarded socket. 10. Return a managed `Process` whose socket path is local but whose server runs remotely. The transferred configuration supplies the remote tools directory and metadata. Remote discovery and metadata variants therefore describe the remote host’s available commands, files, operating system, architecture, and environment. The remote service is cached under `$XDG_CACHE_HOME/ollie` and is not installed system-wide. The bootstrap replaces the cache contents from the transferred archive for the session startup. ## Authentication and transport The client connects to the forwarded local socket with `DialToolsrv`. The toolsrv server still performs the normal 9P `Tauth` exchange. The connection receives a secret and session token, and the client sends the session and agent identities used to scope registry state and process requests. SSH protects the forwarded socket transport. 9P authentication remains enabled on the toolsrv protocol. The remote path does not introduce a second application protocol. ## Tool calls and results A remote tool call follows the normal toolsrv path: ```text agent └─ ToolsrvConn.CallTool(ctx, name, args) └─ authenticated 9P proc/new └─ remote toolsrv registry lookup └─ remote metadata command resolution └─ remote sandboxed process └─ structured ToolResult ``` Tool metadata is loaded from the remote configuration. The agent receives the remote catalog and renders the same tool definitions and documentation into its runtime. Background calls use `proc/new.bg`. Output and exit state remain available through the remote toolsrv process namespace. The client reads them through the forwarded connection. ## Cancellation and recovery Cancellation closes the active 9P request fid. The remote toolsrv cancels its request context, and `exec.CommandContext` terminates the remote child process. Closing the SSH-backed connection or cancelling the session context also terminates the managed SSH process and remote toolsrv process. `ProcessKeeper` owns the current process and can respawn it when a new connection is needed. For a remote session, respawning repeats the SSH bootstrap, configuration transfer, remote toolsrv startup, and socket forwarding sequence. Agent reloads dial a fresh connection through the keeper while preserving the session-level infrastructure. A dropped SSH connection does not silently replay a tool call. The failed connection or tool request returns an error; the keeper can establish a replacement toolsrv process for subsequent operations. ## Environment and prompt context The agent prompt is assembled locally, but environment facts describing the tool host must come from the remote process setup. `SetupToolServer` uses the remote process information when constructing the environment section. The current implementation reports the remote platform as Linux and does not yet detect the remote Git state in `SpawnRemote`; callers should not treat those values as full host discovery. The working directory passed to `SpawnRemote` is sent to the remote toolsrv `--cwd` argument. Tool commands execute relative to that remote directory, not the local caller’s filesystem. ## Sandbox Sandbox policy is enforced where the command runs. A remote tool call uses the remote toolsrv sandbox and the remote host’s filesystem, network, environment, and Landlock capabilities. The `--yolo` session option passes through to the remote toolsrv and disables enforcement for explicit development use. The local bypass broker is not a remote execution engine. Bypass requests and policy handling remain part of the toolsrv/olliesrv integration described in [`architecture-toolsrv.md`](architecture-toolsrv.md); the command itself executes on the remote host. ## Comparison with local execution | Concern | Local session | Remote session | |---|---|---| | Agent loop | Local | Local | | Toolsrv process | Local child process | Remote child process under SSH | | Client socket | Local Unix socket | Local forwarded Unix socket | | 9P protocol | Authenticated | Authenticated | | Tool registry | Local toolsrv | Remote toolsrv | | Tool commands | Local host | Remote host | | Working directory | Local path | Remote path | | Sandbox | Local toolsrv policy | Remote toolsrv policy | | Prompt assembly | Local | Local | | LLM calls | Local | Local | Remote execution is useful when the project, compilers, dependencies, or hardware live on another host while the user interface and model connection remain local. ## Implementation map | Responsibility | Implementation | |---|---| | Session selection and lifecycle | `cmd/olliesrv/internal/session/setup.go` | | Local and remote process spawning | `cmd/olliesrv/internal/toolclient/spawn.go` | | SSH bootstrap and archive transfer | `cmd/olliesrv/internal/toolclient/spawn.go` | | Authenticated 9P client | `cmd/olliesrv/internal/toolclient/toolsrv.go` | | Remote toolsrv service | `cmd/toolsrv/` | | Registry and metadata | `cmd/toolsrv/internal/registry/`, `toolsrv/metadata/` | | Execution and sandbox | `cmd/toolsrv/internal/exec/`, `cmd/toolsrv/internal/sandbox/` | The complete toolsrv service architecture is documented in [`architecture-toolsrv.md`](architecture-toolsrv.md). The agent-side integration is documented in [`architecture-core.md`](architecture-core.md).