# Paseo — Agent Orchestration on the Home Lab **Multi-agent orchestration GUI (Paseo 0.7.2) self-hosted in Docker on `.13`, driving real pi coding agents (0.82.1) through OmniRoute.** > Maintained by Sam · Gitea — [sam/paseo](https://gitea.lab.audasmedia.com.au/sam/paseo) · > interactive map: [maps.lab → Paseo](https://maps.lab.audasmedia.com.au/paseo/docs/system-map.html) --- ## What it is [Paseo](https://github.com/getpaseo/paseo) is a client-server orchestration layer for AI coding agents: one **daemon** manages agent processes and streams their output to desktop, CLI, mobile and web clients. On this lab it runs **inside Docker on the always-on host `.13`**, with **pi** (the coding agent) baked into the image and LLM traffic routed through the existing **OmniRoute** proxy on `.13:20129`. - **Local-first** — agents run on our machines/dev environment; no telemetry. - **Pi is a first-class provider** — the daemon spawns `pi --mode rpc` (pi 0.82.1, no Nix changes). - **One console** — `paseo ls` / `attach` / `logs` from anywhere: `.27`, `.51`, mobile, web UI. ## Architecture ```mermaid flowchart LR subgraph CLIENTS["Clients"] D27[".27 desktop
paseo CLI"] D51[".51 laptop
paseo CLI"] M["Mobile / web UI
browser"] end subgraph S13["Paseo daemon (.13 — Docker, always-on)"] D["Paseo daemon 0.7.2
:6767 · auth"] PI["pi agent 0.82.1
pi --mode rpc
@earendil pi + omni ext"] CFG["pi config
/home/paseo/.pi"] W["workspaces
/workspace/demo"] PWD["PASEO_PASSWORD
.env (600)"] end subgraph LLM["LLM routing"] OR["OmniRoute
.13:20129"] OP["OpenCode-Go /
OpenRouter / DeepSeek / Gemini"] end D27 -->|"PASEO_HOST + password"| D D51 -->|"PASEO_HOST + password"| D M -->|"https :6767"| D D -->|"spawns / manages"| PI PI -->|"reads settings + models"| CFG PI -->|"works in"| W D -->|"protects"| PWD PI -->|"httpx /v1 (omni provider)"| OR OR -->|"combo routing"| OP ``` ## Directory map ``` paseo/ ├── README.md ← this file └── docs/ ├── system.mmd ← Mermaid source (single source of truth) ├── system.architecture.json ← Archify source ├── system-map.html ← interactive Archify map └── diagrams/ ├── system.png └── system.svg ``` ## Quick start (client) ```bash # .27 / .51 (one-time) npm install -g @getpaseo/cli@0.7.2 export PASEO_HOST=192.168.20.13:6767 export PASEO_PASSWORD= paseo status # daemon reachable? paseo ls # running agents paseo run --provider pi --model omni/openrouter/qwen/qwen3.7-flash \ --cwd /workspace/demo "describe this workspace" paseo logs # full activity timeline ``` Web UI: `http://192.168.20.13:6767` (password). Mobile: browser over LAN/Tailscale. ## Deployment (server, `.13`) | Item | Value | |---|---| | Compose dir | `/home/sam/Docker/Containers/paseo/` | | Image | `ghcr.io/getpaseo/paseo:latest` + custom stage | | Daemon | 0.7.2 · `restart: always` · :6767 | | pi | `@earendil-works/pi-coding-agent@0.82.1` (baked, `--mode rpc`) | | Extensions | `omniroute-pi-ext-integration` (baked) | | Config | `./paseo-home:/home/paseo` (persists pi + paseo config) | | Workspace | `./workspace:/workspace` (agent project area) | | LLM | pi → omni provider → `http://192.168.20.13:20129/v1` (OmniRoute) | | Secrets | `.env` (chmod 600) — `PASEO_PASSWORD`, `OMNIROUTE_API_KEY` | **Build note:** base image runs as user `paseo` (uid 1000) with root-owned `/usr/local` — so pi and the extension are installed at **build time** under `USER root` in the Dockerfile, then dropped back to `USER paseo` for runtime. ## Verified end-to-end (2026-09-09) ``` $ paseo run --provider pi --model omni/openrouter/qwen/qwen3.7-flash \ --cwd /workspace/demo --title paseo-demo --background \ "List files, read HELLO.txt, write DEMO_SUMMARY.md" AGENT ID 560ffca0-… STATUS running PROVIDER pi CWD /workspace/demo ↓ AGENT ID 560ffca0-… STATUS idle PROVIDER pi/omni/openrouter/qwen/qwen3.7-flash ↓ → wrote ./workspace/demo/DEMO_SUMMARY.md (correct content) ↓ → `paseo logs` shows full timeline (user → thought → shell → read) ↓ → web UI :6767 → HTTP 200 ``` ## Known findings - **OmniRoute combo regression:** the default `default-opencode-go-ds-flash` combo currently returns `400 missing x-opencode-session` (OpenCode-Go leg) — affects host pi too, not just the container. Working legs verified: `openrouter/qwen/qwen3.7-flash`, `openrouter/openai/gpt-5.6-sol`, `aug/claude-haiku-4.5`. Fix the combo/credentials on OmniRoute to restore the default path. - Paseo is pre-1.0 (0.7.2) — pin the version; expect breaking changes between releases. - CLI runtime install on `.27` carries 3 low/medium CVEs in transitive deps (`qs`, `uuid`, `@ai-sdk/provider-utils`) — vet/npq scanned clean, author verified. ## Why it matters - **Proof the stack composes:** Nix pi binary stays untouched; the lab's OmniRoute routing powers a third-party orchestrator; one always-on Docker host (.13) gives fleet control from any device. - **A pattern for multi-agent work:** workspaces + `pi --mode rpc` + OmniRoute is a base for coordinating several pi agents on real projects — exactly the coordination layer the lab needs. --- *Documentation project — no proprietary code. Secrets never appear in this repo.*