Execution
Colony — Peer Capabilities
Share a model running on your own machine - Ollama, a Gradio app, a local MCP server - with everyone in scope on the shared warehouse, as plain SQL.A Colony turns the shared warehouse into a shared arsenal. Anyone running Data Rabbit can attach something running on their own machine — the Ollama model on their workstation, a Gradio specialist they built, a local stdio MCP server — and everyone in scope on the same database can call it from plain SQL while that person's client stays up.
The database is the rendezvous. There is no relay, no tunnel, no new service: a share is a pair of catalog rows plus a request/response queue inside Postgres, and the sharer's Data Rabbit client polls for work the same way it already polls for everything else. The shared laptop never accepts an inbound connection — it dials out to the database it already trusts, which makes the whole thing NAT- and firewall-friendly by construction.
What a share looks like#
Three transport shapes cover the useful local world:
| Shape | What it fronts | Payload in | Answer out |
|---|---|---|---|
openai_chat |
Any OpenAI-compatible endpoint — Ollama, vLLM, LM Studio | {"user": "..."} |
the model's reply as text |
gradio |
A local Gradio app (the classic ML-demo shape) | {"user": "..."} |
the app's output as text |
mcp |
A local stdio MCP server the client spawns and holds | {"tool": "...", "args": {...}} |
the tool's result |
Every share is scoped to a Postgres role — the same burrow roles that gate everything else. Only members of that role can call it; everyone else is rejected server-side, before any work is queued.
Sharing something#
Open the Colony window in Data Rabbit and hit Share a capability. The Scan for local models button probes Ollama's default port and the common Gradio ports — explicitly, when you click it, never in the background — and offers what it finds as one-click candidates. Pick a name, a kind, a scope role, and share.
Sharing runs from the Data Rabbit desktop app (or a self-hosted instance)
because its local server is the runner — it's the process that can
actually see localhost:11434. Calling a shared capability needs
nothing special: it's just SQL, from any client.
Your machine's hostname is recorded with the share, so the Fleet map can draw your laptop as the cluster member it now is.
Calling one#
Ad hoc, from anywhere with access:
-- chat / gradio shapes
SELECT rvbbit.call_specialist('colony_ollama',
'{"user": "Summarize: revenue grew 12% while costs held flat."}'::jsonb);
-- mcp shape
SELECT rvbbit.call_specialist('colony_tools',
'{"tool": "echo", "args": {"message": "hello"}}'::jsonb);
A peer backend is just another backend — the router, receipts, and operator machinery don't know the difference. That means you can build a real SQL operator on top of a colleague's shared model:
-- An LLM-shaped operator pinned to a Colony peer (chat semantics):
SELECT rvbbit.create_operator('team_summarize', ARRAY['text'], 'text',
op_steps := '[{"kind":"llm","name":"main",
"system":"You are a concise summarizer. One sentence.",
"user":"Summarize: {{ inputs.text }}",
"provider":"colony_ollama","model":"llama3.1:latest"}]'::jsonb);
-- A specialist-shaped operator over a shared Gradio app:
SELECT rvbbit.create_operator('team_sentiment', ARRAY['t'], 'text',
op_steps := '[{"kind":"specialist","name":"s",
"specialist":"colony_sentiment",
"inputs":{"user":"{{t}}"}}]'::jsonb);
SELECT title, team_sentiment(body) FROM feedback LIMIT 50;
Once created, those operators work inline in any query, get receipts and
cost accounting like everything else, and show up in
rvbbit.capability_search() for agents to discover.
Finding what's shared#
Shared capabilities are first-class citizens of the capability graph:
SELECT * FROM rvbbit.capability_search('something that can classify sentiment');
returns Colony peers alongside operators and packs, with their live
status in the description (LIVE — 1 instance online, OFFLINE,
PAUSED by its sharer). The Capability Explorer window browses them
under Peer Capabilities (Colony), and the Fleet window draws each
sharing machine as a node on the cluster map — named by hostname, with
the shared capabilities as its skills.
The live roster in SQL:
SELECT * FROM rvbbit.peer_backends_live;
-- backend_name · kind · scope_role · shared_by · enabled
-- · instance_count · min_queue_depth
Lifecycle#
The sharer stays in control:
SELECT rvbbit.set_peer_backend_enabled('colony_ollama', false); -- pause
SELECT rvbbit.set_peer_backend_enabled('colony_ollama', true); -- resume
SELECT rvbbit.deregister_peer_backend('colony_ollama'); -- detach
Pausing keeps the share visible but marked PAUSED — discoverable, not
callable. Detaching removes the registration entirely and fails any
in-flight requests with a clear error (peer backend was detached by its sharer) rather than letting them hang. Closing the Data Rabbit client
simply stops the heartbeat: the share reads OFFLINE until the client
returns, and new calls fail fast with "has no live instance right now".
Many machines, one name#
If several machines register runners under the same backend name, the
queue fans work out across them automatically — each request is claimed
exactly once (FOR UPDATE SKIP LOCKED, the standard Postgres queue
idiom), and faster or less-busy machines naturally claim more. A team can
turn three workstations with the same Ollama model into a small
answering pool without configuring anything beyond sharing under one
name.
Those runners must connect to the warehouse as the same database role — serving a backend is restricted to its sharer (see below), and the sharer is the role that registered the name first. Pointing three Data Rabbit instances at the same connection is the normal way this happens; pooling across genuinely different database accounts is not supported.
The rules that keep it honest#
- Scope is enforced in the database. Calling a share is gated by a real Postgres role membership check. Not in the client, not in a gateway — in the same place your data's permissions already live.
- Serving is restricted to the sharer. Only the database role that registered a backend can claim its requests, write its answers, or heartbeat for it. Another user on the same warehouse cannot pull the prompts being sent to your model, answer on its behalf, or pretend it is online.
- An answer goes back only to the caller who asked. Holding a request id is not enough to read its response.
- The sharer's machine only dials out. Nothing ever connects to the sharing client. It claims work from the queue over its existing database connection.
- Requests are rows. Every call — payload, response, status, timing — is a row in your database, auditable like everything else. Share with groups you'd be comfortable seeing your model's prompts.
- Absence is a fast failure, not a hang. No live runner means an immediate error; timeouts mark requests failed; detaching fails in-flight work explicitly.
Advanced: the raw queue#
call_specialist() wraps a two-step contract you can also drive
directly — enqueue, then poll:
SELECT rvbbit.enqueue_peer_request('colony_ollama',
'{"user": "hello"}'::jsonb); -- returns a request uuid
SELECT rvbbit.poll_peer_response('<uuid>'::uuid, 30000);
These are deliberately two separate statements. A single function that both enqueues and waits can never work in Postgres: its INSERT stays invisible to every other backend — including the runner trying to claim it — until the statement commits, which can't happen while it's still waiting. The two-step shape is the contract, not a convenience.