colibri/docs/guide/reference/multi-agent.md

182 lines
5.6 KiB
Markdown
Raw Permalink Normal View History

---
title: 'Multi-Agent Deployment (Optional)'
---
Clawdie supports running multiple independent agents on the same FreeBSD host,
but the default path is **one agent per host or per bhyve VM**. Use this guide
only when you intentionally want a second agent later.
## Quick decision
- **Easiest isolation:** one agent per **bhyve VM** (each VM has its own `warden0`)
- **Same-host multi-agent:** one host `warden0` bridge carries **multiple /24 subnets**
## Concepts (what must stay unique)
Separate runtime names from portable agent identity. A host may run multiple
agents, and an agent may also carry a portable soul bundle (`SOUL.md`,
`USER.md`, `IDENTITY.md`, `AGENTS.md`) cloned from a dedicated repo. Runtime
names keep services, jails, datasets, and sockets from colliding; soul files
carry who the agent is and what context it may reuse across hosts or harnesses.
- `AGENT_NAME` is the runtime identity key:
- rc.d service name (`/usr/local/etc/rc.d/${AGENT_NAME}`)
- tmux session name
- jail name prefix (recommended)
- DB identifiers (users + databases)
- `AGENT_SUBNET_BASE` assigns a dedicated `/24` to that agent:
- pick any private `/24` that does not collide with another agent
- repo examples below use `10.0.1`
- live installs can also use `192.168.72`, `172.16.50`, etc
- you can also use `172.16.50`, `192.168.100`, etc — pick any private `/24` and stay consistent
- `warden0` is the canonical bridge name. A single `warden0` can host multiple
subnets; the host must own the `.1` gateway IP **for each subnet**.
- Prefer **VNET jails** (`bastille create -B ... warden0`) for cleaner isolation.
## Portable soul repos
For multi-host or multi-harness continuity, keep durable agent identity in a
small dedicated repository instead of baking it into one install. The same repo
can be pulled by Pi, Hermes, Codex, Claude Code, or Colibri and adapted into the
harness-specific prompt/config layer.
Recommended shape:
```text
SOUL.md # durable agent identity, values, voice, operating style
USER.md # operator/user context shared with this agent when allowed
IDENTITY.md # short runtime identity and boundaries
AGENTS.md # harness-facing rules when supported
manifest.json # schema version, provenance, sharing rules
```
Rules:
- keep secrets out of the soul repo;
- keep runtime state in `system_ops`, not in identity files;
- import long-lived memories into `system_brain` only when the operator allows;
- keep skills/reviewed procedures in `system_skills` or referenced skill repos.
## Same-host multi-agent (VNET path)
Example: add a second agent named `atlas` on `10.0.1.0/24`.
### 1) Create a second project directory
Use a separate clone so each agent has its own `.env`, `logs/`, and runtime state.
### 2) Configure `.env` for the second agent
Minimum keys to set (example values):
```env
AGENT_NAME=atlas
ASSISTANT_NAME=Atlas
AGENT_SUBNET_BASE=10.0.1
WARDEN_GATEWAY=10.0.1.1
WARDEN_SUBNET=10.0.1.0/24
WARDEN_GIT_IP=10.0.1.2
WARDEN_CMS_IP=10.0.1.3
WARDEN_OLLAMA_IP=10.0.1.4
WARDEN_LLAMA_CPP_IP=10.0.1.4
WARDEN_DB_IP=10.0.1.5
```
These are example values only. If your host already uses another private
subnet, keep that and stay consistent across the rest of the file.
Jail name overrides (avoid collisions with an existing agents jails):
```env
CMS_JAIL_NAME=atlas-cms
OLLAMA_JAIL_NAME=atlas-ollama
LLAMA_CPP_JAIL_NAME=atlas-llamacpp
```
Notes:
- `setup/git.ts` already defaults to `${AGENT_NAME}-git`, so `GIT_JAIL_NAME` is
usually not required.
- If you decide to share a local LLM jail across agents, keep a single `ollama`
jail and point both agents at the same IP instead of creating per-agent LLM jails.
### Locale per agent (optional but supported)
Each agent can display in its own language without changing the host locale.
Keep the host system locale stable (UTF-8), then set per-agent display/assistant
locales in that agents `.env`:
```env
DISPLAY_LOCALE=sl-SI
ASSISTANT_LOCALE=sl-SI
SYSTEM_LOCALE=sl_SI.UTF-8
```
For a different agent, choose different values (e.g. `de-DE`, `ru-RU`, `zh-CN`).
Do not use legacy encodings; `SYSTEM_LOCALE` must remain UTF-8.
If multiple agents share one tmux server, new panes inherit the server locale.
Either use separate tmux sessions per agent or set locale env vars inside each
agents rc.d service environment.
### 3) Add the new gateway IP to `warden0`
Runtime (immediate):
```sh
sudo ifconfig warden0 inet 10.0.1.1/24 alias
```
Persist across reboots (choose the next free alias index):
```sh
sudo sysrc ifconfig_warden0_alias0="inet 10.0.1.1/24"
```
### 4) Update PF NAT to include both subnets
If you use an include such as `/etc/pf.warden.conf`, the key idea is:
```pf
warden_net = "{ 10.0.1.0/24, 192.168.72.0/24 }"
nat on $ext_if from $warden_net to any -> ($ext_if)
pass quick on warden0 inet from $warden_net to any keep state
```
Reload PF:
```sh
sudo pfctl -nf /etc/pf.conf
sudo pfctl -f /etc/pf.conf
```
### 5) Provision the second agents service jails
From the second agent repo directory:
```sh
sudo just setup-db
sudo just setup-git
sudo just setup-cms
sudo just setup -- --step ollama # optional
sudo just setup -- --step llama-cpp # optional
```
Database provisioning can be done either via `just setup-db` (or `npm run setup -- --step db`) or via Ansible
playbooks in `infra/ansible/playbooks/`.
### 6) Install and start the second rc.d service
```sh
sudo just setup -- --step service
sudo service atlas onestart
```
## bhyve note
If you deploy one agent per **bhyve VM**, you typically do **not** need any of
the same-host subnet aliasing or multi-subnet PF rules. Each VM can keep a
single-agent `warden0` + single `/24` internally.