1 Commits

Author SHA1 Message Date
0cdfec7557 chore(orchestrator): Bootstrap PRD + TASKS.md for v0.0.1
Phase 1: OpenClaw ContextEngine plugin backed by OpenBrain (8 tasks, ~83K est)
Stack: TypeScript, openclaw/plugin-sdk, OpenBrain REST
2026-03-06 08:07:43 -06:00
2 changed files with 129 additions and 0 deletions

117
docs/PRD.md Normal file
View File

@@ -0,0 +1,117 @@
# 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 OpenBrain
- `ingest(message)` — store each message turn to OpenBrain
- `ingestBatch(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 search
- `compact(params)` — archive current context to OpenBrain, return minimal summary
- `prepareSubagentSpawn(subagentId)` — pass relevant context to spawned subagent
- `onSubagentEnded(subagentId, reason)` — integrate subagent results back
- `dispose()` — cleanup
### Source tagging strategy
Each thought stored in OpenBrain:
- `source`: `openclaw:<agentId>` (e.g., `openclaw:main`)
- `metadata.sessionId`: session key
- `metadata.turn`: turn index
- `metadata.role`: `user` | `assistant` | `tool`
- `metadata.type`: `message` | `summary` | `subagent-result`
### Retrieval strategy
On `assemble()`:
1. Fetch recent N messages (ordered, for continuity)
2. Semantic search with last user message as query
3. Merge + deduplicate, trim to maxTokens
## Plugin Registration
```typescript
// index.ts
import { OpenBrainContextEngine } from "./src/engine.js";
export function register(api: OpenClawPluginApi) {
api.registerContextEngine("openbrain", (config) =>
new OpenBrainContextEngine(config)
);
}
```
## Configuration (openclaw.json)
```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)
1. Plugin registers as a ContextEngine with id `openbrain`
2. `ingest()` stores messages to OpenBrain with correct metadata
3. `assemble()` retrieves recent + semantically relevant context within token budget
4. `compact()` archives turn summary, returns minimal prompt-injection
5. `bootstrap()` loads prior session context on restart
6. Tests pass, TypeScript strict, ESLint clean
7. openclaw.plugin.json with correct manifest
8. README: install + config + usage
## ASSUMPTION: ContextEngine interface shape
Based on lossless-claw source and PR #22201. Plugin SDK import path: `openclaw/plugin-sdk`.

12
docs/TASKS.md Normal file
View File

@@ -0,0 +1,12 @@
# Tasks — openclaw-openbrain-context v0.0.1
| id | status | description | issue | repo | branch | depends_on | blocks | agent | started_at | completed_at | estimate | used | notes |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| OBC-001 | not-started | Init: pnpm, TypeScript strict, ESLint, vitest, openclaw plugin-sdk dep | TASKS:P1 | openclaw-openbrain-context | feat/engine | | OBC-002 | | | | 8K | | |
| OBC-002 | not-started | OpenBrain REST client module (typed, auth, error handling) | TASKS:P1 | openclaw-openbrain-context | feat/engine | OBC-001 | OBC-003 | | | | 8K | | |
| OBC-003 | not-started | ContextEngine implementation: bootstrap + ingest + ingestBatch | TASKS:P1 | openclaw-openbrain-context | feat/engine | OBC-002 | OBC-004 | | | | 15K | | |
| OBC-004 | not-started | ContextEngine implementation: assemble (recent + semantic merge) | TASKS:P1 | openclaw-openbrain-context | feat/engine | OBC-003 | OBC-005 | | | | 15K | | |
| OBC-005 | not-started | ContextEngine implementation: compact + prepareSubagentSpawn + onSubagentEnded + dispose | TASKS:P1 | openclaw-openbrain-context | feat/engine | OBC-004 | OBC-006 | | | | 12K | | |
| OBC-006 | not-started | Plugin entrypoint: register(), openclaw.plugin.json manifest | TASKS:P1 | openclaw-openbrain-context | feat/engine | OBC-005 | OBC-007 | | | | 5K | | |
| OBC-007 | not-started | Unit tests: ingest/assemble/compact + mock OpenBrain responses | TASKS:P1 | openclaw-openbrain-context | feat/engine | OBC-006 | OBC-008 | | | | 15K | | |
| OBC-008 | not-started | README + install instructions + openclaw.json config example | TASKS:P1 | openclaw-openbrain-context | feat/engine | OBC-007 | | | | | 5K | | |