Use for every task involving this project. Covers running Ganglion, its CLI commands, HTTP bridge API, pipeline execution, knowledge queries, configuration,...
---
name: ganglion
description: "Use for every task involving this project. Covers running Ganglion, its CLI commands, HTTP bridge API, pipeline execution, knowledge queries, configuration, and operational workflows. Trigger phrases: 'run the pipeline', 'start the server', 'check status', 'query knowledge', 'configure', 'call the API', 'scaffold a project', 'check metrics', 'rollback', 'swap policy'."
homepage: https://github.com/TensorLink-AI/ganglion
metadata: {"openclaw": {"emoji": "📘", "requires": {"bins": ["python3", "ganglion"], "env": ["LLM_PROVIDER_API_KEY"]}, "always": true}}
---
# Ganglion — Operator's Manual
Ganglion is a domain-specific execution engine for Bittensor subnet mining. It provides a pipeline framework for orchestrating autonomous mining agents that search for optimal model configurations. It exposes a CLI, an HTTP bridge API, and a Python library. Ganglion is search infrastructure — it doesn't know what a good model looks like, it knows how to search for one.
## Quick Reference
```bash
# Scaffold a new project
ganglion init ./my-subnet --subnet sn9 --netuid 9
# Check state (local mode)
ganglion status ./my-subnet
ganglion tools ./my-subnet
ganglion agents ./my-subnet
ganglion knowledge ./my-subnet --capability training --max-entries 10
ganglion pipeline ./my-subnet
# Run (local mode)
ganglion run ./my-subnet
ganglion run ./my-subnet --stage plan
ganglion run ./my-subnet --overrides '{"target_metric":"accuracy"}'
# Start HTTP bridge (remote mode)
ganglion serve ./my-subnet --bot-id alpha --port 8899
# Check state (remote mode)
curl -s "$GANGLION_URL/v1/status" | jq .data
```
## Mode Detection
Ganglion supports two modes. **Always check which mode applies before running commands.**
- **Local mode**: No `GANGLION_URL` set, or `GANGLION_PROJECT` is set. Use `ganglion <command> <project_dir>` directly.
- **Remote mode**: `GANGLION_URL` is set. Use `curl` against the HTTP bridge.
```bash
if [ -n "$GANGLION_PROJECT" ] || [ -z "$GANGLION_URL" ]; then
echo "local"
else
echo "remote"
fi
```
## Response Format
All HTTP bridge endpoints (except health probes) return responses in a standard envelope:
- **Success**: `{"data": <payload>}` — use `jq .data` to extract
- **Error**: `{"detail": {"error": {"code": "ERROR_CODE", "message": "..."}}}`
Health probes (`/healthz`, `/readyz`) return raw JSON without the envelope.
Interactive API docs: `$GANGLION_URL/v1/docs` (Swagger UI).
> **Note:** Unversioned routes (e.g. `/status`) still work but are deprecated. Always use `/v1/`.
## How to Run
**Prerequisites:** Python >= 3.11, `LLM_PROVIDER_API_KEY` set (used by the LLM runtime).
**Install:** `pip install ganglion`
**Scaffold a project:**
```bash
ganglion init ./my-subnet --subnet sn9 --netuid 9
```
This creates `config.py`, `tools/`, `agents/`, and `skill/` in the target directory.
**Start in local mode:**
```bash
export GANGLION_PROJECT=./my-subnet
ganglion status $GANGLION_PROJECT
```
**Start in remote mode:**
```bash
ganglion serve ./my-subnet --bot-id alpha --port 8899
export GANGLION_URL=http://127.0.0.1:8899
```
The project directory must contain a `config.py` that defines `subnet_config` (SubnetConfig) and `pipeline` (PipelineDef). See `{baseDir}/references/configuration.md` for full config details.
## Key Features
### Observe State
Query the current framework state — registered tools, agents, pipeline definition, knowledge, metrics, and run history. Local mode uses CLI commands; remote mode uses GET endpoints.
Full reference: `{baseDir}/references/commands.md`
### Execute Pipelines
Run the full pipeline or a single stage. The orchestrator executes stages in dependency order, applies retry policies, injects accumulated knowledge into agent prompts, and records outcomes.
```bash
# Local
ganglion run ./my-subnet
ganglion run ./my-subnet --stage plan
# Remote
curl -s -X POST "$GANGLION_URL/v1/run/pipeline" -H "Content-Type: application/json" -d '{}' | jq .data
curl -s -X POST "$GANGLION_URL/v1/run/stage/plan" -H "Content-Type: application/json" -d '{}' | jq .data
```
### Mutate at Runtime (Remote Only)
Register new tools, agents, and components; patch the pipeline; swap retry policies; update prompts. All mutations are validated, audited, and reversible.
```bash
# Register a tool
curl -s -X POST "$GANGLION_URL/v1/tools" -H "Content-Type: application/json" \
-d '{"name":"my_tool","code":"<code>","category":"training"}' | jq .data
# Patch pipeline
curl -s -X PATCH "$GANGLION_URL/v1/pipeline" -H "Content-Type: application/json" \
-d '{"operations":[{"op":"add_stage","stage":{"name":"validate","agent":"Validator","depends_on":["train"]}}]}' | jq .data
```
Pipeline operations: `add_stage`, `remove_stage`, `update_stage`. See `{baseDir}/references/commands.md` for all mutation endpoints.
### Knowledge Store
Cross-run strategic memory that compounds over time. Records patterns (what worked) and antipatterns (what failed), then automatically injects relevant history into agent prompts. Knowledge is queried by capability and filtered by bot_id for multi-bot setups.
```bash
# Local
ganglion knowledge ./my-subnet --bot-id alpha --capability training
# Remote
curl -s "$GANGLION_URL/v1/knowledge?capability=training&max_entries=10" | jq
```
### Rollback
Undo any mutation. Every mutation is recorded in an audit log with rollback data.
```bash
curl -s -X POST "$GANGLION_URL/v1/rollback/last" | jq
curl -s -X POST "$GANGLION_URL/v1/rollback/0" | jq # undo ALL mutations
```
### Multi-Bot Workflows
Multiple OpenClaw sessions share a knowledge pool via `--bot-id`. Each bot's discoveries flow into the shared pool. Cooperation emerges from shared knowledge, not explicit coordination.
```bash
# Two local sessions
ganglion run ./my-subnet --bot-id alpha
ganglion run ./my-subnet --bot-id beta
# Two remote servers
ganglion serve ./my-subnet --bot-id alpha --port 8899
ganglion serve ./my-subnet --bot-id beta --port 8900
```
### MCP Integration
Ganglion is a bidirectional MCP system: it can **consume** external MCP servers (client mode) and **expose** its own tools as an MCP server (server mode).
#### MCP Client Mode — Consuming External Tools
Connect to external MCP servers to add tools to the agent's repertoire. Tools from MCP servers appear as regular Ganglion tools with a configurable prefix.
```bash
# Static: add to config.py
# from ganglion.mcp.config import MCPClientConfig
# mcp_clients = [MCPClientConfig(name="weather", transport="stdio", command=["python", "-m", "weather_server"])]
# Dynamic: add at runtime via API
curl -s -X POST "$GANGLION_URL/v1/mcp/servers" -H "Content-Type: application/json" \
-d '{"name":"weather","transport":"stdio","command":["python","-m","weather_server"]}' | jq .data
# Check connected MCP servers
curl -s "$GANGLION_URL/v1/mcp" | jq .data
# Disconnect / Reconnect
curl -s -X DELETE "$GANGLION_URL/v1/mcp/servers/weather" | jq .data
curl -s -X POST "$GANGLION_URL/v1/mcp/servers/weather/reconnect" | jq .data
```
MCPClientConfig options: `name`, `transport` (stdio|sse), `command` (for stdio), `url` (for sse), `env`, `tool_prefix`, `category`, `timeout` (default 30s).
#### MCP Server Mode — Exposing Ganglion Tools
Run Ganglion as an MCP server so external agents (Claude Code, Claude Desktop, OpenClaw) can call Ganglion tools directly.
```bash
# stdio transport (Claude Desktop / Claude Code)
ganglion mcp-serve ./my-subnet --transport stdio
# SSE transport (HTTP-based clients)
ganglion mcp-serve ./my-subnet --transport sse --mcp-port 8900
# Multi-role with access control
ganglion mcp-serve ./my-subnet --roles ./roles.json
```
**Claude Code integration:** This repo includes `.mcp.json` which auto-configures Claude Code to connect to Ganglion's MCP server via stdio. Claude Code will see all Ganglion tools natively in its tool palette.
#### Exposed MCP Tools (31 total)
**Observation (11)** — read-only state queries:
`ganglion_get_status`, `ganglion_get_pipeline`, `ganglion_get_tools`, `ganglion_get_agents`, `ganglion_get_runs`, `ganglion_get_metrics`, `ganglion_get_leaderboard`, `ganglion_get_knowledge`, `ganglion_get_source`, `ganglion_get_components`, `ganglion_get_mcp_status`
**Mutation (6)** — write operations:
`ganglion_write_tool`, `ganglion_write_agent`, `ganglion_write_component`, `ganglion_write_prompt`, `ganglion_patch_pipeline`, `ganglion_swap_policy`
**Execution (3)** — run operations:
`ganglion_run_pipeline`, `ganglion_run_stage`, `ganglion_run_experiment`
**Admin (5)** — rollback and MCP management:
`ganglion_rollback_last`, `ganglion_rollback_to`, `ganglion_connect_mcp`, `ganglion_disconnect_mcp`, `ganglion_reconnect_mcp`
**Compute (6)** — infrastructure tools:
`compute_status`, `compute_jobs`, `compute_job_detail`, `compute_routes`, `write_dockerfile`, `build_image`
#### Multi-Role MCP Serving
Run one process with multiple MCP server instances, each with different access levels and auth tokens.
```json
// roles.json
[
{"name": "admin", "categories": null, "token": "admin-xyz", "port": 8901},
{"name": "worker", "categories": ["observation","execution"], "token": "worker-abc", "port": 8902},
{"name": "observer", "categories": ["observation"], "token": "observer-def", "port": 8903}
]
```
Roles filter tools by category. `null` categories = access to all tools. Each role gets a separate port and bearer token for SSE transport. At most one role can use stdio transport.
#### Per-Bot Usage Tracking
When running with `--roles`, a shared `UsageTracker` records per-bot tool calls (tool name, success/failure, timestamp, duration) to `.ganglion/usage.db`. Query via `/usage` endpoint on any SSE role.
#### Connecting Other Agents to Ganglion's MCP Server
OpenClaw and other LLM agents can start Ganglion's MCP server for themselves or for other agents to connect to. Use SSE transport for generic MCP clients that don't support stdio.
```bash
# Start Ganglion MCP server with SSE transport (any MCP client can connect)
ganglion mcp-serve ./my-subnet --transport sse --mcp-port 8900
# SSE endpoints exposed:
# GET http://127.0.0.1:8900/sse — SSE stream (tool list + results)
# POST http://127.0.0.1:8900/messages — send tool calls
# GET http://127.0.0.1:8900/usage — usage stats (if tracking enabled)
# GET http://127.0.0.1:8900/usage?bot_id=alpha — per-bot stats
# With auth (multi-role), include bearer token:
# curl -H "Authorization: Bearer worker-abc" http://127.0.0.1:8902/sse
```
**For OpenClaw:** OpenClaw reads skills and invokes commands via bash/curl — it doesn't connect to MCP natively. To give OpenClaw access to Ganglion tools, use the CLI (local mode) or HTTP bridge (remote mode) documented above. OpenClaw can also *start* an MCP server so that other MCP-capable agents (Claude Desktop, Cursor, etc.) can connect:
```bash
# OpenClaw starts the MCP server for other agents
ganglion mcp-serve ./my-subnet --transport sse --mcp-port 8900
```
**For generic MCP clients (Cursor, Windsurf, custom):** Point your client's MCP config at the SSE endpoint:
- Server URL: `http://127.0.0.1:8900/sse`
- Messages endpoint: `http://127.0.0.1:8900/messages`
- Transport: SSE
- Auth: Bearer token (if using roles)
## Common Workflows
See `{baseDir}/examples/common-workflows.md` for full step-by-step guides.
1. **First run**: `ganglion init` → edit `config.py` → `ganglion run`
2. **Iterative mining**: check status → review knowledge → run pipeline → check metrics → repeat
3. **Dynamic mutation**: observe tools/agents → register new tool via API → patch pipeline → run
4. **Multi-bot setup**: start multiple servers with different `--bot-id` values on the same project
5. **MCP integration**: connect external tool servers → tools appear in registry → agents can use them
## When Things Go Wrong
| Symptom | Likely Cause | Fix |
|---------|-------------|-----|
| `FileNotFoundError: No config.py` | Wrong project path | Verify path contains `config.py` |
| `LLM_PROVIDER_API_KEY` errors | Missing or invalid API key | `export LLM_PROVIDER_API_KEY=sk-...` |
| `ConcurrentMutationError` | Mutating during a pipeline run | Wait for the run to finish |
| `PipelineValidationError` | Invalid pipeline DAG (cycles, missing deps) | Check `ganglion pipeline` output |
| Agent stuck / max turns reached | Agent cannot make progress | Review knowledge, swap retry policy, adjust prompts |
Full troubleshooting: `{baseDir}/references/troubleshooting.md`
## Retry Policies
Four built-in policies control how stages retry on failure:
- **NoRetry** — single attempt
- **FixedRetry** — retry N times (default: 3)
- **EscalatingRetry** — increase temperature per attempt, optional stall detection
- **ModelEscalationRetry** — climb a model cost ladder (cheap → expensive)
Three presets: `SN50_PRESET` (escalating + stall detection), `SIMPLE_PRESET` (fixed), `AGGRESSIVE_PRESET` (model escalation).
## Additional Resources
- Full CLI & API reference: `{baseDir}/references/commands.md`
- Configuration guide: `{baseDir}/references/configuration.md`
- Operational procedures: `{baseDir}/references/operations.md`
- Troubleshooting: `{baseDir}/references/troubleshooting.md`
- Workflow examples: `{baseDir}/examples/common-workflows.md`
- Sample API requests: `{baseDir}/examples/sample-requests.md`
- Health check script: `{baseDir}/scripts/healthcheck.sh`
don't have the plugin yet? install it then click "run inline in claude" again.
ganglion is a domain-specific execution engine for bittensor subnet mining. it orchestrates autonomous mining agents searching for optimal model configurations via a pipeline framework. use it to scaffold projects, run mining pipelines (full or staged), query cross-run knowledge, mutate components at runtime, and coordinate multi-bot mining via shared knowledge. the engine exposes three interfaces: cli (local mode), http bridge api (remote mode), and mcp server (for external agents). ganglion is search infrastructure. it handles orchestration, dependency resolution, retry logic, and knowledge injection. you define what good looks like in config.py.
required binaries:
pip install ganglion)required environment variables:
LLM_PROVIDER_API_KEY: api key for the llm runtime (e.g., openai sk-xxx, anthropic key, etc.). required for pipeline execution.optional environment variables for mode detection:
GANGLION_PROJECT: if set, forces local mode. path to a ganglion project directory.GANGLION_URL: if set, forces remote mode. http endpoint of a running ganglion http bridge (e.g., http://127.0.0.1:8899).project directory structure: the target project must contain:
config.py: defines subnet_config (SubnetConfig) and pipeline (PipelineDef). see references/configuration.md for schema.tools/: directory of tool definitions (optional but recommended).agents/: directory of agent definitions (optional but recommended).skill/: directory of skill definitions (optional).external connections (for mcp integration):
/v1/mcp/servers endpoint.api authentication (multi-role mcp serving only):
Authorization: Bearer <token> header for sse transport. defined in roles.json if using ganglion mcp-serve --roles ./roles.json.input: environment state (GANGLION_PROJECT, GANGLION_URL, current working directory)
action: determine execution mode.
if [ -n "$GANGLION_PROJECT" ] || [ -z "$GANGLION_URL" ]; then
MODE="local"
else
MODE="remote"
fi
output: MODE is either "local" or "remote". all subsequent commands depend on this choice.
input: target directory path, subnet identifier (e.g., sn9), netuid (e.g., 9)
action:
ganglion init ./my-subnet --subnet sn9 --netuid 9
this creates:
config.py with placeholder subnet_config and pipeline definitionstools/ directory (empty)agents/ directory (empty)skill/ directory (empty)output: new project directory tree ready for editing.
input: config.py file in project root
action: define subnet_config (SubnetConfig instance) and pipeline (PipelineDef instance). include any static mcp client configs here if needed (MCPClientConfig objects).
output: valid config.py that passes validation. test with ganglion pipeline ./my-subnet to catch syntax/dag errors early.
input: project directory, query parameters (optional)
actions (pick one per query):
# pipeline structure
ganglion pipeline ./my-subnet
# registered tools
ganglion tools ./my-subnet
# registered agents
ganglion agents ./my-subnet
# cross-run knowledge (filter by capability and bot_id)
ganglion knowledge ./my-subnet --bot-id alpha --capability training --max-entries 10
# overall status
ganglion status ./my-subnet
# metrics and run history
ganglion metrics ./my-subnet
output: json or table (depending on command) showing current framework state.
input: GANGLION_URL env var, http client (curl), query parameters (optional)
actions (pick one per query):
# pipeline structure
curl -s "$GANGLION_URL/v1/pipeline" | jq .data
# registered tools
curl -s "$GANGLION_URL/v1/tools" | jq .data
# registered agents
curl -s "$GANGLION_URL/v1/agents" | jq .data
# cross-run knowledge
curl -s "$GANGLION_URL/v1/knowledge?bot_id=alpha&capability=training&max_entries=10" | jq .data
# overall status
curl -s "$GANGLION_URL/v1/status" | jq .data
# metrics and run history
curl -s "$GANGLION_URL/v1/metrics" | jq .data
# check health (no data envelope)
curl -s "$GANGLION_URL/healthz" | jq .
output: json payload (extract with jq .data for non-health endpoints).
input: project directory path
action:
export GANGLION_PROJECT=./my-subnet
ganglion status $GANGLION_PROJECT
subsequent commands can now omit the project path and reference $GANGLION_PROJECT directly.
output: env var set; ready for local commands.
input: project directory path, bot identifier (string), port (int, default 8899)
action:
ganglion serve ./my-subnet --bot-id alpha --port 8899
export GANGLION_URL=http://127.0.0.1:8899
this starts an http server. the --bot-id value is used to namespace knowledge and usage metrics in multi-bot setups.
output: http server listening on specified port. GANGLION_URL env var set. ready for remote api calls.
input: project directory, optional stage name, optional runtime overrides (json)
actions (pick one):
# run full pipeline (all stages in dependency order)
ganglion run ./my-subnet
# run single stage
ganglion run ./my-subnet --stage plan
# run with runtime config overrides
ganglion run ./my-subnet --overrides '{"target_metric":"accuracy","max_iterations":20}'
the orchestrator:
output: run completes with exit code 0 (success) or non-zero (failure). check ganglion status or ganglion metrics for detailed results.
input: GANGLION_URL, http client (curl), optional json payload with overrides
actions (pick one):
# run full pipeline
curl -s -X POST "$GANGLION_URL/v1/run/pipeline" \
-H "Content-Type: application/json" \
-d '{}' | jq .data
# run single stage
curl -s -X POST "$GANGLION_URL/v1/run/stage/plan" \
-H "Content-Type: application/json" \
-d '{}' | jq .data
# run with overrides
curl -s -X POST "$GANGLION_URL/v1/run/pipeline" \
-H "Content-Type: application/json" \
-d '{"target_metric":"accuracy","max_iterations":20}' | jq .data
output: json payload containing run id, status, and initial results. long-running executions return immediately with a run id; poll /v1/runs/<run_id> to monitor progress.
input: project directory
action: editing config.py directly, then reloading. local mode does not support dynamic mutations without process restart. for iterative mutation workflows, switch to remote mode.
output: changes take effect on next ganglion run.
input: GANGLION_URL, http client (curl), mutation payload (json)
mutations available:
register a new tool:
curl -s -X POST "$GANGLION_URL/v1/tools" \
-H "Content-Type: application/json" \
-d '{
"name": "my_tool",
"code": "<python code>",
"category": "training",
"description": "optional description"
}' | jq .data
register a new agent:
curl -s -X POST "$GANGLION_URL/v1/agents" \
-H "Content-Type: application/json" \
-d '{
"name": "MyAgent",
"model": "gpt-4",
"system_prompt": "you are a mining agent"
}' | jq .data
patch pipeline (add, remove, or update stages):
curl -s -X PATCH "$GANGLION_URL/v1/pipeline" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{"op": "add_stage", "stage": {"name": "validate", "agent": "Validator", "depends_on": ["train"]}},
{"op": "update_stage", "name": "plan", "updates": {"agent": "NewAgent"}},
{"op": "remove_stage", "name": "old_stage"}
]
}' | jq .data
update an agent prompt:
curl -s -X POST "$GANGLION_URL/v1/prompts" \
-H "Content-Type: application/json" \
-d '{
"agent": "Planner",
"system_prompt": "new prompt text"
}' | jq .data
swap a retry policy for a stage:
curl -s -X POST "$GANGLION_URL/v1/policies" \
-H "Content-Type: application/json" \
-d '{
"stage": "plan",
"policy": "SN50_PRESET"
}' | jq .data
all mutations are validated, audited, and reversible.
output: json payload with updated framework state. check audit log via /v1/audit.
input: project directory or GANGLION_URL, capability filter (string, optional), bot_id filter (string, optional)
action (local):
ganglion knowledge ./my-subnet --capability training --bot-id alpha --max-entries 20
action (remote):
curl -s "$GANGLION_URL/v1/knowledge?capability=training&bot_id=alpha&max_entries=20" | jq .data
the knowledge store holds:
--bot-id maintains its own knowledge pool in multi-bot setupsknowledge is automatically injected into agent prompts during pipeline execution. query it to understand what the system has learned.
output: array of knowledge entries with timestamps, bot_id, capability, and content.
input: GANGLION_URL, rollback target (latest or audit log index)
actions:
# undo the last mutation
curl -s -X POST "$GANGLION_URL/v1/rollback/last" | jq .data
# undo a specific mutation by audit log index
curl -s -X POST "$GANGLION_URL/v1/rollback/0" | jq .data
# undo all mutations (rollback to index 0)
curl -s -X POST "$GANGLION_URL/v1/rollback/0" | jq .data
every mutation records its reverse operation in the audit log. rollback is idempotent.
output: framework state reverted to target point. audit log updated with rollback entry.
external mcp servers expose tools (e.g., weather, database, compute) to ganglion agents.
static configuration (config.py):
from ganglion.mcp.config import MCPClientConfig
mcp_clients = [
MCPClientConfig(
name="weather",
transport="stdio",
command=["python", "-m", "weather_server"],
category="external_tools",
timeout=30
),
MCPClientConfig(
name="compute_api",
transport="sse",
url="http://compute-server:9000/sse",
tool_prefix="compute_",
category="infrastructure"
)
]
dynamic registration (remote mode):
curl -s -X POST "$GANGLION_URL/v1/mcp/servers" \
-H "Content-Type: application/json" \
-d '{
"name": "weather",
"transport": "stdio",
"command": ["python", "-m", "weather_server"],
"category": "external_tools",
"timeout": 30
}' | jq .data
check connected servers:
curl -s "$GANGLION_URL/v1/mcp" | jq .data
reconnect a server:
curl -s -X POST "$GANGLION_URL/v1/mcp/servers/weather/reconnect" | jq .data
disconnect a server:
curl -s -X DELETE "$GANGLION_URL/v1/mcp/servers/weather" | jq .data
tools from mcp servers appear in the tool registry and are available to agents with no additional configuration.
output: tools from external mcp servers registered and ready for use. ganglion tools / /v1/tools includes them.
ganglion itself can run as an mcp server so external agents (claude desktop, cursor, openai code interpreter, openclaw) can invoke ganglion tools.
start ganglion mcp server (stdio transport):
ganglion mcp-serve ./my-subnet --transport stdio
use this with claude desktop or claude code. ganglion tools appear in the claude tool palette.
start ganglion mcp server (sse transport):
ganglion mcp-serve ./my-subnet --transport sse --mcp-port 8900
use this with http-based mcp clients (generic clients, cursor, windsurf). endpoints:
GET http://127.0.0.1:8900/sse , sse stream (tool list + results)POST http://127.0.0.1:8900/messages , send tool callsmulti-role mcp serving (access control):
ganglion mcp-serve ./my-subnet --roles ./roles.json
roles.json defines separate mcp server instances with different tool access and auth:
[
{"name": "admin", "categories": null, "token": "admin-xyz", "port": 8901},
{"name": "worker", "categories": ["observation","execution"], "token": "worker-abc", "port": 8902},
{"name": "observer", "categories": ["observation"], "token": "observer-def", "port": 8903}
]
null categories = all tools. each role gets a separate port (sse) and bearer token. at most one role can use stdio transport.
connect an external mcp client to ganglion's sse server:
set up client config (cursor, windsurf, custom):
http://127.0.0.1:8900/ssehttp://127.0.0.1:8900/messagesAuthorization: Bearer worker-abcusage tracking (multi-role only):
each call to a ganglion tool is logged to .ganglion/usage.db per bot_id (tool name, success/failure, timestamp, duration). query via:
curl -s "$GANGLION_URL/v1/usage" | jq .data
curl -s "$GANGLION_URL/v1/usage?bot_id=alpha" | jq .data
output: ganglion tools exposed as mcp server. external agents can discover and invoke them.
multiple openclaw or agent sessions share a knowledge pool and optionally contribute to shared metrics.
local mode (shared project directory):
# session 1
export GANGLION_PROJECT=./my-subnet
ganglion run ./my-subnet --bot-id alpha
# session 2 (different terminal)
export GANGLION_PROJECT=./my-subnet
ganglion run ./my-subnet --bot-id beta
discoveries by alpha are visible to beta via ganglion knowledge --bot-id beta --capability training.
remote mode (shared project, different ports):
# terminal 1
ganglion serve ./my-subnet --bot-id alpha --port 8899
export GANGLION_URL=http://127.0.0.1:8899
# terminal 2
ganglion serve ./my-subnet --bot-id beta --port 8900
export GANGLION_URL=http://127.0.0.1:8900
each server has its own http listener but shares the underlying project directory and knowledge pool.
output: multiple bots mining in parallel. cross-bot knowledge flows through the shared knowledge store. cooperation emerges from shared memory, not explicit coordination.
mode selection (step 1):
GANGLION_PROJECT env var is set, use local mode (cli commands).GANGLION_URL is set, use remote mode (http api).mcp client config (step 10a):
/v1/mcp/servers endpoints to manage them dynamically.url instead of command.command instead of url.project configuration validation (step 3):
ganglion pipeline ./my-subnet reports PipelineValidationError, the dag contains cycles or missing dependencies. fix config.py and re-run validation.ganglion run fails with FileNotFoundError: No config.py, verify the project path and that config.py exists in the root.runtime mutations during execution (step 7b):
ConcurrentMutationError. wait for the run to complete, then retry the mutation.knowledge injection (step 8):
--bot-id is not specified in local mode or bot_id query param is not passed in remote mode, knowledge is not filtered by bot. all knowledge is visible.--capability or capability param is not specified, knowledge is not filtered by capability. all knowledge is visible.external agent access (step 10b):
--transport stdio. ganglion tools appear natively in claude's tool palette.--transport sse and point the client at http://<host>:<port>/sse.Authorization: Bearer <token> header.multi-bot coordination (step 11):
--bot-id value to maintain separate knowledge namespaces and avoid collisions.local mode execution (steps 4a, 5a, 6a):
PipelineValidationError, FileNotFoundError)..ganglion/runs/ directory in the project..ganglion/knowledge.db in the project.remote mode api responses (steps 4b, 5b, 6b, 7b, 8, 9, 10a, 10b):
{"data": <payload>} envelope on success. extract with jq .data.{"detail": {"error": {"code": "ERROR_CODE", "message": "description"}}}./healthz, /readyz) return raw json without envelope.pipeline execution (local and remote):
mutations (step 7b):
mcp server startup (step 10b):
knowledge store (step 8):
.ganglion/knowledge.db persists cross-run patterns and antipatterns.timestamp (iso8601), bot_id (string), capability (string), pattern_type ("pattern" or "antipattern"), content (text), source_run_id (string).audit log (step 7b, 9):
.ganglion/audit.log records every mutation with timestamp, operation type, user/bot, payload, and rollback data.usage tracking (step 10b, multi-role only):
.ganglion/usage.db records tool calls per bot_id: tool name, success/failure, timestamp, duration, bot_id.successful project init (step 2):
config.py, tools/, agents/, skill/ subdirectories.ganglion pipeline ./my-subnet runs without errors and outputs the pipeline dag.successful local mode startup (step 5a):
echo $GANGLION_PROJECT shows the project path.ganglion status $GANGLION_PROJECT returns framework state (no errors).successful remote mode startup (step 5b):
curl -s "$GANGLION_URL/healthz").echo $GANGLION_URL shows the http endpoint.curl -s "$GANGLION_URL/v1/status" | jq .data returns framework state (no errors).successful pipeline run (steps 6a, 6b):
ganglion metrics ./my-subnet shows updated run history, or /v1/metrics returns new run entry..ganglion/runs/<run_id>/ directory contains execution logs and results (local mode).successful mutation (step 7b):
/v1/audit shows new mutation entry.ganglion tools or /v1/tools includes the new tool./v1/rollback/last can undo the mutation.successful knowledge query (step 8):
ganglion knowledge ./my-subnet or curl -s "$GANGLION_URL/v1/knowledge" returns non-empty array of entries.bot_id, capability, pattern_type, and content fields.successful mcp integration (steps 10a, 10b):
curl -s "$GANGLION_URL/v1/mcp" lists connected servers (no errors).http://127.0.0.1:<port>/sse and receives tool list.**successful multi-bot setup (