Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
4.1 KiB
PRD: openclaw-openbrain-context
Version: 0.0.1 Status: Approved
Problem Statement
OpenClaw compacts context when sessions grow long, causing information loss. The new ContextEngine plugin interface (merged in PR #22201) allows replacing the default compaction strategy with a persistent, lossless alternative. OpenBrain (brain.woltje.com) is a live pgvector + REST API service that can store and semantically retrieve conversation context indefinitely.
Solution
An OpenClaw plugin that implements the ContextEngine interface and stores all context in OpenBrain using semantic embeddings. Sessions become effectively lossless — context is archived, not discarded. On reassembly, relevant context is retrieved via semantic search.
Reference Implementation
lossless-claw (https://github.com/Martian-Engineering/lossless-claw) is the primary reference. It uses SQLite; we use OpenBrain (Postgres + pgvector via REST). Our implementation is simpler: no local DB, no migrations — everything goes through the OpenBrain REST API.
OpenBrain API
Base: https://brain.woltje.com
Auth: Bearer <OPENBRAIN_API_KEY>
POST /v1/thoughts { content, source, metadata }
POST /v1/search { query, limit }
GET /v1/thoughts/recent ?limit=N&source=X
PATCH /v1/thoughts/:id { content?, metadata? }
DELETE /v1/thoughts/:id
DELETE /v1/thoughts ?source=X&metadata_id=Y (bulk)
Plugin Architecture
ContextEngine interface lifecycle hooks to implement:
bootstrap(sessionId)— init session context, retrieve prior context from OpenBrainingest(message)— store each message turn to OpenBrainingestBatch(messages)— bulk store (e.g., on session import)afterTurn()— post-turn hook (optional: summarize/compress)assemble(maxTokens)— retrieve relevant context for next turn via semantic searchcompact(params)— archive current context to OpenBrain, return minimal summaryprepareSubagentSpawn(subagentId)— pass relevant context to spawned subagentonSubagentEnded(subagentId, reason)— integrate subagent results backdispose()— cleanup
Source tagging strategy
Each thought stored in OpenBrain:
source:openclaw:<agentId>(e.g.,openclaw:main)metadata.sessionId: session keymetadata.turn: turn indexmetadata.role:user|assistant|toolmetadata.type:message|summary|subagent-result
Retrieval strategy
On assemble():
- Fetch recent N messages (ordered, for continuity)
- Semantic search with last user message as query
- Merge + deduplicate, trim to maxTokens
Plugin Registration
// index.ts
import { OpenBrainContextEngine } from "./src/engine.js";
export function register(api: OpenClawPluginApi) {
api.registerContextEngine("openbrain", (config) =>
new OpenBrainContextEngine(config)
);
}
Configuration (openclaw.json)
{
"agents": {
"defaults": {
"contextEngine": "openbrain"
}
},
"plugins": {
"entries": {
"openclaw-openbrain-context": {
"enabled": true,
"config": {
"baseUrl": "https://brain.woltje.com",
"apiKey": "${OPENBRAIN_API_KEY}",
"recentMessages": 20,
"semanticSearchLimit": 10,
"source": "openclaw"
}
}
}
}
}
Tech Stack
- TypeScript strict
- No local DB (pure REST calls to OpenBrain)
- openclaw/plugin-sdk for ContextEngine interface
- pnpm, vitest, ESLint
Acceptance Criteria (v0.0.1)
- Plugin registers as a ContextEngine with id
openbrain ingest()stores messages to OpenBrain with correct metadataassemble()retrieves recent + semantically relevant context within token budgetcompact()archives turn summary, returns minimal prompt-injectionbootstrap()loads prior session context on restart- Tests pass, TypeScript strict, ESLint clean
- openclaw.plugin.json with correct manifest
- README: install + config + usage
ASSUMPTION: ContextEngine interface shape
Based on lossless-claw source and PR #22201. Plugin SDK import path: openclaw/plugin-sdk.