Manages a pool of pre-warmed OpenClaw agent instances on Railway. Instances are created ahead of time so that when a user claims one, it's ready in seconds instead of minutes.
┌──────────────┐
│ Pool Manager │
│ (this repo) │
└──┬───┬───┬───┘
creates │ │ │ polls /convos/status
┌───────────────┘ │ └───────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ OpenClaw │ │ OpenClaw │ │ OpenClaw │
│ instance 1 │ │ instance 2 │ ... │ instance N │
│ (Railway) │ │ (Railway) │ │ (Railway) │
└──────────────┘ └──────────────┘ └──────────────┘
- The pool manager creates Railway services from the
agent/directory in this repo (Dockerfile + entrypoint that builds and runs OpenClaw) - It polls each instance's
/convos/statusendpoint until it reportsready - Ready instances are marked idle and available for claiming
- When claimed via
POST /api/pool/claim, the manager calls/convos/conversation(or/convos/join) on the instance with the provided instructions, then backfills the pool - Claimed instances are renamed in Railway so they're identifiable in the dashboard
This is a 2-repo system:
| Repo | Description |
|---|---|
this repo (convos-agent-pool-manager) |
Pool manager + agent Dockerfile/entrypoint in agent/ |
| openclaw | The AI gateway that runs inside each agent instance |
The agent/Dockerfile clones OpenClaw from source, builds it, and the agent/entrypoint.sh configures and starts the gateway.
Requires Node.js 22+ and a Neon Postgres database.
git clone https://github.com/xmtplabs/convos-agent-pool-manager.git
cd convos-agent-pool-manager
npm installCopy .env.example to .env and fill in the values:
cp .env.example .env| Variable | Description |
|---|---|
PORT |
Server port (default 3001) |
POOL_API_KEY |
Shared secret for API auth (Bearer token) |
POOL_ENVIRONMENT |
"staging", "dev", or "production" |
RAILWAY_API_TOKEN |
Railway project-scoped API token |
RAILWAY_PROJECT_ID |
Railway project ID |
RAILWAY_ENVIRONMENT_ID |
Railway environment ID |
RAILWAY_SOURCE_REPO |
GitHub repo to deploy (e.g. xmtplabs/convos-agent-pool-manager) |
RAILWAY_SOURCE_BRANCH |
Branch to deploy from (e.g. staging, main) |
RAILWAY_SOURCE_ROOT_DIR |
Subdirectory containing the Dockerfile (agent) |
OPENCLAW_GIT_REF |
OpenClaw git ref to build from (default: staging or main) |
INSTANCE_ANTHROPIC_API_KEY |
Anthropic API key injected into each instance |
INSTANCE_XMTP_ENV |
XMTP environment (dev or production) |
POOL_MIN_IDLE |
Minimum idle instances to maintain (default 3) |
POOL_MAX_TOTAL |
Maximum total instances (default 10) |
DATABASE_URL |
Neon Postgres connection string |
Run the database migration:
npm run db:migrateStart the server:
npm startAll endpoints (except GET / and GET /healthz) require a Authorization: Bearer <POOL_API_KEY> header.
Serves a web dashboard for managing the pool and claiming instances.
Health check. Returns {"ok": true}.
Returns pool counts and all instances.
{
"counts": { "provisioning": 2, "idle": 3, "claimed": 1 },
"instances": [...]
}Returns pool counts only (no auth required).
{ "provisioning": 2, "idle": 3, "claimed": 1 }Claims an idle instance and provisions it. Creates a new conversation or joins an existing one.
Create mode (default):
{
"agentName": "tokyo-trip-planner",
"instructions": "You are a helpful trip planner for Tokyo."
}Join mode (join existing conversation via invite URL):
{
"agentName": "tokyo-trip-planner",
"instructions": "You are a helpful trip planner for Tokyo.",
"joinUrl": "https://dev.convos.org/v2?i=..."
}Returns:
{
"inviteUrl": "https://dev.convos.org/v2?i=...",
"conversationId": "abc123",
"instanceId": "rnM8UBQ_fZCz",
"joined": false
}Manually triggers a poll + replenish cycle. Pass {"count": N} to create N instances directly.
Removes idle instances from the pool. Pass {"count": N} to drain up to N idle instances.
Verifies DB state against Railway and removes orphaned entries.
provisioning → idle → claimed
(building) (ready) (in use)
The background tick runs every 30 seconds:
- Polls all
provisioninginstances — if/convos/statusreturnsready, marks themidle - Checks if idle + provisioning count is below
POOL_MIN_IDLE— if so, creates new instances up toPOOL_MAX_TOTAL - Periodically reconciles DB against Railway to clean up orphaned entries
Three Railway environments share the same project:
| Environment | Pool Manager URL | XMTP Network | Source Branch |
|---|---|---|---|
| dev | convos-agent-pool-manager-dev.up.railway.app |
dev | (your branch) |
| staging | convos-agents-dev.up.railway.app |
dev | staging |
| production | convos-agents.up.railway.app |
production | main |