Files

9.9 KiB

Local Setup

This guide runs the active Zopu stack locally, including the browser chat and the AgentOS issue-to-PR path.

What runs

Browser (React Router/Vite, :5173)
  -> Convex Cloud (durable product state, auth, workflows)
  -> Flue agent server + AgentOS registry (:3585, one Node process)
  -> Rivet Engine control plane (:6420)
  -> AgentOS workspace actor (Git + repo clone mounted from the local checkout)
  -> Gitea branch and pull request

The active stack does not use repos/; that directory is archived reference code. In particular, the old standalone server on port 3590 is not part of this setup.

Requirements

  • macOS or Linux
  • Bun and Node.js matching the repository toolchain (packages/agents requires Node >=22.18 <23 || >=23.6)
  • pnpm 11
  • Git with SSH access to git.openputer.com
  • Tea authenticated to https://git.openputer.com
  • a Convex account with access to the development deployment
  • an OpenAI-completions-compatible model endpoint and API key

Install dependencies from the repository root:

bun install --frozen-lockfile

Confirm Git and Tea access before testing issue or PR tools:

git ls-remote origin HEAD
tea login list
tea issues list

The default Tea login should target https://git.openputer.com. Never put credentials in committed files.

Environment

Create the local environment file:

cp .env.example .env

At minimum, configure these groups.

Application and Convex

CONVEX_DEPLOYMENT=dev:<deployment-name>
CONVEX_URL=https://<deployment>.convex.cloud
CONVEX_SITE_URL=https://<deployment>.convex.site
SITE_URL=http://localhost:5173
VITE_AUTH_URL=http://localhost:5173
VITE_CONVEX_URL=https://<deployment>.convex.cloud

Flue and model provider

FLUE_DB_TOKEN=<shared-random-token>
FLUE_URL=http://127.0.0.1:3585

AGENT_MODEL_PROVIDER=<provider-name>
AGENT_MODEL_NAME=<model-name>
AGENT_MODEL_API=openai-completions
AGENT_MODEL_BASE_URL=https://<model-endpoint>/v1
AGENT_MODEL_API_KEY=<model-api-key>
AGENT_MODEL_CONTEXT_WINDOW=<positive-integer>
AGENT_MODEL_MAX_TOKENS=<positive-integer>

FLUE_DB_TOKEN must match the value stored in the Convex deployment.

Rivet and AgentOS

# The private Engine control plane the registry connects to.
RIVET_ENDPOINT=http://127.0.0.1:6420
RIVET_WORKSPACE_TOKEN=<shared-random-workspace-token>
AGENT_WORKSPACE_ROOT=/absolute/path/to/zopu-agent-workspaces
# Optional: bump when the actor definition changes to drain old actors.
RIVET_ENVOY_VERSION=0.0.0

The Hono/Flue Node process hosts the AgentOS registry in native envoy Mode A (registry.startAndWait()). The registry opens one persistent outbound connection to the Rivet Engine; the Engine routes actor calls back over that connection, so no inbound HTTP callback is required. Port 6421 is an internal Engine API-peer port and must not be used as RIVET_ENDPOINT. Do not set RIVET_SERVERLESS_URL or RIVET_SERVERLESS_TOKEN; they are unused in this topology.

Gitea

GITEA_URL=https://git.openputer.com
GITEA_TOKEN=<personal-access-token>

GITEA_TOKEN is optional for read-only agent startup but required for the complete issue-to-PR flow unless Tea and Git already have sufficient local credentials.

The legacy variables VITE_FLUE_URL and VITE_ZOPU_SERVER_URL are not used by the active web chat path.

One-time Convex setup

On a new machine, authenticate and configure the Convex development deployment:

bun run dev:setup

Then configure the deployment-scoped values from packages/backend:

cd packages/backend
bunx convex env set SITE_URL 'http://localhost:5173'
bunx convex env set FLUE_DB_TOKEN '<same value as .env>'
bunx convex env set FLUE_URL 'http://<tailscale-ip>:3585'

Convex runs in the cloud, so FLUE_URL must be reachable from the deployment. 127.0.0.1 and localhost point at Convex's machine, not your laptop. For the current Mac setup, expose Flue on the Mac's Tailscale address, for example http://100.x.y.z:3585.

SITE_URL is deployment-scoped and single-valued. Set it to the exact browser origin currently being tested:

# Browser opened locally
bunx convex env set SITE_URL 'http://localhost:5173'

# Browser opened from another device over Tailscale
bunx convex env set SITE_URL 'http://<tailscale-ip>:5173'

If work execution uses a separate agent URL, set AGENT_BACKEND_URL; otherwise it falls back to FLUE_URL.

Start the stack

Run each process in its own terminal. The Engine must be healthy before the agents process starts.

1. Start Convex development

# Publish once after backend changes
pnpm --filter @code/backend dev:once

# Watch and republish while developing
pnpm dev:server

Both commands run from packages/backend and explicitly load the repository-root .env with --env-file=../../.env. packages/backend/.env.local remains Convex CLI metadata for the selected deployment; keep the shared runtime settings in the root .env.

2. Start the Rivet Engine

Start exactly one Engine listening on 127.0.0.1:6420 using the local Engine deployment mechanism. Do not use port 6421 as the application endpoint.

3. Start the agents process

# Laptop-only access
pnpm --filter @code/agents dev -- --port 3585

# Convex callbacks or access from another device
HOST=0.0.0.0 \
RIVET_ENDPOINT=http://127.0.0.1:6420 \
FLUE_URL=http://<tailscale-ip>:3585 \
pnpm --filter @code/agents dev -- --port 3585

This single process serves the Hono/Flue routes and starts the AgentOS registry in native envoy Mode A during app module initialization (registry.startAndWait()). The registry opens an outbound connection to the Rivet Engine; actor calls are routed back over that connection, so there is no separate runner process and no inbound serverless callback route. If shell exports override .env, set RIVET_ENDPOINT explicitly.

4. Start the web application

If you are not using the root dev script, start the web app separately.

For laptop-only access:

pnpm dev:web

For phone or other Tailscale-device access:

pnpm dev:tailscale:web

Open http://localhost:5173, or http://<tailscale-ip>:5173 when using the Tailscale command.

Verify the setup

Check the listeners:

curl -fsS http://127.0.0.1:6420/health
curl -fsS http://127.0.0.1:3585/health
curl -I http://127.0.0.1:5173

The first two commands must return a successful health response; the web root may redirect or return 404 if its functional routes live elsewhere.

Then verify behavior in order:

  1. Open the web app and sign in.
  2. Send a simple chat message and confirm the response streams back through Convex.
  3. Ask Zopu to list open Gitea issues.
  4. For the full execution path, send Create a PR for issue #N for an open, unassigned test issue.
  5. Confirm chat immediately reports that the issue was accepted.
  6. Follow the Flue server logs for [create_pr_for_issue] and wait for a completed line with the PR URL.
  7. Confirm the branch and pull request in Gitea.

The PR pipeline is asynchronous: the initial chat turn acknowledges acceptance, while AgentOS implements, commits, pushes, and opens the pull request in the background.

Request flow

Web sends a conversation mutation to Convex
  -> Convex persists the exact message
  -> Convex dispatches to FLUE_URL/agents/zopu/<organizationId>
  -> Flue runs the Zopu agent and its typed tools
  -> responses return to Convex
  -> the web observes Convex's reactive projection

For code execution:
  -> Flue calls the AgentOS actor through the Rivet Engine
  -> a Rivet actor boots an AgentOS VM with the project workspace
  -> the actor clones the repository and runs validated commands
  -> the actor writes artifacts back through the actor RPC

Common failures

Chat stays pending or reports that Flue is unavailable

  • Confirm Flue is listening on 3585.
  • Confirm the Convex deployment's FLUE_URL uses a host-reachable address, not localhost.
  • Confirm FLUE_DB_TOKEN is identical in .env and the Convex deployment.

Sign-in fails or the browser reports CORS errors

Set Convex SITE_URL to the exact browser origin. The shared development deployment trusts only the current single value.

AgentOS fails while mounting the repository

  • Confirm the Engine is healthy at http://127.0.0.1:6420/health.
  • Confirm the agents process is running and the registry started the envoy connection on startup.
  • Confirm the process has RIVET_ENDPOINT=http://127.0.0.1:6420.
  • Confirm AGENT_WORKSPACE_ROOT is writable.
  • Restart the agents process after changing the actor configuration; the registry re-registers actor type changes with the engine on startup.

The actor client requires CBOR encoding for actor RPC. Do not remove the encoding: "cbor" configuration in packages/agents/src/adapters/agentos.ts.

AgentOS reports an ACP completed-message resource limit

Restart the agents process so the registry re-registers its updated actor configuration with the engine.

The process connects to a remote Rivet deployment unexpectedly

Environment variables exported by the shell override values loaded from .env. Start the agents process with explicit RIVET_ENDPOINT=http://127.0.0.1:6420.

Gitea issue or PR commands fail

Run:

tea login list
git ls-remote origin HEAD
tea issues list

Confirm the default Tea login, SSH key, repository remote, and token all target git.openputer.com.

Repository checks

After changing source or configuration:

bunx ultracite check <changed-files>
bun run check-types
bun run check

For agent-only changes, run bun run check-types from packages/agents before the root check.

See also: