# openvisio-agent

Connect your coding agent (**Claude Code, Codex, OpenCode, Gemini CLI, or Qwen Code**) to an [OpenVisio](https://openvisio.io) team from Agent Studio. One command starts everything:

```bash
npx -y openvisio-agent@latest
```

**Agent Studio** is the local control room. Choose **Connect agent**, select the runtime, then enter the **identifier** and **API key** for your backend agent. Studio resolves the agent name from OpenVisio, verifies the connection, saves it privately, and starts the agent’s watcher. It also lets you update connections, change reply and coding models, start/stop/restart watchers, remove local agents, and follow recorded work — no other CLI commands needed.

Install and sign in to your chosen runtime first (`claude`, `codex`, `opencode`, `gemini`, or `qwen`) so the watcher can start immediately. If it is not ready, the connection is still saved; install it, then choose **Start watcher** in Studio.

**New here?** Start with the [user guide](USER_GUIDE.md) for setup, everyday work, Agent Studio, and troubleshooting.

**Agent controls:** In the app, choose **Agents → Open Agent Studio**. Updated backend watchers start Studio automatically on this computer. Select an agent’s **Model settings** to change reply and coding models for the next request without a restart. Agents can offer the same button in chat; rate-limit notices link directly to settings. Model access and quota remain managed by the connected provider.

The `connect`, `watch`, `stop`, and `update` commands remain available for automation and advanced options, but they are intentionally not part of the main help. Prefer Studio.

## What it does

`openvisio-agent` is a local CLI and autonomy harness. Nothing is fetched-and-executed outside its declared npm dependencies; the source is here and on npm.

### Code graph for every coding session

Coding sessions automatically attach the open-source [`openvisio`](https://www.npmjs.com/package/openvisio) MCP server. It parses the workspace into a symbol and import graph and serves ranked, token-budgeted slices with exact `path:line` anchors, so the agent queries structure before it greps or reads whole files.

- `openvisio` is a dependency of this package, so every runtime (Claude Code, Codex, OpenCode, Gemini CLI, Qwen Code) gets the same local server with no extra setup.
- The agent is told to call `resolve_context` first, use `search_code` instead of `Grep`, and use `find_symbol`, `trace_calls`, `get_neighborhood`, `get_dependents`, and `get_hotspots` for structure.
- Native `Grep` and `Glob` are disabled in coding sessions while the graph is attached; `Read` stays available for the anchored slices the graph returns.
- The server is read-only, local, and indexes the coding workspace (or the ticket worktree) with `--watch`.

### `connect <ovs_code> --host <url>`

1. Redeems the **single-use** setup code for your agent key (`POST /api/agent/setup/exchange`). The code is short-lived and one-time, so it's inert if it leaks into your shell history.
2. Configures the `openvisio-team` MCP for the selected runtime. Claude Code is registered globally; ACP and embedded runtimes receive an isolated authenticated MCP configuration for each autonomy cycle.
3. Saves a scoped config under `~/.openvisio/` (chmod `600`) for the optional watcher.

Options: `--name "<agent>"` (label), `--mcp-url <url>` (override the MCP endpoint).

### `connect --backend <url> --key <api-key> --id <identifier>`

For an agent created against the **org backend** (OpenVisio → Agents → Connect your agent). Verifies the credentials against the backend, then saves `~/.openvisio/<agent>.json` plus a sourceable `~/.openvisio/<agent>.env`:

```
npx -y openvisio-agent@latest connect --backend https://api.your-org.example/dev \
  --key 660e8400-… --id 550e8400-… --name "Ada"
```

The api-key is shown **once**, when the agent is created — if it's lost, remove the agent in OpenVisio and connect it again. The backend dispatches board tasks to the agent; every request authenticates with the `x-agent-api-key` + `x-agent-identifier` headers. Options: `--name "<agent>"` (label / file names).

**Real-time autonomy (optional).** Add `--ws` and `--mcp-url` to let the agent react to assignments and @mentions the moment the backend pushes them:

```
npx -y openvisio-agent@latest connect --backend https://api.your-org.example/dev \
  --key 660e8400-… --id 550e8400-… --name "Ada" \
  --ws wss://abc123.execute-api.us-east-1.amazonaws.com/dev \
  --mcp-url https://api.your-org.example/dev/agent/mcp
```

- `--ws <wss-url>` — the org's API-Gateway WebSocket base (the same value the frontend uses as `NEXT_PUBLIC_BACKEND_WS_URL`).
- `--mcp-url <url>` — registers the `openvisio-team` MCP (authed with the agent header pair) so the agent has tools to **act** on the events.

Then `watch --name ada` auto-detects the backend agent and runs a WebSocket loop instead of polling: it connects with `?api_key=&identifier=`, keeps the connection warm with keepalives, reconnects with backoff, and queues each accepted assignment or mention independently. A work cycle can contain many assistant, tool, and message actions; emitting a progress message does not end it. The Mastra runtime requires **Node ≥ 22.13**.

### Automatic connection updates

Backend/BYO watchers fetch the current WebSocket and MCP URLs from the stable OpenVisio app's `/api/agent/setup/connection` endpoint at startup and after connection failures (at most once per 30 seconds). There is no periodic discovery timer: a healthy, idle watcher makes no discovery requests. The request sends no credentials and accepts only a complete configuration matching the saved backend. Failed discovery keeps the last saved endpoints. It does not poll team tasks or invoke a model.

If the old connections remain healthy, an endpoint change is picked up on the next startup, connection failure, or explicit `update` command. Immediate propagation to healthy watchers requires a backend-published configuration-change event; that publisher is not implemented here.

When URLs change, the watcher saves them, reconnects its WebSocket, and uses the new MCP endpoint for new runtime sessions. Active sessions finish before being retired; they can still encounter errors if their old MCP endpoint is removed during a turn. There is no automatic process restart or cancellation of accepted work. Credentials, runtime, models, workspace, and other settings are preserved.

New setup commands and copied Studio credentials include the app address. For self-hosted or staging setups, pass `--host <app-url>` to `connect`. Legacy configurations try `https://openvisio.io`, but reject a different backend. Existing agents need this package version installed and their watcher restarted once. To set a different discovery host and refresh immediately:

```bash
npx -y openvisio-agent@latest update --name ada \
  --host https://your-openvisio.app --restart
```

After the host is saved, `openvisio-agent update --name ada` fetches the current URLs without requiring either URL or another API key. Automatic refresh updates the watcher's scoped MCP configuration; the explicit `update` command also refreshes Claude's global registration when the MCP URL changes. Manual `--ws` and/or `--mcp-url` overrides remain available. Relay agents support manual MCP updates only.

If the API backend itself has moved, pass `--backend <new-api-url>` along with the current `--ws <new-websocket-url>` (and `--mcp-url` if it changed). The update verifies the saved credentials against the new API before saving, preserves agent settings, and updates both API and WebSocket values in the agent's environment file. Without manual connection URLs, it discovers them from `--host` and requires that metadata to match the explicitly selected backend. Automatic discovery never migrates credentials to a different backend.

`--restart` explicitly stops the named watcher (interrupting active work) and installs/starts its background service on macOS or Linux. It does not upgrade an existing global package; install the new release first. Omit it to save changes without interrupting work. Foreground watchers can be stopped and started with `openvisio-agent watch --name ada`. Explicit URL overrides on `watch` disable discovery for that invocation. The discovery app host must remain reachable; changing that host or the backend identity requires an explicit update/reconnect.

### `watch --name <agent>`

Runs the **autonomy loop** — the agent replies to @mentions and picks up tickets on its own. It cheaply polls an inbox endpoint (no model spend when idle) and starts isolated runtime sessions only when something new arrives.

Codex, Gemini CLI, and Qwen Code cycles run through one Mastra ACP harness; Codex uses the packaged `codex-acp` adapter, the others their native ACP servers. OpenCode runs only on the official `@opencode/sdk` embedded host: no `opencode acp` child process, no HTTP listener, and no dependence on the installed OpenCode CLI version at runtime. The host requires Node 24 or newer; older Node is rejected with a clear error instead of falling back. Every provider receives the same authenticated team tools, workspace isolation, cancellation, and Studio model-selection path. Each accepted ticket gets its own session and worktree. Mastra Memory stores ticket/thread context in local libSQL under `~/.openvisio/`, while a compact JSON ledger retains only exact replay, cancellation, and delivery keys.

Embedded OpenCode shares the machine's OpenCode data directory by default, so credentials from `opencode auth login` are reused. The watcher reads active key credentials from OpenCode's credential table and exports them to the provider package environment before the host starts; an explicitly set environment variable always wins. When several BYO agents run on one machine, set `OPENVISIO_OPENCODE_DB` to a per-agent database path (the shared database remains the credential fallback) and supply providers or a default model with `OPENVISIO_OPENCODE_CONFIG` (JSON merged into the V2 config). One host serves all concurrent work and reply sessions for an agent; work and reply isolation is enforced per session.

Backend watchers also provide four local context tools through the authenticated MCP bridge:

| Tool | Purpose |
| --- | --- |
| `openvisio_list_my_tasks` | Read live pending assignments, including when someone says “I have a task for you.” Does not claim or start work. |
| `openvisio_find_tools` | Search advertised tools by intent and return actual schemas, related tools, and weighted graph paths; optionally specify `from_tool` and `to_tool` for a shortest-path lookup. |
| `openvisio_search_conversations` | Search recorded conversations by meaning and keywords, optionally narrowed to a channel or thread. |
| `openvisio_load_skill` | Load the `organization-work`, `openvisio-work`, or `conversation-recall` skill when useful, including after compaction. |

Tool discovery builds a directed graph from the current agent's available MCP catalog and caches it in memory until the catalog or schemas change. Tool nodes retain their exact advertised names. Edges use output/input identifier relationships (cost 1), inferred identifier relationships (2), read-back verification (1), suggested organization workflows (2), and shared resource names (4). Relationships inferred from names or workflow conventions are labeled in edge evidence; they do not prove data dependencies. Tools on different server namespaces are not connected.

Keyword/semantic search locates up to three starting tools, then multi-source Dijkstra finds related tools with a binary min-heap. Search ranks contribute seed costs of 0, 0.25, and 0.5; graph edge weights are added to those costs. Ordinary expansion is bounded to cost 6 and the requested result limit. Providing `from_tool` bypasses keyword/embedding search entirely. Explicit destination searches return the lowest-cost reachable path, or `reachable: false`. This accelerates relationship traversal after the graph is built; it does not replace semantic search or establish a measured end-to-end latency improvement. No new graph database or model call is required.

For example, use `openvisio_find_tools({"query":"document our API collection","from_tool":"list_api_collections","to_tool":"get_document"})` to inspect a suggested collection → endpoints → create document → verify document route. The response includes `matches`, `relatedTools`, and a compact `graph` with nodes, weighted edges, and paths. Actual tools must be advertised; no missing tool is synthesized. The graph is restricted to the session catalog before traversal, and the MCP proxy rechecks availability and sanitized schemas before returning it. Destructive tools can appear as direct search matches or explicit destinations, but are excluded from automatic relationship expansion. Discovery never invokes the suggested tools, validates an entire workflow, or authorizes a mutation.

Conversation search combines Mastra's `LibSQLVector` with local BGE-small embeddings from `@mastra/fastembed` and keyword ranking. The first search downloads the model; inference then runs locally without an embedding API key. A worker handles inference independently of the agent loop. Search reports `embeddingStatus` and returns keyword results during download or failure. No conversation text is sent to an embedding provider.

The corpus contains accepted messages and messages obtained through successful `list_message_thread` or `post_message` calls. It does not automatically crawl the whole organization. Results include authors, timestamps when supplied, observation times, and source IDs. Messages retain up to 24,000 characters and are stored as overlapping excerpts, with a 5,000-excerpt retention cap per backend/agent. Observed edits replace previous content; observed deletions remove it. Deleted or changed messages not yet observed can remain in local history: verify material facts against live tools. Exact graph context and current ticket checks remain separate from historical search.

The integration follows Mastra's [semantic memory](https://mastra.ai/docs/memory/semantic-recall), [skills](https://mastra.ai/docs/skills), [harness](https://mastra.ai/docs/harness/overview), and [workflow](https://mastra.ai/docs/workflows/overview) documentation. The built-in skills use `createSkill()` and are exposed to native coding runtimes through MCP. Native project skills and context compaction remain owned by the selected runtime. Workflows coordinate predictable application steps; they do not prescribe the agent's investigation or decide whether its ticket is complete.

Model selections are stable. Exact IDs (including reasoning effort) are preserved. An unsuffixed ACP model may resolve once to the same model with `medium` effort; the watcher saves that exact selection. Unavailable selections produce an explicit error rather than switching generations or families. Claude versioned IDs are preserved, with automatic family fallbacks disabled. Codex uses the configured chat model for replies.

Backend/BYO watchers reconcile assignments whenever the WebSocket starts or reconnects. A direct MCP session discovers and caches the backend's actual `tools/list` response, then uses available tools such as `list_agents`, `list_projects`, `list_tasks`, and `list_task_types` to recover assigned work after a connection event. The authenticated profile lookup also supplies the verified organization needed for channel, assignment, and task-comment subscriptions. Once connected, the watcher makes no periodic `list_activity`, roster, project, board, task-type, or task calls while idle; incoming WebSocket events start the relevant verification path. Team discovery is shared by every runtime provider: structured MCP results and compact Markdown list envelopes are normalized once before the watcher resolves its project, identity, boards, tickets, or dedicated channel. Adding another model provider therefore reuses the same saved team connection and setup path instead of adding provider-specific project discovery. New comments on a task assigned to the agent are verified with `get_ticket`; human comments and concrete peer-agent requests receive one deduplicated reply in the source comment thread. Optional comment actions are used only when advertised, and their absence cannot strand a completed ticket in a retry loop.

The backend MCP may be stateful or stateless. A successful initialize response without `Mcp-Session-Id` is accepted as stateless, so OpenCode agents do not stop with “MCP initialize returned no session id.” The embedded OpenCode host receives the authenticated local stdio bridge and the code graph in its generated V2 config. Its provider state is isolated per agent with `OPENVISIO_OPENCODE_DB`, so stale project configuration cannot swap one agent's credentials for another's. The generated config disables OAuth probing, and backend cycles never request relay-only inbox calls or MCP resource-discovery tools in place of team actions.

Codex BYO agents follow the repository's normative runtime specification in `docs/CODEX_BYO_AGENT_SPEC.md`: one WebSocket identity, independent reply/work queues, authoritative `get_ticket` verification for assignments, silent transient activity, persistent replay suppression, and agent-controlled turn completion. Maintainers must run `npm run certify` before publishing.

Both `agent:mention` and organization `channel:message` events pass through the same source-recipient, ownership, and deduplication checks before any model starts. The watcher hydrates compact roster entries through `get_agent`, subscribes only to the organization verified from that authenticated profile, and restores the subscription after reconnect. Organization `task:created` and `task:updated` events enter the same authoritative assignment verifier as targeted `task:assigned` events, so a task starts only after `get_ticket` confirms it is open and owned by this agent. Explicit self-authored task updates and source messages are ignored; embedded old agent replies cannot hide a human follow-up. An explicit tag establishes durable ownership of that thread, so later untagged human follow-ups remain addressed to the agent. Another BYO agent can make one concrete request after the latest human turn; after this agent answers, further peer turns stay silent until a human speaks. Routine agent chatter, reciprocal questions, and sender-less echoes of watcher-delivered task comments remain silent. Ticket-inventory intent is sentence-scoped, so a peer saying it has no assigned tickets cannot hijack a separate onboarding or coordination question. Messages redirected to another agent stay silent, while a direct stand-down cancels queued/running work and releases ownership for that thread. Agent messages and comments are kept within 1,200 characters, and task mutations expose the distinction between human `assignee_id` and agent `agent_id`. Concrete roots verified as belonging to someone else have a bounded one-minute cache; missing authors and failed reads remain immediately retryable. The watcher publishes working, thinking, and typing presence from actual runtime activity using the authenticated REST endpoint. It stops refreshing when work finishes or is cancelled; the app clears the indicator through its expiry timer. Accepted coding tasks publish a short native plan first; the watcher sends one acknowledgement with up to three steps to the source thread or default agent channel. Every runtime returns a distinct final answer for guarded watcher delivery. Plans and reconnects cannot duplicate or suppress that final answer.

Ticket references follow the board UI: BYO agents use the project-scoped slug, such as `OVS-57`, in messages, comments, PR descriptions, blockers, and results. Numeric `project_id` and `ticket_id` values remain internal MCP arguments and are never used as human-facing ticket names. If an older backend omits the slug, the agent uses the ticket title rather than inventing one.

Claude uses Haiku for routine coordination and Sonnet for repository work. Codex defaults to `gpt-5.6-sol`; configured code and chat models are preserved independently.

```bash
openvisio-agent watch --name ada                 # run in this terminal
openvisio-agent watch --name ada --install       # run in the background, start at login
openvisio-agent watch --name ada --workdir ~/repo  # allow REAL work on a git branch
openvisio-agent stop --name ada                  # stop service + every ada watcher
```

Agents choose their tools, investigation steps, context management, and when to end a turn. Coding agents can delegate independent subtasks through the runtime’s native sub-agent tools: Codex multi-agent is enabled, OpenCode permits task delegation, and Claude permits Agent/Task. The parent supplies scoped context and file ownership, works alongside children, reviews their results, and reports once. Delegation depends on the tools advertised by the installed runtime; it does not grant additional task or publishing authority. Each turn receives the agent’s configured identity, role, and voice when supplied by its profile; that context is cached across restarts. Reply sessions can request their configured coding workspace through `openvisio_request_work_session`, carrying their findings, source thread, and permissions into the continuation. They do not ask you to reassign work because of an internal scheduling choice. A successful native final turn triggers a structured goal assessment before the cycle can succeed; it does not mark a ticket done. The original request stays attached across reply-to-work handoffs. The assessment checks requested outcomes, observed evidence, remaining work, and external blockers in the same session. Incomplete or malformed assessments allow up to two additional work turns, with uncertain writes verified before retrying; exhausted attempts remain incomplete, and real blockers remain blocked. Assessment JSON is not posted to teammates. This adds a model turn per completion check and relies on the model accurately judging its observed evidence; it is not independent proof of backend state. The agent decides when to update the board. Research, audits, and already-satisfied requests can finish without code changes, ticket mutations, or a PR. Optional tool failures remain diagnostics; the goal assessment determines whether they prevent the requested outcome.

The context graph records source-to-continuation relationships and recalls direct neighbors without walking into unrelated conversations. The watcher saves the agent's final response for delivery retry and avoids rerunning an unchanged assignment after restart. Every supported runtime keeps context within a ticket or conversation; native runtimes handle compaction. BYO runs are unbounded: the watcher arms no run deadline, so a long build, test suite, or research task is never cut off mid-work. Liveness stays visible through process and tool events plus the WebSocket heartbeat, and the team stops a stuck run manually from Agent Studio. Ownership, cancellation, delivery deduplication, credential injection, and repository permissions remain enforced.

The watcher can run up to three assigned coding tasks concurrently. Each ticket gets an isolated model runtime and ticket-specific worktree; tasks sharing the same mutable workspace remain serialized to prevent branch and file conflicts. Replies to one thread stay serialized while up to three independent threads run concurrently, and cancellation targets only the matching ticket or source thread. The work pool reuses local clones and is instructed to preserve dirty/staged work, create unique branches, and stage only task-owned changes. The independent reply lane receives a chat charter and no coding workspace. Codex publishes local branches through the constrained helper, then opens a PR with `gh pr create`; linked-codebase MCP operations are a fallback when the repository cannot be obtained locally.

PR publishing is part of normal coding setup. `connect` authorizes the selected `--workspace` (or `~/openvisio-workspace`) for routine agent-branch pushes and installs the constrained Codex helper rule. New clones and linked worktrees inherit that workspace authority. Existing coding configurations migrate on their next watcher start. Use `--no-pr-push` during setup to opt out.

The helper `openvisio-agent push-pr-branch` accepts no arguments. It pushes only HEAD to the matching `agent/*` branch at the verified origin push URL, disables hooks, and rejects protected branches, force pushes, local/file remotes, and credential-bearing URLs. `revoke-pr-push` revokes the repository across its worktrees and survives future starts. `authorize-pr-push --repo <path>` remains available for repositories outside the configured workspace.

Authorization recovery checks paused repositories locally every two seconds and clears both policy and failed-revision state before live ticket verification. It does not need a new watcher or a new chat message. Updating the package still requires the running service to load the new version once.

Responses to existing requests stay in their source thread. For completed tasks without a source thread, the agent inspects live channels and chooses the best fit for the task, project, and audience; a dedicated channel is not required. The watcher validates the choice and delivers the saved final answer through MCP. Missing channels or failed delivery leave the result pending for retry without repeating the task. Introductions and plans continue to use the configured or uniquely matched dedicated channel. Explicitly requested destinations remain authoritative.

BYO agents can include Markdown links to tickets, documents, sheets, flowcharts, and channels using verified app identifiers, with ticket slugs or item titles as readable labels. The corresponding frontend update opens these references directly inside the app.

Codex, Gemini CLI, and Qwen Code use Mastra ACP directly. OpenCode uses only the embedded V2 host and requires Node 24+; one reference-counted host is shared across the agent's concurrent work and reply sessions, and its sessions are cheap enough to keep warm behind the same pools. Work sessions stay in a six-entry pool and reply sessions in an eight-entry pool; idle sessions expire after five minutes, and active sessions cannot be evicted. Git snapshots are asynchronous, lightweight commands lazily load the watcher, and logs separate queue wait, preflight, first-event, and total runtime time. Studio reads watcher liveness from the local PID lock instead of requiring journal heartbeats, and model changes arrive through filesystem notifications. Projects reconcile with concurrency three and enqueue tickets before reading optional activity history; later idle recovery reads activity only. Coordination sessions can update the board without gaining repository access.

Assignments use independent FIFO entries with stable-key duplicate suppression and bounded, worktree-aware concurrency. Backlog recovery uses the same ticket verification path as WebSocket events, and each queued ticket is checked again before a model starts. MCP calls have a 20-second deadline including response bodies; tool discovery is cached and paginated. Codex MCP failures retain a bounded, credential-redacted reason in the watcher log. Cancellation targets only its ACP session. Credentials and replay state use atomic file replacement; Mastra persists contextual memory in libSQL.

An event WebSocket disconnect does not cancel accepted coding work. If the native coding runtime also reports a transport interruption, its queue entry retains the source request, workspace, and partial output. It waits for a known event-channel outage to reconnect, then verifies the ticket again and asks the agent to inspect existing work and uncertain remote writes before continuing. Provider-only interruptions use up to four retries (2, 8, 30, and 60 seconds); repeated failure then reports a blocker. Agent final responses, optional tool errors, explicit cancellation, inactivity timeouts, quota errors, and policy denials do not trigger this recovery. Coordination requests are not automatically replayed. Keep the watcher running during an outage; this recovery retains in-flight context in that watcher, not across process termination.

See `docs/BYO_PERFORMANCE_AUDIT_2026-09-08.md` in the repository for the audit results and remaining live-validation limits. Local certification does not certify a deployed agent's behavior.

`--install` sets up a background service (launchd on macOS, systemd `--user` on Linux) that runs `watch` and restarts on login. Logs go to `~/.openvisio/<agent>.log` (macOS) or `journalctl --user -u openvisio-<agent>` (Linux).

Do not chase auto-changing watcher PIDs. `openvisio-agent stop --name <agent>` unloads the named background service first, stops every remaining watcher for that exact agent, and clears its stale lock. Running `watch --install` also performs this cleanup before replacing the service.

### Specialist agents: extra MCP servers and a charter

A pool of agents (marketing, support, research) shares one watcher but each member needs its own tools and playbook. Both are saved per agent in `~/.openvisio/<agent>.json` and threaded into every runtime session, including reply sessions.

```bash
npx -y openvisio-agent@latest connect --backend https://api.your-org.example/dev \
  --key 660e8400-… --id 550e8400-… --name "Rhea" --host https://your-openvisio.app \
  --mcp-url https://your-mcp/api/mcp/openvisio/mcp --ws wss://…/dev \
  --extra-mcp openvisio-crm=https://your-openvisio.app/api/crm/mcp \
  --extra-mcp-header "openvisio-crm: Authorization: Bearer ova_…" \
  --charter ~/openvisio-workspace/OpenVisio/marketing/playbooks/rhea.md
```

- `--extra-mcp <name>=<url>` (repeatable) adds an HTTP MCP server next to `openvisio-team`. Claude sessions get it in their private `mcp.json` and may call `mcp__<name>__*` without a prompt; ACP and embedded runtimes receive it in the session's server list. The name `openvisio-team` is reserved.
- `--extra-mcp-header "<name>: <Header>: <value>"` (repeatable) adds a header for that server. Header values are stored with mode `600`, never placed on a command line, and redacted from logs, Agent Studio and journal text.
- `--charter <file>` appends a role playbook (Markdown, at most 12 KB) to the agent's cached system prompt as `ROLE PLAYBOOK`. The file is read when the watcher starts; keep it in a repository under the agent's workspace so the team can edit it, and restart the watcher after editing. A missing or oversized charter stops the watcher at startup with the fix printed.
- `openvisio-agent update --name <agent> --extra-mcp … --extra-mcp-header … --charter …` changes these later; `--no-extra-mcp` and `--no-charter` clear them. Specialist-only updates do not run endpoint discovery.

- `--patrol-every <minutes>` (5 to 1440) makes the agent wake itself on that interval and work its own lane with no request: its open tickets, then the standing duties in the "On patrol" section of its charter, then hand-offs by ticket. `--patrol-model <m>` picks the model (default: the chat model). A patrol is skipped while the agent is already working, ends silently when there is nothing to do, and never posts a blocker if it fails. Each patrol is a model call, so choose the interval with cost in mind. `update --no-patrol` turns it off.

The playbook and the extra servers never grant new authority: the agent still acts within the request, the team's roles, and the extra server's own permissions.

## Security

- **No opaque script.** You run a named, versioned npm package you can read here and on [npmjs.com](https://www.npmjs.com/package/openvisio-agent).
- **Single-use code.** The `ovs_` code is exchanged once for a key; a leaked code is already spent.
- **Scoped workspace access.** Chat sessions can discover advertised MCP actions and use reading, search, browsing, planning, and context tools. Local writes and shell execution require a coding workspace. Coding setup grants routine PR publishing inside its workspace through a no-argument `agent/*`-only helper. Repositories outside that workspace need an exact repository grant. The helper cannot merge or push protected branches.
- **Local secrets.** Your agent key lives in `~/.openvisio/` with `600` permissions — never printed, never committed.

## Requirements

- Node.js ≥ 22.13. OpenCode requires Node ≥ 24 because its embedded SDK uses features Node 22 cannot parse.
- Claude Code, Codex (`@openai/codex`), OpenCode, Gemini CLI (`@google/gemini-cli`), or Qwen Code (`@qwen-code/qwen-code`). The selected CLI is installed when missing. OpenCode's CLI is used only for login and model listing; its runtime is hosted from the bundled SDK.

## Connecting from Studio

Open Agent Studio and choose **Connect agent**. Select the runtime, then enter the backend agent's **identifier** and **API key**. Studio resolves the agent name, verifies the connection, saves it privately, and starts the watcher. Install and authenticate your runtime first. **Or use a terminal command** keeps CLI setup available for advanced options, including the one-time `ovs_` setup code.

## Uninstall

```bash
claude mcp remove openvisio-team
# macOS: launchctl unload ~/Library/LaunchAgents/io.openvisio.<agent>.plist && rm it
# Linux: systemctl --user disable --now openvisio-<agent>.service
rm -rf ~/.openvisio
```

MIT

## Agent studio

Agent Studio is available in `0.20.0` and later. It is the single command:

```bash
npx -y openvisio-agent@latest
```

The package supplies the OpenVisio app, backend, WebSocket, and MCP endpoints. A hidden `--staging` flag switches all four to the staging environment:

```bash
openvisio-agent --staging
```

The selected environment is saved with each agent, and the watcher resolves the endpoints from the package at startup, so a staging agent keeps using the staging MCP across restarts. Studio connections use the package endpoints; the legacy CLI commands still accept explicit URLs for self-hosted setups.

To run from source, see [the checkout instructions](USER_GUIDE.md#run-studio-from-this-checkout).

Select **Read the guide** under **Documentation** in the sidebar (or **Documentation** in the mobile header) for a local, printable guide to controls and statuses. Start with [the walkthrough](USER_GUIDE.md#open-agent-studio) if you have not used the viewer before.

Studio opens `http://127.0.0.1:4317` and follows the local agents' activity live. Select an agent or cycle to inspect its emitted plan, tool calls, command previews, file locations, progress messages, final result, and process status. The timeline distinguishes queued, running, completed, canceled, and failed work. Plans appear only when the runtime emits an explicit plan; internal reasoning is not recorded.

```bash
openvisio-agent --demo       # labeled sample activity; no model calls
openvisio-agent --no-open    # print the URL without opening a browser
openvisio-agent --port 0     # choose an available local port
```

Watchers running this version record bounded, credential-redacted activity under `~/.openvisio/observability`. Update and restart an older watcher once to start recording; its earlier plans and tool activity cannot be reconstructed. Closing Studio leaves the agents running. Studio uses local files and a loopback listener; it does not require a workspace or provider login. `--state-dir <dir>` selects an isolated watcher's state directory for local testing.

## Reliability scenarios

`npm test` includes the executable BYO scenario catalogue. `npm run test:scenarios -- --report /tmp/byo-results.json` writes every case, result, category, and duration. Cases cover routing, runtime lifecycle, transport, memory, authorization, and complete watcher sequences against simulated service/runtime boundaries. They do not invoke paid models or mutate a live workspace.

`node scripts/smoke-context-search.mjs` explicitly downloads the local embedding model and tests paraphrase retrieval against synthetic conversations. Set `OPENVISIO_SEARCH_SMOKE_DIR` to a persistent temporary directory to reuse that model download between runs. Ordinary tests use deterministic injected embeddings and require no model download.

Dependency review (2026-09-10): `@mastra/fastembed@1.3.1` pins `onnxruntime-node@1.26.0`, whose installer depends on `adm-zip@0.5.x`. npm reports a [high-severity ZIP allocation issue](https://github.com/advisories/GHSA-xcpc-8h2w-3j85) and a [symlink extraction issue](https://github.com/advisories/GHSA-vwc7-r8mq-g2x9), propagated to the parent dependencies. Conversation text does not enter this ZIP installer; the unresolved dependency findings still need an upstream update before claiming a clean audit.

The watcher now stores pending threaded replies before posting and retries their authoritative delivery checks without rerunning the model. Distinct source message IDs remain distinct requests even when their text is identical. Stable agent IDs take precedence over display names at every assignment gate.
