Repository navigation
Operational Runbooks
Canonical source:
docs/11-runbooks/operational-runbooks.md— this page is rendered from it on every publish; edit the source.
ClawAI supports cloud AI providers through the connector system. Adding a new provider requires backend changes to the connector and chat services, plus frontend updates.
-
Add the provider enum value
File:
packages/shared-types/src/enums/connector-provider.enum.tsAdd the new provider to the
ConnectorProviderenum (e.g.,MISTRAL = 'MISTRAL'). An OpenAI-compatible provider needs no enum value or adapter at all — it is data: seeskills/add-an-openai-compatible-provider.md. -
Implement the provider adapter
File:
apps/claw-connector-service/src/modules/connectors/managers/adapters/<provider>.adapter.ts, registered inadapter-factory.tsnext to itImplement the adapter interface with methods for:
-
testConnection()— verify the API key works -
listModels()— fetch available models from the provider API -
healthCheck()— check provider availability
-
-
Add provider execution to chat service
File:
apps/claw-chat-service/src/modules/chat-messages/managers/chat-execution.manager.tsAdd a case for the new provider in the execution switch. Implement the API call using the provider's SDK or HTTP API (wrapped in a utility file).
-
Update routing rules
File:
apps/claw-routing-service/src/modules/routing/managers/routing.manager.tsAdd the new provider to the allowlist for AUTO mode routing. Define when the router should select this provider.
-
Update the frontend
- Add the provider to the connector creation form
- Add the provider icon/logo
- Update i18n files (all 9 locales) with the provider name
-
Add tests
- Adapter unit tests (connector service)
- Execution unit tests (chat service)
- DTO validation tests
-
Update documentation
- Update
CLAUDE.mdrouting tables - Update architecture docs if the provider has unique characteristics
- Update
Adding a new microservice to the ClawAI platform.
-
Create the service directory
mkdir -p apps/claw-<name>-service/src
Copy the structure from an existing service (e.g.,
claw-health-servicefor a simple service,claw-auth-servicefor one with Prisma). -
Set up the NestJS application
Required files:
-
src/main.ts— bootstrap with Helmet, validation pipe, global filters -
src/app/app.module.ts— root module -
src/app/app.controller.ts— health endpoint -
src/modules/<domain>/— domain module with controller, service, repository -
package.json— with workspace scripts (dev, build, lint, test, typecheck) -
tsconfig.json,tsconfig.build.json— TypeScript config -
eslint.config.mjs— ESLint flat config (copy from existing service) -
Dockerfile.dev— development Dockerfile -
docker-entrypoint.dev.sh— if using Prisma
-
-
If the service needs a database
PostgreSQL:
- Create
prisma/schema.prismawith the data model - Add the PG container to
docker/docker-compose.dev.databases.ymlanddocker/docker-compose.prod.databases.yml - Add
PG_<NAME>_USER,PG_<NAME>_PASSWORD,PG_<NAME>_DB,PG_<NAME>_PORTto.env.exampleand.env - Add
<NAME>_DATABASE_URLto.env.exampleand.env - Add named volume for the database
MongoDB:
- Add
<NAME>_MONGODB_URIto.env.exampleand.env
- Create
-
Add to Docker Compose
Add the service container to
docker/docker-compose.dev.services.ymlanddocker/docker-compose.prod.services.yml(and every GPU overlay that lists services):- Build context and Dockerfile
- Port mapping
- Volume mounts (src/ and prisma/ if applicable)
- Dependencies (database, redis, rabbitmq)
- Health check
- Network:
claw-network
-
Add Nginx route
File:
infra/nginx/nginx.confAdd a location block for the service's API path:
location /api/v1/<endpoint> { set $backend http://<name>-service:<port>; proxy_pass $backend; }
Add the service to nginx's
depends_onlist. -
Add to shared packages
- Add the port to
packages/shared-constants/ - Add event types to
packages/shared-types/if the service publishes events
- Add the port to
-
Update all configuration files
Follow the Mandatory Change Checklist in
CLAUDE.md:-
.env.exampleand.env -
scripts/install.shandscripts/install.ps1 - Docker Compose files
CLAUDE.md
-
-
Add to CI pipeline
If the service uses Prisma, add it to the Prisma generate loop in
.github/workflows/ci.yml. -
Add tests
At minimum:
app.spec.tsfor bootstrap verification.
# Backup a single database
docker exec claw-pg-auth pg_dump -U claw -d claw_auth > backup_auth_$(date +%Y%m%d).sql
# Backup all PostgreSQL databases
for svc in auth chat connector routing memory files ollama images file-generations; do
docker exec claw-pg-${svc} pg_dump -U claw -d claw_${svc} > backup_${svc}_$(date +%Y%m%d).sql
done# Restore a single database
docker exec -i claw-pg-auth psql -U claw -d claw_auth < backup_auth_20260409.sql
# Full restore (drop and recreate)
docker exec claw-pg-auth psql -U claw -d postgres -c "DROP DATABASE IF EXISTS claw_auth;"
docker exec claw-pg-auth psql -U claw -d postgres -c "CREATE DATABASE claw_auth;"
docker exec -i claw-pg-auth psql -U claw -d claw_auth < backup_auth_20260409.sql# Backup all MongoDB databases
docker exec claw-mongodb mongodump --username claw --password claw_secret --authenticationDatabase admin --out /data/backup
# Copy backup to host
docker cp claw-mongodb:/data/backup ./mongo_backup_$(date +%Y%m%d)# Copy backup into container
docker cp ./mongo_backup_20260409 claw-mongodb:/data/backup
# Restore
docker exec claw-mongodb mongorestore --username claw --password claw_secret --authenticationDatabase admin /data/backupRotating the JWT secret invalidates ALL existing access tokens and refresh tokens. All users will be logged out.
-
Generate a new secret
openssl rand -hex 32
-
Update
.envJWT_SECRET=<new-64-char-hex-string> -
Restart all backend services
./scripts/claw.sh restart auth-service chat-service connector-service routing-service memory-service file-service audit-service ollama-service health-service client-logs-service server-logs-service image-service
-
Clear expired sessions (optional)
The auth service stores refresh tokens in the database. Old sessions will fail validation naturally, but you can clean them up:
docker exec -it claw-pg-auth psql -U claw -d claw_auth -c "DELETE FROM \"Session\" WHERE \"expiresAt\" < NOW();"
-
Notify users that they need to log in again.
The encryption key (ENCRYPTION_KEY) is used for AES-256-GCM encryption of connector API keys. Rotating this key requires re-encrypting all existing connector configurations.
This is a high-risk operation. Incorrect execution will make all connector API keys unreadable.
-
Export current connector configs (while old key is active):
# Use the connector service API to list all connectors curl -H "Authorization: Bearer <admin-token>" http://localhost:4000/api/v1/connectors
Record the decrypted API keys for each connector.
-
Generate a new key
openssl rand -hex 32
-
Update
.envENCRYPTION_KEY=<new-64-char-hex-string> -
Restart the connector service
./scripts/claw.sh restart connector-service
-
Re-create or update each connector with its API key, which will be encrypted with the new key.
ClawAI services are stateless (state is in databases and RabbitMQ) and can be scaled horizontally. In Docker Compose:
./scripts/claw.sh up -d --scale chat-service=3When scaling, consider:
-
Nginx load balancing: The default config uses a single upstream. For multiple instances, add an
upstreamblock with multiple servers. - RabbitMQ consumers: Multiple instances will compete for messages (round-robin), which is the desired behavior.
- SSE connections: Each instance handles its own SSE connections. The frontend must reconnect to the same instance or use Redis pub/sub for cross-instance notification.
Adjust container resource limits in docker/docker-compose.dev.services.yml (and the prod counterpart):
services:
chat-service:
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 256MThe health service aggregates status from all other services:
curl http://localhost:4000/api/v1/health# Direct to service (bypassing nginx)
curl http://localhost:4001/api/v1/health # auth
curl http://localhost:4002/api/v1/health # chat
curl http://localhost:4003/api/v1/health # connector
curl http://localhost:4004/api/v1/health # routing
curl http://localhost:4005/api/v1/health # memory
curl http://localhost:4006/api/v1/health # file
curl http://localhost:4007/api/v1/health # audit
curl http://localhost:4008/api/v1/health # ollama
curl http://localhost:4009/api/v1/health # health
curl http://localhost:4010/api/v1/health # client-logs
curl http://localhost:4011/api/v1/health # server-logs
curl http://localhost:4012/api/v1/health # image# RabbitMQ management UI
# Open http://localhost:15672 (claw / claw_secret)
# Redis
docker exec -it claw-redis redis-cli ping
# MongoDB
docker exec -it claw-mongodb mongosh --eval "db.runCommand('ping')" --quiet
# Ollama
curl http://localhost:11434/api/tags
# Docker container status
./scripts/claw.sh ps
docker stats --no-stream# Real-time logs
docker logs claw-chat-service -f --tail=100
# Filter by log level (services use Pino JSON format)
docker logs claw-chat-service 2>&1 | grep '"level":50' # errors
docker logs claw-chat-service 2>&1 | grep '"level":40' # warnings
# Search for a specific request ID
docker logs claw-chat-service 2>&1 | grep '<request-id>'Server logs are sent to the server-logs service via RabbitMQ (log.server events). Query them via the API:
curl -H "Authorization: Bearer <token>" "http://localhost:4000/api/v1/server-logs?level=error&limit=50"Client logs are sent from the frontend to the client-logs service:
curl -H "Authorization: Bearer <token>" "http://localhost:4000/api/v1/client-logs?level=error&limit=50"All significant actions are recorded in the audit service:
curl -H "Authorization: Bearer <token>" "http://localhost:4000/api/v1/audits?action=user.login&limit=20"
curl -H "Authorization: Bearer <token>" "http://localhost:4000/api/v1/usage?limit=20"MongoDB logs have a 30-day TTL (Time-To-Live). Documents are automatically deleted after 30 days.
- Health service reports a service as unhealthy
- Error rate spikes in audit logs
- User reports feature is broken
- RabbitMQ management UI shows growing queue depth
Determine the blast radius:
- Which service is affected?
- Which other services depend on it?
- Are users currently impacted?
# If a service is causing cascading failures, stop it
./scripts/claw.sh stop <service>
# Check if dependent services recover
./scripts/claw.sh ps# Collect logs from the affected service
docker logs claw-<service> --since="2026-04-09T10:00:00" > incident_logs.txt
# Check resource usage
docker stats claw-<service> --no-stream
# Check database state
docker exec -it claw-pg-<service> psql -U claw -d claw_<service>Apply the fix (restart, rollback, configuration change, code fix).
# Restart
./scripts/claw.sh restart <service>
# Rebuild and restart
./scripts/claw.sh service:rebuild <service># Check health
curl http://localhost:4000/api/v1/health
# Check that the specific feature works
# Run relevant API calls or UI testsRecord in the audit log or team communication:
- What happened
- What was the root cause
- What was the fix
- What can prevent recurrence
Sessions that have passed their expiresAt date should be cleaned up periodically:
docker exec -it claw-pg-auth psql -U claw -d claw_auth -c "DELETE FROM \"Session\" WHERE \"expiresAt\" < NOW();"MongoDB logs have automatic TTL cleanup (30 days). To manually clean older data:
# Client logs
docker exec -it claw-mongodb mongosh --eval "
use claw_client_logs;
db.clientlogs.deleteMany({ createdAt: { \$lt: new Date(Date.now() - 30*24*60*60*1000) } });
" --username claw --password claw_secret --authenticationDatabase admin
# Server logs
docker exec -it claw-mongodb mongosh --eval "
use claw_server_logs;
db.serverlogs.deleteMany({ createdAt: { \$lt: new Date(Date.now() - 30*24*60*60*1000) } });
" --username claw --password claw_secret --authenticationDatabase adminFiles that were uploaded but not attached to any message:
docker exec -it claw-pg-files psql -U claw -d claw_files -c "
SELECT id, filename, \"createdAt\"
FROM \"File\"
WHERE id NOT IN (SELECT \"fileId\" FROM \"MessageAttachment\")
AND \"createdAt\" < NOW() - INTERVAL '30 days';
"Review the list before deleting. To delete:
docker exec -it claw-pg-files psql -U claw -d claw_files -c "
DELETE FROM \"File\"
WHERE id NOT IN (SELECT \"fileId\" FROM \"MessageAttachment\")
AND \"createdAt\" < NOW() - INTERVAL '30 days';
"Audit logs grow indefinitely in MongoDB. For long-term retention, export before cleaning:
# Export old audit logs
docker exec claw-mongodb mongodump --username claw --password claw_secret --authenticationDatabase admin --db claw_audit --query '{"createdAt": {"$lt": {"$date": "2026-01-01T00:00:00Z"}}}' --out /data/archive
# Copy to host
docker cp claw-mongodb:/data/archive ./audit_archive_$(date +%Y%m%d)
# Then delete old entries
docker exec -it claw-mongodb mongosh --eval "
use claw_audit;
db.auditlogs.deleteMany({ createdAt: { \$lt: new ISODate('2026-01-01') } });
" --username claw --password claw_secret --authenticationDatabase admin# List all queues with message counts
docker exec -it claw-rabbitmq rabbitmqctl list_queues name messages consumers
# Check exchange bindings
docker exec -it claw-rabbitmq rabbitmqctl list_bindingsOr use the management UI at http://localhost:15672.
If a queue has accumulated messages that are causing issues:
docker exec -it claw-rabbitmq rabbitmqctl purge_queue <queue-name>Failed messages (after 3 retries with exponential backoff) are routed to the DLQ. Inspect them in the management UI under the DLQ queue. Common reasons for DLQ messages:
- Consumer service was down during delivery
- Message payload does not match expected schema
- Processing error in the consumer
ClawAI Wiki · source-controlled under wiki/ · generated/mirrored from the current repository knowledge layer.
ClawAI Wiki
Product
- Product-Vision
- Flagship-Features
- Business-Overview
- Requirements-Register
- Drift-Log
- Runtime-Managed-Connector-Providers
- Threads
- ADR-Index
Architecture
- System-at-a-Glance
- Architecture-Map
- System-Architecture
- Message-Flow
- End-to-End-Data-Flow
- Routing-Engine
- Event-Bus
- Security-Architecture
Platform
- Backend-Services
- Frontend-Architecture
- Shared-Packages
- Database-Reference
- API-Reference
- Provider-Catalog
- Memory-and-Context-Architecture
- File-Support-Architecture
- Research-and-Web-Crawling
Runtime & Ops
- Docker-Guide
- Nginx-Reference
- CI-CD-Pipeline
- Logging-and-Observability
- Operational-Runbooks
- Troubleshooting
Quality
Engineering OS
- AI-Native-Engineering-OS
- Generated-Manifests
- Rules-Catalog
- Skills-Catalog
- Context-Layer
- Engineering-Memory
- Tooling-and-Automation
- Scripts-and-Operations
- ESLint-and-Architecture-Enforcement
- Extended-Work-Skills
Agents
Reference