Status: Research / deferred. Not in active development. Date: 2026-05-24
Navi currently runs all tools (terminal, filesystem, code_exec, ssh_exec) on the same machine as the backend server. Users who want Navi to manage their local dev machine must either:
ssh_exec to loopback to localhost (clunky, requires local sshd).The original idea — a "terminal client" that lets the browser execute commands on the user's local machine — was explored and rejected.
A browser-based client could theoretically receive a terminal command from the server, run it locally via a companion app or extension, and return stdout.
Agent.run_stream assumes tools are synchronous await tool.execute() calls inside a single Python process. A remote tool that waits for a browser response would freeze the entire agent loop or require a full async-state-machine refactor.terminal("npm install")? Requires device registry, affinity, and explicit routing.Conclusion: Browser-based client-side execution is architecturally incompatible with Navi's current synchronous tool loop and operationally too expensive.
A headless Navi node is a lightweight instance of the Navi backend (FastAPI + agent loop) without a web client. It runs on the target machine (e.g. a user's dev laptop, a VPS, a home server) and connects back to a central Navi server.
┌──────────────┐ WS/HTTP ┌──────────────┐
│ Browser │◄───────────────────►│ Central │
│ (web client)│ │ Navi Server │
└──────────────┘ └──────┬───────┘
│
│ WS outbound
│ (nodes register here)
│
┌───────────────────────────────────┼───────────────────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Headless │ │ Headless │ │ Headless │
│ Node A │ │ Node B │ │ Node C │
│ (dev laptop)│ │ (home NAS) │ │ (VPS) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
▼ local shell ▼ local shell ▼ local shell
terminal, filesystem, code_exec remain synchronous Python tools inside the node's process.If all nodes share one PostgreSQL database:
recalls will try to execute the same scheduled task. Needs claimed_by column or a leader-election mechanism per recall.messages array could overwrite each other. Needs row-level locking or instance_id partitioning.process_stale_sessions on every node would duplicate embedding work. Needs instance_id gating so only the central server or a designated node runs background workers.Direction: Tag every row with instance_id (central = main). Nodes only read/write rows assigned to them. The scheduler table gets a claimed_by atomic UPDATE.
The agent on the central server must know that terminal for profile server_admin should run on Node B, not locally.
Options:
server_admin has node_id: "home-nas". All tools in that profile execute on that node.remote_terminal, remote_filesystem) that forward calls to the node's REST/WebSocket API.spawn_agent spawns the subagent on a remote node via the node's API instead of locally.terminal and filesystem operate inside the container by default. Access to the host requires --privileged, --pid host, or explicit volume mounts, which weakens isolation.Direction: Provide both: Docker for sandboxed/isolated tasks, bare-metal install script for full host management.
Nodes must prove identity to the central server.
NODE_API_KEY) in .env.ws://central.navi/ws/nodes/{node_id}) for real-time task streaming.stream_start, tool_started, stream_delta, stream_end) so the central server can forward node events to the browser client unchanged.| Date | Decision | Rationale |
|---|---|---|
| 2026-05-24 | Reject browser client-side terminal | Sandbox impossibility, C2 trust issues, agent loop blocking |
| 2026-05-24 | Prefer headless node swarm | Preserves existing tool execution model, NAT-friendly, composable |
instance_id database partitioning for sessions, recalls, and content./ws/nodes/{node_id} endpoint to central server for node registration and task streaming..env template).ToolRegistry or as proxy tools.AgentSessionOrchestrator.