OpenClaw Adapter
May 7, 2026 · View on GitHub
context-mode plugin for the OpenClaw gateway, targeting Pi Agent sessions.
Overview
OpenClaw is the gateway/platform that manages agent sessions, extensions, and tool routing. Pi Agent is OpenClaw's coding agent — it runs within OpenClaw and provides Read, Write, Edit, and Bash tools for software development tasks.
The context-mode adapter hooks into Pi Agent sessions specifically, intercepting tool calls to route data-heavy operations through the sandbox and tracking session events for compaction recovery.
Supported Configurations
- Pi Agent sessions with coding tools (Read/Write/Edit/Bash) — fully supported.
- Custom agents with coding tools — may work but are untested. The adapter relies on tool names matching Pi Agent's conventions.
Installation
Quick install
npm run install:openclaw
This runs scripts/install-openclaw-plugin.sh, which handles building, extension setup, runtime registration, and gateway restart.
Prerequisites
- Node.js must be in PATH (required for the build and registration steps)
- OpenClaw must have been started once — the script needs
openclaw.json, which OpenClaw creates on first launch OPENCLAW_STATE_DIRmust point to your OpenClaw state directory (default:/openclaw). Pass it as an argument:npm run install:openclaw -- /path/to/state
Manual install
For advanced users or custom setups:
bash scripts/install-openclaw-plugin.sh [OPENCLAW_STATE_DIR]
See scripts/install-openclaw-plugin.sh for details.
Troubleshooting
"openclaw.json not found"
OpenClaw creates this file on first launch. Start OpenClaw once (openclaw gateway start), then re-run the install script. This is the most common issue for users who install context-mode before ever starting OpenClaw.
"OPENCLAW_STATE_DIR (/path) does not exist. Is OpenClaw installed?"
The state directory doesn't exist at the expected path. If you installed OpenClaw via npm (not git clone), check where it stores state — common locations are ~/.openclaw or /openclaw. Pass the correct path: npm run install:openclaw -- /path/to/state.
Plugin installed but not loading
Clear the jiti cache (rm -f /tmp/jiti/context-mode-*.cjs) and restart the gateway. If the issue persists, verify the plugin appears in openclaw plugins list.
Plugin loads but ctx_* tools are missing from the agent's tool list
The plugin registers its hooks via api.on(...) / api.registerCommand(...), but the agent-callable ctx_* tools live in the MCP server (server.bundle.mjs). OpenClaw surfaces them by spawning the server as an MCP sidecar declared in mcp.servers.context-mode. The install script writes this entry automatically (step 5); if you configured OpenClaw manually, verify with openclaw mcp list and add it if missing:
openclaw mcp set context-mode \
"{\"command\":\"node\",\"args\":[\"/absolute/path/to/context-mode/server.bundle.mjs\"]}"
openclaw gateway restart
After the restart, the agent's tool inventory should include context-mode__ctx_execute, context-mode__ctx_search, context-mode__ctx_fetch_and_index, and the rest of the ctx_* surface (OpenClaw prefixes MCP-sourced tools with the server name).
Hook Registration
The adapter uses two different registration APIs, matching OpenClaw's internal architecture:
api.on()for lifecycle and tool hooks:session_start,before_tool_call,after_tool_call,before_compaction,after_compaction,before_prompt_build,before_model_resolve. These are typed event emitters with structured payloads.api.registerHook()for command hooks:command:new,command:reset,command:stop. These use colon-delimited names and the generic hook registration system.
Using the wrong API (e.g., api.registerHook("before_tool_call", ...)) registers silently but the hook never fires. This distinction is critical.
Synchronous register()
OpenClaw silently discards the return value of register(). If register() is async, all hooks registered inside it are lost. The adapter uses the initPromise pattern:
register(api): void {
const initPromise = (async () => { /* async setup */ })();
api.on("after_tool_call", async (e) => {
await initPromise;
// handle event
});
}
Session Continuity
| Hook | Method | Status |
|---|---|---|
after_tool_call | api.on() | Working |
before_compaction | api.on() | Working |
session_start | api.on() | Working |
command:new | api.registerHook() | Working |
command:reset | api.registerHook() | Working |
command:stop | api.registerHook() | Working |
Graceful Degradation
If compaction hooks fail to fire (e.g., on older OpenClaw versions), the adapter falls back to DB snapshot reconstruction — rebuilding session state from the events already persisted in SQLite by after_tool_call. This produces a less precise snapshot than the PreCompact path but preserves critical state (active files, tasks, errors).
Previously Known Upstream Issues
Both issues below have been resolved in upstream OpenClaw:
- #4967 — Compaction hooks not firing. Closed as duplicate of #3728; fix merged.
- #5513 —
api.on()hooks not invoked for tool lifecycle events. Fixed in PR #9761.
Minimum Version
Required: OpenClaw >2026.1.29
This is the first release that includes the api.on() fix from PR #9761, which shipped on 2026-01-29.
What breaks on older versions: Lifecycle hooks registered via api.on() — including before_compaction, after_compaction, session_start, and tool interception hooks — may silently fail to fire.
Graceful degradation: If compaction hooks don't fire, the adapter falls back to DB snapshot reconstruction, rebuilding session state from events already persisted by after_tool_call. This produces a less precise snapshot than the PreCompact path but preserves critical state (active files, tasks, errors). The adapter will not crash on older versions, but compaction recovery quality will be reduced.
Workspace Routing
The adapter includes a workspace router (src/adapters/openclaw/workspace-router.ts) that resolves project paths from Pi Agent session metadata, ensuring session databases and routing instructions are scoped per-workspace.
Key Files
| File | Purpose |
|---|---|
src/adapters/openclaw/plugin.ts | Main plugin entry (sync register, initPromise pattern) |
src/adapters/openclaw/workspace-router.ts | Workspace path resolution for session scoping |
.openclaw-plugin/ | Plugin manifest (index.ts, openclaw.plugin.json, package.json) |
scripts/install-openclaw-plugin.sh | One-shot installer |