Capability operator setup¶
This guide tells the service provider running a Colony deployment what to configure on the deployment host (env vars, external accounts, Docker socket, optional volume mounts) so that the five new agent capabilities work end-to-end.
Some capabilities (
GitHubCapabilityin particular) also require per-tenant work by a tenant admin and per-user work by an end user — seegithub-app-setup.mdandconnect-github.mdfor the three-role split. This page covers the service-provider piece only.
The capabilities themselves are bound to the session agent unconditionally — none of them crash the agent when their configuration is missing. Each one degrades to a clean "not configured" error dict that the LLM can surface to the user. So no setup is mandatory; configure only the capabilities you actually plan to use.
| Capability | Required env vars | External setup |
|---|---|---|
VCMCapability |
none | none |
WebSearchCapability |
TAVILY_API_KEY |
Tavily account |
ColonyDocsCapability |
TAVILY_API_KEY (same) |
Tavily account |
SandboxedShellCapability |
none | Docker daemon (already mounted in dev) |
UserPluginCapability |
none | optional: host mount for custom skills |
GitHubCapability |
GITHUB_APP_ID, GITHUB_PRIVATE_KEY_PEM, optionally GITHUB_APP_CLIENT_ID + GITHUB_APP_CLIENT_SECRET for the per-user OAuth flow |
GitHub App registration; per-tenant App installation set via the dashboard (not env) — see github-app-setup.md |
The full list of compose env-var passthroughs is in
colony/cli/deploy/docker/docker-compose.yml.
Every entry uses ${VAR:-} so an empty value is acceptable; the
capability simply stays disabled.
How env vars reach the cluster¶
colony-env up shells out to docker compose up. Docker Compose
substitutes ${VAR:-default} against the operator's shell
environment, so any variable you export in the shell that runs
colony-env up flows through to ray-head and ray-worker.
The cleanest pattern is a .env file at the directory you launch
from (Compose auto-loads it):
# .env (gitignored — never check in)
TAVILY_API_KEY=tvly-...
GITHUB_APP_ID=123456
GITHUB_PRIVATE_KEY_PEM="-----BEGIN RSA PRIVATE KEY-----
MIIEow...
-----END RSA PRIVATE KEY-----
"
# Optional — only needed for the "Connect GitHub" user OAuth flow.
GITHUB_APP_CLIENT_ID=Iv1.abc...
GITHUB_APP_CLIENT_SECRET=...
The per-tenant installation_id is not set in env — it's stored per-tenant in Postgres (set by the tenant admin via the dashboard's Tenant GitHub Installation panel). See github-app-setup.md.
Then:
To rotate a key: edit .env, then colony-env down && colony-env up.
Restarting just the cluster process (without down) doesn't pick up
new env vars.
WebSearchCapability / ColonyDocsCapability¶
Both capabilities use the same TavilyBackend and therefore the same
TAVILY_API_KEY.
- Create a Tavily account at https://tavily.com.
- Generate an API key in the dashboard.
export TAVILY_API_KEY=tvly-...(or add to.env).colony-env down && colony-env up.
The first search_web or search_docs call after restart will
exercise the backend; if the key is wrong, the action returns
{ok: false, message: "Tavily API ..."} instead of crashing the
agent.
To swap to a different backend (SerpAPI, Bing, Brave) without
changing capability code, subclass SearchBackend and pass it via
the blueprint — see the
capability doc.
SandboxedShellCapability¶
Already wired in dev. Docker socket is bind-mounted into both
ray-head and ray-worker; the curated image registry is mounted at
/etc/colony/sandbox-images.yaml:ro.
Production hardening. The dev mount of /var/run/docker.sock
gives anything inside ray-head root-equivalent access to the host
through the daemon. For multi-tenant deployments:
- Run a separate hardened Docker daemon and expose it over TLS.
- Set
DOCKER_HOST=tcp://hardened-daemon:2376in ray-head / ray-worker (and remove the socket mount). - Mount the TLS client certs (
DOCKER_CERT_PATH,DOCKER_TLS_VERIFY).
See design_SandboxedShellCapability.md §5.3 for the full plan.
Image registry. The default
sandbox-images.yaml
ships two roles (default, code_analysis) both pointing at
python:3.11-slim — an image that exists on Docker Hub so the
capability works out of the box. To add a role with a real toolchain:
- Edit
sandbox-images.yaml(the file is mounted read-only from the repo, so edit it on the host andcolony-env down/upto pick up the change). - Pin by digest in production:
image: ghcr.io/.../analyzer@sha256:abc…. - Optionally declare named scripts so
execute_script(name=…)is available — these are vetted command lines per role.
UserPluginCapability¶
The capability ships a bundled
colony-samples plugin
(three skills) that auto-discovers without any setup — they live
inside the wheel and the session agent's blueprint passes
extra_plugin_roots to expose them.
To add custom skills that live on your host, mount their directory into the container at one of the discovery roots:
| Discovery root inside the container | What it's for |
|---|---|
/etc/colony/skills and /etc/colony/plugins |
operator-managed shared skills (lowest priority) |
~/.colony/skills and ~/.colony/plugins |
per-user skills — but ~ inside the ray container is the ray user's home, not the operator's |
/workspace/.colony/skills |
session-scoped (mounted per session by the workspace mount) |
The simplest pattern for a developer machine is to drop a
docker-compose.override.yml next to the main one:
services:
ray-head:
volumes:
- ${HOME}/.colony:/etc/colony:ro
ray-worker:
volumes:
- ${HOME}/.colony:/etc/colony:ro
Skills you put in ~/.colony/skills/<name>/SKILL.md on the host
appear at /etc/colony/skills/<name>/SKILL.md inside the container
and the capability picks them up at SYSTEM priority. (See the
layout reference
for SKILL.md schema.)
A future Settings UI tab will surface discovered skills with
enable/disable toggles; until then, edit on the host and call
reload_skills from the agent (or restart the cluster).
GitHubCapability¶
Uses GitHub App auth — not personal access tokens. The full setup
(register the App, set the env vars, install the App per tenant,
wire the per-user OAuth flow) is documented in
github-app-setup.md. The summary for this
page:
- Service provider (you, on this host): set
GITHUB_APP_ID,GITHUB_PRIVATE_KEY_PEM, and (for the per-user "Connect GitHub" flow)GITHUB_APP_CLIENT_ID+GITHUB_APP_CLIENT_SECRET. The shape is shown in the.envblock earlier on this page;github-app-setup.md§2 has the rotation - private-key handling.
- Tenant admin: installs the App into the tenant's GitHub org
and pastes the resulting installation id into the dashboard's
Tenant GitHub Installation panel —
github-app-setup.md§3. - End user: clicks Connect GitHub on their profile —
connect-github.md.
Audit + rate limits¶
- Every mutation writes a blackboard record at
audit:github:{ts}:{uuid}— visible from the dashboard's Blackboard tab. - The App's installation is rate-limited to 5 000 req/h. The
capability surfaces primary-rate-limit errors as
{ok: false, status_code: 403}and backs off automatically on secondary (abuse) limits, honouringRetry-After.
VCMCapability¶
No setup. The VCM is part of the cluster's standard deployment, and
the capability is a thin facade over its existing endpoints. The
filesystem watcher uses watchfiles,
which is already in the dependency closure.
The watcher operates on paths visible to the ray-head /
ray-worker process — typically anything under /mnt/shared/filesystem
where Colony clones repos via mmap_repo. If you mount additional
host directories and want them watched, configure
watch_root="/your/path" on the capability blueprint.
Where the env vars live in code¶
For traceability, here's where each variable is read:
| Env var | Reader | Action surface |
|---|---|---|
TAVILY_API_KEY |
_github/auth.py-style fallback in TavilyBackend.__init__ |
search_web, fetch_page, search_docs, fetch_doc |
GITHUB_APP_ID |
GitHubCapability._build_live_client |
every GitHubCapability action |
GITHUB_PRIVATE_KEY_PEM |
same (also accepts private_key_path kwarg) |
same |
GITHUB_APP_CLIENT_ID |
routers/github_oauth.py::github_connect |
GET /auth/github/connect, GET /auth/github/callback |
GITHUB_APP_CLIENT_SECRET |
routers/github_oauth.py::github_callback |
GET /auth/github/callback |
The per-tenant installation_id is not an env var — it's
populated per-tenant in Postgres (tenants.github_installation_id),
set via the dashboard. GitHubCapability._build_live_client reads
it from agent.metadata.parameters["github_identity"]["tenant_installation_id"]
(threaded by the session-create handler).
A capability whose env var is missing logs a one-line warning at agent startup and returns clean error dicts when invoked.