Skip to main content

OpenClaw Relay Plugin

The OpenClaw Relay plugin is the easiest way to connect AI agents to Relay. It manages WebSocket connections, session creation, and message routing automatically.

What the Plugin Does

The plugin:

  • Maintains persistent WebSocket connections to Relay (one per agent)
  • Receives events from apps
  • Creates/resumes OpenClaw sessions with the correct session key
  • Injects payloads as user messages
  • Streams tokens and final replies back to Relay
  • Handles reconnection with exponential backoff
  • Manages per-agent TTL (time-to-live) for sessions

Think of it as a bridge between Relay and OpenClaw — one connection per agent.

Installation

The plugin is available on npm:

npm install openclaw-relay-plugin

Or with yarn:

yarn add openclaw-relay-plugin

Configuration

Create a openclaw.plugin.json file:

{
"relay": {
"url": "wss://api.relay.ckgworks.com/v1/ws/agent",
"reconnect": {
"enabled": true,
"maxRetries": 5,
"baseDelayMs": 1000,
"maxDelayMs": 60000
}
},
"agents": [
{
"agent_id": "athena",
"token": "rla_athena_k9x2p7m2jq8r5v3n1b9...",
"ttl_days": 14,
"context": {}
},
{
"agent_id": "klyve",
"token": "rla_klyve_k9x2p7m2jq8r5v3n1b9...",
"ttl_days": 30,
"context": {}
}
]
}

Config Schema

FieldTypeRequiredNotes
relay.urlstringYesRelay WebSocket endpoint
relay.reconnect.enabledbooleanNoAuto-reconnect on disconnect (default: true)
relay.reconnect.maxRetriesnumberNoMax reconnection attempts (default: 5)
relay.reconnect.baseDelayMsnumberNoInitial backoff delay in ms (default: 1000)
relay.reconnect.maxDelayMsnumberNoMax backoff delay in ms (default: 60000)
agents[].agent_idstringYesAgent identifier (matches Relay registration)
agents[].tokenstringYesAgent token from Relay dashboard (rla_...)
agents[].ttl_daysnumberNoSession TTL in days (default: 14)
agents[].contextobjectNoCustom context passed to OpenClaw

Security Note

Never commit the config file with real tokens to version control. Use environment variables:

{
"agents": [
{
"agent_id": "athena",
"token": "${RELAY_ATHENA_TOKEN}",
"ttl_days": 14
}
]
}

Then set the env var:

export RELAY_ATHENA_TOKEN="rla_athena_k9x2p..."

The plugin will interpolate ${VAR} from environment.

Usage

TypeScript/Node.js

import { RelayPlugin } from 'openclaw-relay-plugin';
import OpenClaw from 'openclaw';

const plugin = new RelayPlugin({
configPath: './openclaw.plugin.json'
});

const openClaw = new OpenClaw({
plugins: [plugin]
});

openClaw.on('connected', () => {
console.log('OpenClaw connected to Relay');
});

openClaw.on('error', (error) => {
console.error('Error:', error);
});

// Plugin handles everything automatically

With Environment Config

const plugin = new RelayPlugin({
config: {
relay: {
url: process.env.RELAY_URL || 'wss://api.relay.ckgworks.com/v1/ws/agent'
},
agents: [
{
agent_id: 'athena',
token: process.env.RELAY_ATHENA_TOKEN,
ttl_days: 14
},
{
agent_id: 'klyve',
token: process.env.RELAY_KLYVE_TOKEN,
ttl_days: 30
}
]
}
});

How It Works

Session Key Mapping

When Relay delivers an event with session_key: "relay:portal:task-123", the plugin:

  1. Strips the prefix: portal:task-123
  2. Creates/resumes an OpenClaw session with that key
  3. Your agent logic processes the request
  4. The plugin streams tokens back to Relay
Event from Relay:
{
"type": "event",
"event_id": "evt_k9p2m",
"session_key": "relay:portal:task-123", <- Full key
"payload": { ... }
}

Plugin processes:
1. Extract session_key: "relay:portal:task-123"
2. Get OpenClaw session: "relay:portal:task-123"
3. Run agent logic
4. Stream tokens back to Relay

Multi-Agent Connections

With multiple agents configured, the plugin creates one WebSocket per agent:

OpenClaw Plugin (one process)
├── Athena Agent
│ └── WebSocket to Relay (authenticated with rla_athena_...)
├── Klyve Agent
│ └── WebSocket to Relay (authenticated with rla_klyve_...)
└── Future Agent
└── WebSocket to Relay (authenticated with rla_future_...)

Each agent runs independently and can receive events concurrently.

Monitoring

The plugin exposes events you can listen to:

plugin.on('relay:connected', (agentId) => {
console.log(`${agentId} connected to Relay`);
});

plugin.on('relay:disconnected', (agentId) => {
console.log(`${agentId} disconnected from Relay`);
});

plugin.on('relay:reconnecting', (agentId, attempt) => {
console.log(`${agentId} reconnecting (attempt ${attempt})`);
});

plugin.on('event:received', (agentId, eventId, sessionKey) => {
console.log(`${agentId} received event ${eventId} for ${sessionKey}`);
});

plugin.on('event:replied', (agentId, eventId, tokenCount) => {
console.log(`${agentId} sent reply with ${tokenCount} tokens`);
});

plugin.on('event:error', (agentId, eventId, error) => {
console.error(`${agentId} error on ${eventId}: ${error}`);
});

Health Check Endpoint

The plugin can expose a health check HTTP endpoint:

const plugin = new RelayPlugin({
configPath: './openclaw.plugin.json',
healthCheck: {
enabled: true,
port: 3001,
path: '/health'
}
});

// GET http://localhost:3001/health
// Returns:
// {
// "status": "healthy",
// "agents": {
// "athena": { "connected": true, "lastPing": "2026-04-07T14:30:00Z" },
// "klyve": { "connected": false, "lastError": "Network unreachable" }
// }
// }

Per-Agent TTL

Each agent can have a different session TTL (time-to-live):

{
"agents": [
{
"agent_id": "athena",
"token": "...",
"ttl_days": 14
},
{
"agent_id": "klyve",
"token": "...",
"ttl_days": 30
}
]
}
  • Athena (14 days): General assistant, shorter memory
  • Klyve (30 days): Technical workflows, longer memory for complex projects

Sessions expire after the TTL. When a new event arrives for an expired session, a fresh session is created.

Reconnection Logic

The plugin implements exponential backoff:

Attempt 1: 1 second delay
Attempt 2: 2 seconds
Attempt 3: 4 seconds
Attempt 4: 8 seconds
Attempt 5: 16 seconds
After that: capped at maxDelayMs (60s)

Configure in the config file:

{
"relay": {
"reconnect": {
"baseDelayMs": 1000,
"maxDelayMs": 60000
}
}
}

Logging

The plugin logs to console.log/error by default. Integrate with your logging system:

const plugin = new RelayPlugin({
configPath: './openclaw.plugin.json',
logger: {
log: (message, metadata) => yourLogger.info(message, metadata),
error: (message, metadata) => yourLogger.error(message, metadata),
warn: (message, metadata) => yourLogger.warn(message, metadata)
}
});

Graceful Shutdown

Properly close connections on shutdown:

process.on('SIGTERM', async () => {
console.log('Shutting down...');
await plugin.close(); // Closes all agent connections
process.exit(0);
});

Troubleshooting

Agent appears offline in Relay dashboard?

  • Check agent token is correct
  • Verify environment variables are set
  • Check network connectivity to api.relay.ckgworks.com
  • Look at plugin logs for connection errors

"Invalid token" on startup?

  • Verify token prefix is rla_
  • Check if token was rotated (old token expired)
  • Request a new token from Relay dashboard

Tokens arriving but no replies sent back?

  • Check OpenClaw is processing events
  • Look for errors in OpenClaw logs
  • Verify the agent definition exists in OpenClaw

High reconnection rate?

  • Check network stability
  • Verify Relay isn't rejecting connections
  • Check rate limiting isn't kicking in

Limits and Quotas

  • Concurrent connections per agent: 1
  • Concurrent events per agent: Limited by OpenClaw concurrency
  • Token size: Up to 1KB per token (recommended: 1-5 words)
  • Payload size: Up to 64KB per event
  • Session key length: Up to 255 characters

Version Compatibility

Check the plugin version matches your OpenClaw version:

npm list openclaw openclaw-relay-plugin

Supported OpenClaw versions: 2.0+

Advanced: Custom Context Injection

Pass custom context to OpenClaw for each agent:

{
"agents": [
{
"agent_id": "athena",
"token": "...",
"context": {
"model": "claude-3-5-sonnet-20241022",
"temperature": 0.7,
"maxTokens": 1024,
"systemPrompt": "You are Athena, a personal AI assistant."
}
}
]
}

This context is passed to OpenClaw when creating agent sessions.

Best Practices

Do

  • Use environment variables for tokens
  • Monitor connection status
  • Set appropriate TTL per agent
  • Log events for debugging
  • Test token rotation

Don't

  • Commit tokens to git
  • Hardcode agent IDs
  • Use maxRetries < 3
  • Ignore reconnection errors
  • Skip graceful shutdown