Skip to content

fix(openclaw): claim plugins.slots.memory via registerMemoryCapability#310

Merged
rohitg00 merged 2 commits into
mainfrom
fix/openclaw-register-memory-capability
May 12, 2026
Merged

fix(openclaw): claim plugins.slots.memory via registerMemoryCapability#310
rohitg00 merged 2 commits into
mainfrom
fix/openclaw-register-memory-capability

Conversation

@rohitg00
Copy link
Copy Markdown
Owner

@rohitg00 rohitg00 commented May 12, 2026

Problem

The OpenClaw integration declared "kind": "memory" in its manifest and wired before_agent_start / agent_end hooks, but never called api.registerMemoryCapability(...). On OpenClaw 2026.4.9+, plugins.slots.memory = "agentmemory" reported unavailable despite hooks running end-to-end and the REST API being healthy.

Verified API contract

Pulled [email protected] and read the type declarations directly:

// plugin-sdk/src/plugins/types.d.ts:2028
registerMemoryCapability: (capability: MemoryPluginCapability) => void;

// plugin-sdk/src/plugins/memory-state.d.ts
export type MemoryPluginCapability = {
  promptBuilder?: MemoryPromptSectionBuilder;
  flushPlanResolver?: MemoryFlushPlanResolver;
  runtime?: MemoryPluginRuntime;
  publicArtifacts?: MemoryPluginPublicArtifactsProvider;
};

export type MemoryPromptSectionBuilder = (params: {
  availableTools: Set<string>;
  citationsMode?: MemoryCitationsMode;
}) => string[];

All capability fields are optional. promptBuilder alone is enough to claim the slot.

Changes

integrations/openclaw/plugin.mjs

if (typeof api.registerMemoryCapability === "function") {
  api.registerMemoryCapability({
    promptBuilder: () => [
      "Long-term memory provider: agentmemory (external REST service on " +
        client.baseUrl + ").",
      "agentmemory recalls relevant prior observations before each turn via " +
        "the before_agent_start hook and captures completed turns via agent_end.",
      "Treat recalled context as background, not authoritative — prefer " +
        "current workspace state and explicit user instructions when they conflict.",
    ],
  });
}
  • Guards on typeof api.registerMemoryCapability === "function" so older OpenClaw builds (pre-capability API) still load via the existing hook-only path. Net behaviour on older hosts unchanged.
  • Returns the configured base_url in the prompt so the agent knows where recall is coming from.

integrations/openclaw/README.md

Adds an explicit troubleshooting entry for plugins.slots.memory = "agentmemory" reports unavailable, points at this fix. Documents the runtime-adapter scope decision so users running deep host integrations aren't surprised.

test/openclaw-plugin.test.ts (new, 3 cases)

  1. registerMemoryCapability is called with a promptBuilder when the host supports it.
  2. Plugin still registers hooks and does not throw on older hosts that don't expose registerMemoryCapability.
  3. promptBuilder respects the configured base_url.

What this PR does NOT do

Does not register a runtime adapter. OpenClaw's current MemoryRuntimeBackendConfig type is:

type MemoryRuntimeBackendConfig =
  | { backend: "builtin" }
  | { backend: "qmd"; qmd?: { command?: string } };

Both variants are in-process backends. There's no "external" option that fits agentmemory's REST shape. The hook-driven recall + capture flow remains the working integration path; full runtime registration is documented as a follow-up gated on an upstream OpenClaw change to add an "external" backend variant.

Why a fresh PR, not #302

The closed PR #302 attempted the same end goal but:

  1. Imported memoryRuntime from openclaw/extensions/memory-core/runtime-api — a path not in the package's exports map. Would have failed with ERR_PACKAGE_PATH_NOT_EXPORTED at load time.
  2. Referenced a memoryRuntime symbol that does not exist anywhere in [email protected].

This PR uses only api.registerMemoryCapability(...) directly off the api object the plugin init receives — no openclaw imports needed.

Test plan

  • npm test871 / 871 (868 baseline + 3 new tests).
  • npm run build — tsdown clean.
  • Smoke test on a real OpenClaw 2026.4.9+ install: plugins.slots.memory = "agentmemory" should now show as available; the prompt-section builder lines should appear in the assembled system prompt.
  • If unavailable still reports after this lands, file follow-up with the exact OpenClaw build's slot-status check (might need additional optional capability fields).

Closes the bug premise originally reported in PR #302 (without picking up that PR's broken implementation).

Summary by CodeRabbit

  • New Features

    • OpenClaw plugin now registers memory capability when available, enabling automatic recall before interactions and capture after turns.
    • Prompt generation now reflects the configured external memory service, including its base URL.
  • Documentation

    • Expanded README with detailed memory runtime behavior and troubleshooting guidance, including upgrade advice for registration issues.
  • Tests

    • Added tests verifying memory capability registration, hook behavior, and prompt content.

Review Change Stack

The OpenClaw integration declared kind: "memory" in its manifest and
wired before_agent_start / agent_end hooks, but never called
api.registerMemoryCapability(...). On OpenClaw 2026.4.9+ that
left plugins.slots.memory = "agentmemory" reporting unavailable
even though the hooks worked end-to-end and the REST API was
healthy.

Per OpenClaw's plugin SDK declarations
(plugin-sdk/src/plugins/types.d.ts), api.registerMemoryCapability
takes a MemoryPluginCapability and is the canonical way to occupy
the memory slot. All capability fields are optional. The
promptBuilder field has signature:
  (params: { availableTools: Set<string>; citationsMode? }) => string[]

This commit:

- Calls api.registerMemoryCapability({ promptBuilder }) at register
  time when the host exposes it. promptBuilder returns three lines
  describing agentmemory as the active memory provider, including
  the configured base_url so the agent knows where recall is
  coming from.
- Guards on `typeof api.registerMemoryCapability === "function"`
  so older OpenClaw builds (pre-capability API) still load via
  the existing hook-only path. Net behaviour on older hosts is
  unchanged.
- Does NOT register a runtime adapter. OpenClaw's current
  MemoryRuntimeBackendConfig type is exactly { backend: "builtin" }
  or { backend: "qmd"; qmd?: { command?: string } }; both are
  in-process backends and don't fit an external REST service.
  The hook-driven recall + capture flow is the working
  integration path; runtime registration is documented as a
  follow-up gated on an upstream OpenClaw change to add an
  "external" backend variant.

README troubleshooting block adds a specific entry for the
"unavailable slot" symptom, pointing at the registerMemoryCapability
fix. The README also documents the runtime-adapter scope decision
so users running deep host integrations aren't surprised.

3 new tests in test/openclaw-plugin.test.ts assert:
1. registerMemoryCapability is called with a promptBuilder when
   the host supports it.
2. Plugin still registers hooks and does not throw on older hosts
   that don't expose registerMemoryCapability.
3. promptBuilder respects the configured base_url.

871 / 871 tests pass.

Verified against the openclaw npm package surface:
- api.registerMemoryCapability is declared at
  plugin-sdk/src/plugins/types.d.ts:2028
- MemoryPluginCapability is declared at
  plugin-sdk/src/plugins/memory-state.d.ts
- promptBuilder signature matches MemoryPromptSectionBuilder
- No import from openclaw/extensions/* needed (and that path is
  not in the package's exports map anyway)

This is a fresh implementation. The closed PR #302 attempted the
same end goal but imported memoryRuntime from a non-existent
path (openclaw/extensions/memory-core/runtime-api) and would have
failed with ERR_PACKAGE_PATH_NOT_EXPORTED at load time.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agentmemory Ready Ready Preview, Comment May 12, 2026 10:38pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b6cfbbf3-924e-4800-aa19-9ac1e449338b

📥 Commits

Reviewing files that changed from the base of the PR and between 39f3a45 and 10ef4b7.

📒 Files selected for processing (1)
  • integrations/openclaw/plugin.mjs

📝 Walkthrough

Walkthrough

The OpenClaw plugin now claims the plugins.slots.memory capability by conditionally registering via api.registerMemoryCapability() with a promptBuilder describing external agentmemory integration. Tests validate the capability registration, promptBuilder output content, and backward compatibility when the API lacks memory capability support. Documentation explains the new integration behaviors and provides troubleshooting guidance.

Changes

OpenClaw memory capability registration

Layer / File(s) Summary
Memory capability registration implementation
integrations/openclaw/plugin.mjs
Plugin header and plugin.register function now document and implement memory capability registration, conditionally calling api.registerMemoryCapability with a promptBuilder that references the configured agentmemory base URL and lifecycle hooks for recall/capture.
Memory capability registration tests
test/openclaw-plugin.test.ts
Vitest suite with FakeApi harness validates registerMemoryCapability is called once, checks promptBuilder content matches configured base URL, and verifies graceful fallback behavior when registerMemoryCapability is unavailable in older API versions.
README integration documentation
integrations/openclaw/README.md
"What the plugin does" section expanded with ordered list of integration behaviors; new "Memory runtime (current scope)" section added; troubleshooting section updated with version requirement (v0.9.11+) and explanation of missing capability registration in older plugin versions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • rohitg00/agentmemory#113: Both PRs modify the OpenClaw integration in integrations/openclaw/plugin.mjs and README; this PR builds on the plugin foundation introduced in PR #113.
  • rohitg00/agentmemory#230: Both PRs touch the OpenClaw integration to change how the agentmemory plugin integrates with OpenClaw's memory capability and lifecycle hooks.

Poem

🐰 I nibble at prompts with ears held high,
AgentMemory whispers from base_url nigh,
Hooks recall and save each passing thread,
Tests ensure no memory is misled,
A rabbit cheers the integration sky!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: the plugin now claims the plugins.slots.memory capability by calling registerMemoryCapability, which is the core fix addressed throughout the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/openclaw-register-memory-capability

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integrations/openclaw/plugin.mjs`:
- Around line 126-132: The promptBuilder currently has the wrong signature
(defined as () => [...]) which violates the expected contract; update the
promptBuilder function to accept a params object parameter (e.g., ({
availableTools }: { availableTools: Set<string> }) or similar) so it matches the
test/type expectations, and if you don't need to use availableTools yet, accept
it and optionally reference or ignore it explicitly to avoid unused-argument
warnings; locate and update the promptBuilder definition in the OpenClaw plugin
(symbol: promptBuilder) to accept and propagate the params argument.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a277b1a8-b4ce-4d23-bf69-4181b94b16ce

📥 Commits

Reviewing files that changed from the base of the PR and between 292e9f6 and 39f3a45.

📒 Files selected for processing (3)
  • integrations/openclaw/README.md
  • integrations/openclaw/plugin.mjs
  • test/openclaw-plugin.test.ts

Comment thread integrations/openclaw/plugin.mjs Outdated
…ptSectionBuilder

Reviewer flagged that promptBuilder was declared as () => [...] which
doesn't match the MemoryPluginCapability contract verified from
[email protected] (plugin-sdk/src/plugins/memory-state.d.ts):

  type MemoryPromptSectionBuilder = (params: {
    availableTools: Set<string>;
    citationsMode?: MemoryCitationsMode;
  }) => string[];

JavaScript would tolerate the zero-arg form at runtime (extra args
are ignored), but the signature was misleading and would fail a
TypeScript port. Updated to (_params) => [...] with a comment
explaining we accept-but-ignore. Underscore-prefix conveys
intentional non-use to lint/readers.

Validation: 3/3 openclaw tests still pass (they invoke
promptBuilder({ availableTools: new Set() }) — both old and new
signatures accept that call).
@rohitg00 rohitg00 merged commit 48b11e8 into main May 12, 2026
4 of 5 checks passed
@rohitg00 rohitg00 deleted the fix/openclaw-register-memory-capability branch May 12, 2026 22:39
rohitg00 added a commit that referenced this pull request May 12, 2026
… website star button (#317)

Three landed PRs since v0.9.10:
- #311 — Codex plugin support (manifest + marketplace + Codex-shaped
  hooks subset, sharing the same scripts as the Claude Code plugin
  via CLAUDE_PLUGIN_ROOT OOTB-compat injection on Codex's hook
  engine)
- #310 — OpenClaw plugins.slots.memory now actually claimed via
  api.registerMemoryCapability({ promptBuilder }); older builds
  without the capability API still load via the existing hook-only
  path
- #316 — Star on GitHub button in the website hero CTA row, live
  stargazer count via api.github.com, 30-minute localStorage cache,
  graceful degrade on API failure

Bumping 0.9.10 -> 0.9.11 across the 8 standard files:
- package.json
- packages/mcp/package.json
- plugin/.claude-plugin/plugin.json
- plugin/.codex-plugin/plugin.json
- src/version.ts
- src/types.ts (ExportData.version literal)
- src/functions/export-import.ts (supportedVersions)
- test/export-import.test.ts (round-trip expectation)
- CHANGELOG.md (new 0.9.11 entry)

877 / 877 tests pass. Build clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant