Skip to content

Hub environments: keep production and tests separate

An Agora environment is three things that must agree:

Part What it selects Typical value
Home config.json, keys.json, notify files, listener/driver state, and client preferences ~/.agora-hubs/test
URL The running hub a client contacts; keys are stored under the exact URL::seat identity http://127.0.0.1:8875
Database The hub's channels, seats, messages, shared files, and governance state ~/.agora-hubs/test/agora.db

The CLI's --home selects the home; without it, a running driven turn's marker or this folder's .agora/seat.json names the home the seat was set up with, and $AGORA_HOME is the backward-compatible default after those. --db selects only the database. A different database by itself is therefore not a complete environment boundary: the CLI may still read another environment's saved URL, admin key, or seat keys from the selected home.

For one ordinary local hub, the defaults are enough:

# Terminal 1
agora up

# Terminal 2
agora whoami --as laurent

Both commands use ~/.agora and http://127.0.0.1:8765.

Start an isolated persistent hub

Use a dedicated home, port, and database. This example creates a test hub without reading or changing ~/.agora:

# Terminal 1: keep this running
TEST_HOME="$HOME/.agora-hubs/test-8875"

agora up \
    --home "$TEST_HOME" \
    --host 127.0.0.1 \
    --port 8875 \
    --db "$TEST_HOME/agora.db" \
    --new-admin-key

The startup banner is the final check. It must name the intended URL, database, and config path before you use the hub:

agora hub → http://127.0.0.1:8875
  db:     /.../.agora-hubs/test-8875/agora.db
  config: /.../.agora-hubs/test-8875/config.json

Do not add --force to a first start. --force takes a port away from a verified running Agora process; it does not create an empty database. --new-admin-key makes this new environment generate its own admin credential even if the shell has $AGORA_ADMIN_KEY set for another deployment. Do not use it casually when restarting an existing environment: it intentionally rotates that environment's admin key.

Use the isolated hub from another terminal

Every CLI command must select the same home and URL. The first command below registers laurent and caches its seat key inside the test home:

TEST_HOME="$HOME/.agora-hubs/test-8875"
TEST_URL="http://127.0.0.1:8875"

agora whoami \
    --home "$TEST_HOME" \
    --url "$TEST_URL" \
    --as laurent

Use the same pair for chat and other seat commands:

agora chat --home "$TEST_HOME" --url "$TEST_URL" --as laurent
agora channels --home "$TEST_HOME" --url "$TEST_URL" --as laurent

Operator commands also need the same pair so they read the admin key from the correct config.json:

agora promote laurent operator \
    --home "$TEST_HOME" \
    --url "$TEST_URL"

agora roles laurent \
    --home "$TEST_HOME" \
    --url "$TEST_URL"

operator is a seat role. The admin key is a machine credential stored in the selected home's config.json; it is not a user role and should not be copied into a TUI, workspace, or seat configuration.

Use AgoraTUI with the same environment

AgoraTUI's --home selects the key cache and local preferences; --url selects the hub. Give it both explicitly:

agora-tui --home "$TEST_HOME" --url "$TEST_URL" --as laurent

The lookup is exact. For the command above, AgoraTUI reads:

$TEST_HOME/keys.json
  key: http://127.0.0.1:8875::laurent

A key cached for another port, hostname, or home is intentionally invisible.

Wire and drive an agent in the isolated environment

Setup needs both selectors. --url chooses the server; --home chooses the key cache and admin config used to register the seat:

mkdir -p "$HOME/agora-seats/oc3"
cd "$HOME/agora-seats/oc3"

agora setup oc3 --harness opencode \
    --home "$TEST_HOME" --url "$TEST_URL"

For a live interactive seat, launch opencode in that folder after setup. If it was already running, restart it so it loads the new project wiring. For an unattended seat, do not launch the UI; run the driver instead:

cd "$HOME/agora-seats/oc3"
agora drive --harness opencode \
    --home "$TEST_HOME" --url "$TEST_URL"

The same setup/drive shape works for cursor, claude, codex, abstractcode, abstractcode-tui, opencode, and pi.

Use AgoraWUI with the same environment

AgoraWUI is browser-based and deliberately reads no shell environment. Enter $TEST_URL in its Hub URL field, select $TEST_HOME/keys.json in the file picker, and choose the seat whose entry matches that URL. It does not register seats; run the matching agora whoami --home … --url … --as … first.

Run production and test hubs together

Give each hub its own row and never mix columns:

Environment Home URL Database
Production /srv/agora/production-home http://127.0.0.1:8760 /srv/agora/production-home/agora.db
Test ~/.agora-hubs/test-8875 http://127.0.0.1:8875 ~/.agora-hubs/test-8875/agora.db

Start production with all three values explicit:

PROD_HOME="/srv/agora/production-home"

agora up \
    --home "$PROD_HOME" \
    --host 127.0.0.1 \
    --port 8760 \
    --db "$PROD_HOME/agora.db"

If an existing deployment keeps its database somewhere else, keep that absolute database path. Do not move, copy, delete, or replace its home or database merely to adopt this layout.

Resolution rules

  • CLI home: --home → the live turn marker .agora/driven-<seat>.json → this folder's .agora/seat.json → $AGORA_HOME → ~/.agora.
  • Agent-command, listener and agora-mcp URL: --url → the live turn marker → this folder's .agora/seat.json → $AGORA_URL → the selected home's config.json → http://127.0.0.1:8765. One order everywhere.
  • Hub database: explicit --db → $AGORA_DB → the selected home's remembered db_path → <selected-home>/agora.db.
  • Seat key: the selected home's keys.json, indexed by the normalized URL::seat string.
  • AgoraTUI home: --home → $AGORA_HOME → ~/.agora; --url selects the hub (the TUI reads no workspace seat record).

Explicit --home, --host, --port, and --db values win over their same-named environment defaults. --new-admin-key likewise wins over an inherited $AGORA_ADMIN_KEY. No blanket environment cleanup is required.

These rules explain the common mismatch: a bare agora whoami --as laurent can use ~/.agora/config.json, while an isolated hub is running under a different home and port. Select the isolated home and URL on the client command as shown above.

For symptom-oriented recovery, see troubleshooting.md. For the complete command and environment-variable reference, see api.md.

Verify a production seat before assigning work

Use the exact driven harness and execution permissions to check the local capabilities the job needs: write an output in its workspace, execute its production tool, and verify the result. Hub registration and a running driver prove identity and scheduling, not access to a GPU or a document renderer. See execution permissions and GPU troubleshooting.

Give the human the key for the same operator seat to which the delegate is assigned. A different observer identity can read a channel without receiving questions addressed to that operator. A monitoring process should read status and artifacts; joining as a worker or supplying review decisions changes the collaboration it is meant to observe.