Transport-level routing for MCP/ACP protocols
Registry Launcher
Universal worker for spawning agents from the ACP Registry on demand.
Overview
The Registry Launcher provides dynamic agent routing capabilities by integrating with the ACP Registry. It automatically discovers available agents, manages their lifecycle as child processes, and routes messages based on the requested agentId. This enables a single stdio Bus deployment to support multiple agents without manual configuration.
Location: workers-registry/acp-worker/src/registry-launcher/
Features
- Automatic Agent Discovery: Fetches and caches the latest agent list from the ACP Registry
- Dynamic Process Management: Spawns and manages agent processes on-demand
- API Key Injection: Securely injects API keys from configuration into agent environments
- Session Affinity Routing: Ensures messages with the same
sessionIdroute to the same agent instance - Multi-Agent Support: Handle requests for multiple different agents simultaneously
- Graceful Shutdown: Cleanly terminates agent processes on shutdown signals
Available Agents
The Registry Launcher can route to any agent in the ACP Registry, including:
claude-acp- Claude Agentgoose- Goosecline- Clinegithub-copilot- GitHub Copilot- And many more from the ACP Registry
The full list of available agents is dynamically fetched from the registry at runtime.
Configuration
Basic Configuration
Create a configuration file for stdio Bus kernel:
{"pools": [{"id": "registry-launcher","command": "npx","args": ["@stdiobus/workers-registry","registry-launcher"],"instances": 1}]}
Configuration with API Keys
For agents that require API keys (like Claude), provide a separate API keys file:
{"pools": [{"id": "registry-launcher","command": "npx","args": ["@stdiobus/workers-registry","registry-launcher","./api-keys.json"],"instances": 1}]}
API Keys File Format (api-keys.json):
{"agents": {"claude-acp": {"apiKey": "sk-ant-...","env": {}},"goose": {"apiKey": "sk-...","env": {}},"github-copilot": {"apiKey": "ghp_...","env": {}}},"version": "1.0.0"}
The Registry Launcher will use these API keys and environment variables for spawned agent processes.
Production Configuration
For production deployments with resource limits:
{"pools": [{"id": "registry-launcher","command": "npx","args": ["@stdiobus/workers-registry","registry-launcher","./api-keys.json"],"instances": 2}],"limits": {"max_input_buffer": 2097152,"max_output_queue": 8388608,"max_restarts": 10,"restart_window_sec": 120,"backpressure_timeout_sec": 90}}
Configuration Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the worker pool |
command | string | Path to Node.js executable |
args | string[] | Arguments: launcher path, "registry-launcher", optional API keys file |
instances | number | Number of launcher instances (≥1) |
ACP Registry Integration
Registry Discovery
The Registry Launcher automatically fetches the agent registry from:
https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json
The registry contains metadata for each agent including:
- Agent ID and display name
- Installation command
- Required environment variables
- Supported capabilities
Agent Metadata
Each agent in the registry includes:
{"id": "claude-acp","name": "Claude Agent","command": "npx","args": ["@agentclientprotocol/claude-acp"],"env": {"ANTHROPIC_API_KEY": "required"}}
The Registry Launcher uses this metadata to spawn and configure agent processes.
Caching
The registry is cached locally to minimize network requests. The cache is refreshed:
- On startup
- When an unknown agent is requested
- After cache expiration (configurable)
Dynamic Agent Discovery and Management
Agent Lifecycle
The Registry Launcher manages agent processes through the following lifecycle:
- Client sends request with
agentId - Launcher checks if agent process is already running
- If not running, launcher fetches agent metadata from registry
- Launcher spawns new agent process with proper configuration
- API keys are injected into agent environment
- Request is routed to the agent process
- Agent response is returned to client
Process Management
The Registry Launcher manages agent processes:
- On-Demand Spawning: Agents are spawned only when first requested
- Process Pooling: Multiple instances of the same agent can run concurrently
- Health Monitoring: Monitors agent process health and restarts on failure
- Resource Cleanup: Terminates idle agents after timeout (configurable)
- Graceful Shutdown: Sends SIGTERM to all agents on launcher shutdown
Session Affinity
Messages with the same sessionId are routed to the same agent instance:
{"jsonrpc": "2.0","id": "1","method": "initialize","params": {"agentId": "claude-acp","clientInfo": {"name": "my-client","version": "1.0.0"}},"sessionId": "sess-abc123"}
All subsequent messages with sessionId: "sess-abc123" will route to the same Claude agent instance.
Agent Routing
Specifying the Agent
Include the agentId in the request parameters:
{"jsonrpc": "2.0","id": "1","method": "initialize","params": {"agentId": "claude-acp","clientInfo": {"name": "test-client","version": "1.0.0"}}}
Routing Flow
- Client sends request with
agentIdparameter - Registry Launcher receives request via stdio Bus
- Launcher checks if agent process exists for this
agentId - If not, launcher spawns new agent process using registry metadata
- Request is forwarded to agent process via stdin
- Agent response is returned to client via stdio Bus
Multi-Agent Scenarios
The Registry Launcher can handle multiple agents simultaneously:
# Client 1 requests Claude{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"agentId":"claude-acp"}}# Client 2 requests Goose{"jsonrpc":"2.0","id":"2","method":"initialize","params":{"agentId":"goose"}}# Both agents run concurrently, managed by the same launcher
Protocol Messages
Initialize with Agent ID
{"jsonrpc": "2.0","id": "1","method": "initialize","params": {"agentId": "claude-acp","clientInfo": {"name": "my-client","version": "1.0.0"}}}
Initialize Response
{"jsonrpc": "2.0","id": "1","result": {"serverInfo": {"name": "claude-acp","version": "1.0.0"},"capabilities": {"prompts": true,"tools": true}}}
Prompt with Session Affinity
{"jsonrpc": "2.0","id": "2","method": "prompt","sessionId": "sess-abc123","params": {"agentId": "claude-acp","prompt": "What is the weather today?","context": {}}}
Testing
Test Registry Launcher
Start stdio Bus with the Registry Launcher:
docker run \--name stdiobus-registry-test \-p 9000:9000 \-v $(pwd):/stdiobus:ro \-v $(pwd)/config.json:/config.json:ro \-v $(pwd)/api-keys.json:/api-keys.json:ro \stdiobus/stdiobus:latest \--config /config.json --tcp 0.0.0.0:9000
Send Test Message
echo '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"agentId":"claude-acp","clientInfo":{"name":"test"}}}' | nc localhost 9000
Expected Response
The Registry Launcher will spawn the Claude agent and return its initialization response:
{"jsonrpc":"2.0","id":"1","result":{"serverInfo":{"name":"claude-acp","version":"1.0.0"},"capabilities":{"prompts":true,"tools":true}}}
Cleanup
docker stop stdiobus-registry-test && docker rm stdiobus-registry-test
Programmatic Usage
Module Import
// Import registry launcherimport { registryLauncher } from '@stdiobus/workers-registry/workers';
TypeScript Types
import type { RegistryAgent } from '@stdiobus/workers-registry/workers/registry-launcher';// Use types for type-safe developmentconst agent: RegistryAgent = /* ... */;
Troubleshooting
Agent Not Found
If the Registry Launcher cannot find an agent:
{"jsonrpc":"2.0","id":"1","error":{"code":-32602,"message":"Agent not found: unknown-agent"}}
Solution: Verify the agent ID exists in the ACP Registry.
API Key Missing
If an agent requires an API key that is not provided:
{"jsonrpc":"2.0","id":"1","error":{"code":-32603,"message":"Missing required API key: ANTHROPIC_API_KEY"}}
Solution: Add the required API key to your api-keys.json file.
Registry Fetch Failure
If the Registry Launcher cannot fetch the registry:
# Check network connectivitycurl https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json
Solution: Ensure the launcher has internet access to fetch the registry.
Next Steps
- ACP Worker - Direct ACP protocol implementation
- MCP-to-ACP Proxy - IDE integration