Routes every incoming request through OpenClaw gateway to the correct client-specialized model. Each client_id maps to an active model version. No 200k context dump at inference.
┌─────────────────────────────────────────────────────────────────────────────┐ │ Incoming Request │ │ POST http://localhost:18789/v1/messages │ │ Headers: x-client-id: hre | x-model-preference: client │ └──────────────────────────────────┬──────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────────────────────┐ │ OPENCLAW GATEWAY :18789 (apps/openclaw-gateway/) │ ├──────────────────────────────────────────────────────────────────────────────┤ │ Layer 1: AuthMiddleware Tailscale IP check + API key validation │ │ Layer 2: ClientIDMiddleware Extract x-client-id → lookup model_registry │ │ Layer 3: ModelRouter Resolve active model version + track │ │ Layer 4: TelemetryMiddleware Log client_id, model_version, latency │ └──────────────────────────────────┬───────────────────────────────────────────┘ │ ModelRouter resolves → active model for client_id ┌──────────────┴──────────────┐ ▼ ▼ ┌─────────────────────────────┐ ┌────────────────────────────────────────────┐ │ Track A — OpenAI │ │ Track B — Ollama (NoClaw :11434) │ │ model: ft:gpt-4o-mini:hre-v3 │ │ model: hre-client:v3 │ │ client: hre (active) │ │ client: teleios (active, no egress) │ └──────────────┬──────────────┘ └──────────────────┬─────────────────────────┘ └──────────────────┬──────────────────┘ ▼ ┌──────────────────────────────────────────────────────────────────────────────┐ │ Response + x-model-version: hre-v3 + x-client-id: hre response header │ └──────────────────────────────────────────────────────────────────────────────┘
x-api-key header. Reject with 401 if either fails. Part of existing OpenClaw 8-phase hardening plan for CVE-2026-25253.x-client-id header. Load data/clients/{id}/model_registry.json. Find record where active: true. Attach resolved ClientContext (model_id, track, version) to request object.http://100.86.248.8:11434) based on ClientContext.track. Falls back to RAG context injection if no active model exists for client.client_id, model_version, track, latency_ms, token_count, timestamp. Write to SQLite telemetry table. Used for drift detection in Phase 6 flywheel.AccountState.system_prompt into the request messages array before forwarding to base model. Ensures graceful degradation for new clients.{
"client_id": "hre",
"display_name": "HRE",
"track_preference": "a", // "a" | "b"
"data_egress_allowed": true, // false = track B only (Teleios)
"min_examples_to_activate": 50,
"score_threshold": 0.75,
"openclaw_routing": {
"header": "x-client-id",
"fallback_on_missing_model": "rag_context", // "rag_context" | "base_model" | "error"
"response_header_version": true // attach x-model-version to responses
},
"integrations": {
"gtm_container_id": "GTM-XXXXXXX",
"google_ads_account_id": "123-456-7890",
"meta_pixel_id": "HRE-pixel-id",
"meta_ad_account_id": "act_12345"
}
}
ft:gpt-4o-mini:hre-v3teleios-client:v1model_registry.json routed directly. No context injection needed — account knowledge baked into weights. Fastest, most accurate.AccountState.system_prompt + top-5 Chroma memories. Inject as system message. Forward to base model (Claude Sonnet / GPT-4o).$ pnpm openclaw register --client hre --model ft:gpt-4o-mini-2024-07-18:hre-v3 --track a ────────────────────────────────────────────────────── OpenClaw Client Brain — Registering HRE v3 ────────────────────────────────────────────────────── Loading config... ✓ data/clients/hre/config.json Validating model_id... ✓ ft:gpt-4o-mini-2024-07-18:hre-v3 (reachable) Writing registry... ✓ model_registry.json updated Reloading OpenClaw... ✓ gateway :18789 hot-reloaded Testing routing: x-client-id: hre → ft:gpt-4o-mini-2024-07-18:hre-v3 ✓ x-client-id: teleios → teleios-client:v1 (ollama) ✓ x-client-id: unknown → fallback: rag_context ✓ ────────────────────────────────────────────────────── ✓ HRE Client Brain active on OpenClaw :18789 x-client-id: hre → ft:gpt-4o-mini-2024-07-18:hre-v3 Next: pnpm flywheel start --client hre (Phase 6)
claude --dangerously-skip-permissions
# Phase 5: OpenClaw Client Brain Integration
# Branch: feature/finetune-pipeline
# Repo: github.com/Organized-AI/gtm-autoresearch
## Context
Phases 1–4 complete. Phase 5 wires the fine-tuned models into
the OpenClaw gateway (:18789) via client-aware middleware.
## Task
Read AGENT-HANDOFF/ and PLANNING/ first.
Read existing apps/openclaw-gateway/ code before modifying.
1. Create packages/client-brain-router/
ClientIDMiddleware:
- Extract x-client-id from request header
- Load data/clients/{id}/config.json
- Load data/clients/{id}/model_registry.json
- Find active:true record → attach ClientContext to req
- If no config: set fallback mode = "rag_context"
ModelRouter:
- ClientContext.track === "a" → route to OpenAI with model_id
- ClientContext.track === "b" → route to Ollama
URL: http://{OLLAMA_HOST}/api/chat, model: client model name
- No active model → FallbackHandler
FallbackHandler:
- Load AccountState.system_prompt from data/clients/{id}/
- Query Chroma :37777 for top-5 memories by client_id
- Prepend as system message to request
- Forward to base model (FALLBACK_MODEL env var)
TelemetryLogger:
- On each request completion, write to SQLite:
{timestamp, client_id, model_version, track,
latency_ms, input_tokens, output_tokens, fallback_used}
- Expose GET /telemetry?client_id=hre for Phase 6 drift query
2. Wire middleware into apps/openclaw-gateway/ request pipeline:
AuthMiddleware → ClientIDMiddleware → ModelRouter →
TelemetryLogger → response
3. CLI: pnpm openclaw register --client hre --model {id} --track a
- Validates model is reachable before registering
- Hot-reloads gateway config (no restart needed)
- Tests all registered client routes
4. Add response headers:
x-model-version: {version}
x-client-id: {client_id}
x-fallback-used: true|false
5. Unit tests:
- ClientIDMiddleware resolves correct model for known client
- FallbackHandler activates when no active model exists
- TelemetryLogger writes correct record to SQLite
- ModelRouter correctly distinguishes track A vs B
## Env vars:
OPENCLAW_PORT=18789
OLLAMA_HOST=http://100.86.248.8:11434
FALLBACK_MODEL=claude-sonnet-4-6
CHROMA_URL=http://localhost:37777
CLIENT_DATA_DIR=./data/clients
TELEMETRY_DB_PATH=./data/telemetry.sqlite
## Do NOT build Phase 6 (flywheel) yet.