---
title: "OpenClaw Integration"
description: "The OpenClaw Integration binds Mem0 memory management into the OpenClaw agent runtime, supporting both cloud-hosted Mem0 platform backends and self-hosted open-source deployments. It solves the pro..."
last_updated: "2026-10-11T17:37:10.212608+00:00"
canonical_url: "https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/agent-plugins/openclaw-integration"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [integrations/openclaw/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/index.ts)
- [integrations/openclaw/cli/commands.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/commands.ts)
- [integrations/openclaw/tools/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/index.ts)
- [integrations/hermes-plugin-mem0/__init__.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/hermes-plugin-mem0/__init__.py)
- [integrations/opencode-plugin/opencode-mem0.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/opencode-plugin/opencode-mem0.ts)
- [integrations/openclaw/tools/memory-list.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-list.ts)
- [integrations/pi-agent-plugin/src/memory/tools.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts)
- [integrations/openclaw/tools/memory-delete.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-delete.ts)
- [integrations/openclaw/tools/memory-get.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-get.ts)
- [integrations/openclaw/tools/memory-update.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-update.ts)
- [integrations/openclaw/openclaw.plugin.json](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/openclaw.plugin.json)
- [integrations/openclaw/tools/memory-add.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-add.ts)
- [integrations/claude-code-plugin/core/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_cli.py)
- [integrations/openclaw/tools/memory-search.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-search.ts)
- [integrations/openclaw/providers.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/providers.ts)
- [integrations/openclaw/tools/memory-event-list.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-event-list.ts)
- [integrations/openclaw/isolation.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/isolation.ts)
- [integrations/openclaw/openclaw-plugin-sdk.d.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/openclaw-plugin-sdk.d.ts)
- [integrations/deepseek-plugin/src/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/deepseek-plugin/src/index.ts)
- [cli/node/src/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/cli/node/src/index.ts)
- [integrations/kimi-plugin/core/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/kimi-plugin/core/memory_cli.py)
- [integrations/codex-plugin/core/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/codex-plugin/core/memory_cli.py)
- [integrations/antigravity-plugin/core/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/memory_cli.py)
- [integrations/openclaw/cli/config-file.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts)
- [integrations/openclaw/cli/oss-wizard.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts)
- [integrations/openclaw/recall.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts)
- [integrations/openclaw/fs-safe.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/fs-safe.ts)
</details>

## Overview

The OpenClaw Integration binds Mem0 memory management into the OpenClaw agent runtime, supporting both cloud-hosted Mem0 platform backends and self-hosted open-source deployments. It solves the problem of stateless agent turns by providing automated context injection and fact extraction alongside granular tool execution. Key design decisions include per-agent session namespacing to isolate state, token-budgeted and category-ranked recall engines, and robust CLI authentication helpers that persist credentials safely within local configuration files.

Sources: [integrations/openclaw/openclaw.plugin.json:4-5](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/openclaw.plugin.json#L4-L5), [integrations/openclaw/index.ts:90-105](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/index.ts#L90-L105), [integrations/openclaw/recall.ts:1-10](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L1-L10)

## Plugin Lifecycle and Hook Registration

The `memoryPlugin` entry point orchestrates plugin bootstrapping, configuration validation, and backend initialization within the OpenClaw execution environment. Upon registration through `definePluginEntry`, the `register` method initializes telemetry flags and reads persistent authentication state from configuration artifacts. It validates settings using `mem0ConfigSchema` against `api.pluginConfig` combined with file-based credentials, determining whether the host runs in `cli-metadata` registration mode or standard execution.

```mermaid
flowchart TD
    Start([register API]) --> Bootstrap[bootstrapTelemetryFlag]
    Bootstrap --> ReadAuth[readPluginAuth]
    ReadAuth --> ParseCfg[mem0ConfigSchema.parse]
    ParseCfg --> CheckMode{registrationMode === cli-metadata?}
    
    CheckMode -- Yes --> RegCLI[registerCliCommands only]
    CheckMode -- No --> CheckSetup{cfg.needsSetup?}
    
    CheckSetup -- Yes --> Warn[api.logger.warn missing API key]
    Warn --> RegCLIInit[registerCLICommands with nulls]
    RegCLIInit --> RegSvc[api.registerService waiting state]
    
    CheckSetup -- No --> Prov[createProvider cfg, api]
    Prov --> Life[createMemoryLifecycle beginSession]
    Life --> BackendChoice{cfg.mode === platform?}
    
    BackendChoice -- Yes --> Plat[PlatformBackend init]
    BackendChoice -- No --> OSS[providerToBackend adapter]
    
    Plat --> Tools[registerAllTools & hooks]
    OSS --> Tools
    
    Tools --> End([Ready])
```
Sources: [integrations/openclaw/index.ts:90-184](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/index.ts#L90-L184)

> [!WARNING]
> If `cfg.needsSetup` evaluates to true due to a missing API key, full memory capabilities are disabled, logging a warning instructing operators to run `openclaw mem0 init`. Even in this unauthenticated state, the plugin registers CLI commands and a waiting service so the initialization flow remains accessible.
Sources: [integrations/openclaw/index.ts:137-167](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/index.ts#L137-L167)

When fully configured, `createProvider` instantiates either a `PlatformProvider` for cloud-hosted backends or an `OSSProvider` for self-hosted instances. The lifecycle manager begins a new session, and a `Backend` instance is selected: `PlatformBackend` is assigned when `cfg.mode === "platform"`, while `providerToBackend` wraps local providers for open-source mode. 

```typescript
const provider = createProvider(cfg, api);
const lifecycle = createMemoryLifecycle();
lifecycle.beginSession();

// Create Backend instance — PlatformBackend for platform mode, providerToBackend adapter for OSS
let backend: Backend;
if (cfg.mode === "platform") {
  backend = new PlatformBackend({
    apiKey: cfg.apiKey!,
    baseUrl: cfg.baseUrl ?? "https://api.mem0.ai",
  });
} else {
  backend = providerToBackend(provider, cfg.userId);
}

```
Sources: [integrations/openclaw/index.ts:170-184](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/index.ts#L170-L184), [integrations/openclaw/providers.ts:530-584](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/providers.ts#L530-L584)

## Per-Agent Isolation and Scoping

### Session Trigger Filtering and Subagent Detection

Multi-agent memory boundary enforcement relies on deriving structured user identifiers from session keys, ensuring distinct agent workspaces do not pollute shared storage namespaces. The isolation engine processes OpenClaw session keys to detect system automation triggers, identify ephemeral subagent runs, and extract specific agent identifiers.

System-initiated execution loops such as cron jobs, heartbeats, automation pipelines, and schedules are filtered out using `isNonInteractiveTrigger` to prevent automated prompts from contaminating long-term user memory stores. This function checks explicit trigger names against the `SKIP_TRIGGERS` set and falls back to inspecting the session key pattern for `:cron:` or `:heartbeat:` tokens.

```typescript
 */
const SKIP_TRIGGERS = new Set(["cron", "heartbeat", "automation", "schedule"]);

/**
 * Returns true if the session trigger is non-interactive and memory
 * hooks should be skipped entirely.
 *
 * Also detects cron-style session keys (e.g. "agent:main:cron:<id>")
 * as a fallback when the trigger field is not set.
 */
export function isNonInteractiveTrigger(
  trigger: string | undefined,
  sessionKey: string | undefined,
): boolean {
  if (trigger && SKIP_TRIGGERS.has(trigger.toLowerCase())) return true;

  // Fallback: detect cron/heartbeat from the session key pattern
  if (sessionKey) {
    if (/:cron:/i.test(sessionKey) || /:heartbeat:/i.test(sessionKey))
      return true;
  }

  return false;
}
```
Sources: [integrations/openclaw/isolation.ts:16-39](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/isolation.ts#L16-L39)

> [!WARNING]
> Ephemeral subagent sessions identified by `isSubagentSession` through the `:subagent:` pattern evaluate to empty namespaces during memory recall and leave orphaned data after capture because their random UUIDs change with every spawn.
Sources: [integrations/openclaw/isolation.ts:46-49](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/isolation.ts#L46-L49)

### User Identification Resolution and Session Parsing

Session keys follow specific formats that determine how the agent extracts isolation boundaries. The `extractAgentId` function parses subagent UUIDs, named agent identifiers, and primary main sessions.

| Session Key Pattern | Example Format | Extracted Agent ID Result |
| :--- | :--- | :--- |
| Main Agent Session | `agent:main:main` | `undefined` (falls back to base user ID) |
| Subagent Session | `agent:main:subagent:d3b07384` | `subagent-d3b07384` |
| Named Agent Session | `agent:researcher:main` | `researcher` |

Sources: [integrations/openclaw/isolation.ts:53-77](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/isolation.ts#L53-L77)

The resolution hierarchy implemented in `resolveUserId` enforces priority rules when determining the active namespace for memory reads and writes. Explicit parameter overrides take precedence over session context, which in turn overrides base configuration settings.

```mermaid
flowchart TD
    Start([resolveUserId params]) --> CheckAgent{opts.agentId present?}
    CheckAgent -- Yes --> ResAgent[Return agentUserId base, opts.agentId]
    CheckAgent -- No --> CheckUser{opts.userId present?}
    
    CheckUser -- Yes --> ResUser[Return opts.userId]
    CheckUser -- No --> CheckSession{currentSessionId present?}
    
    CheckSession -- Yes --> ResEffective[Return effectiveUserId base, currentSessionId]
    CheckSession -- No --> ResBase[Return baseUserId]
```
Sources: [integrations/openclaw/isolation.ts:98-107](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/isolation.ts#L98-L107)

## Memory Tool Execution and CRUD

### Tool Registration and Execution Lifecycle

The plugin exposes a comprehensive set of capabilities for managing stored memories through the OpenClaw tool registration framework. The `registerAllTools` function registers eight distinct tool handlers using the plugin API with `optional: false` settings, ensuring that memory management tools are always available during agent execution loops.

```typescript
export function registerAllTools(deps: ToolDeps): void {
  const { api } = deps;
  const nonOptional = { optional: false };

  api.registerTool(createMemorySearchTool(deps), nonOptional);
  api.registerTool(createMemoryAddTool(deps), nonOptional);
  api.registerTool(createMemoryGetTool(deps), nonOptional);
  api.registerTool(createMemoryListTool(deps), nonOptional);
  api.registerTool(createMemoryUpdateTool(deps), nonOptional);
  api.registerTool(createMemoryDeleteTool(deps), nonOptional);
  api.registerTool(createMemoryEventListTool(deps), nonOptional);
  api.registerTool(createMemoryEventStatusTool(deps), nonOptional);
}
```
Sources: [integrations/openclaw/tools/index.ts:29-41](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/index.ts#L29-L41)

| Tool Name | Creating Function | Description / Purpose |
| :--- | :--- | :--- |
| `memory_search` | `createMemorySearchTool` | Retrieves memories relevant to a query using semantic search with rank ordering. |
| `memory_add` | `createMemoryAddTool` | Saves preferences, facts, decisions, rules, or technical notes to long-term memory. |
| `memory_get` | `createMemoryGetTool` | Fetches a single memory by exact ID to inspect its full content and metadata. |
| `memory_list` | `createMemoryListTool` | Lists all stored memories for auditing purposes without requiring a query string. |
| `memory_update` | `createMemoryUpdateTool` | Modifies an existing memory's text in-place while preserving its ID and update history. |
| `memory_delete` | `createMemoryDeleteTool` | Deletes memories via explicit ID, query search, or bulk deletion (`all: true`). |
| `memory_event_list` | `createMemoryEventListTool` | Lists recent background processing events from the platform backend. |
| `memory_event_status` | `createMemoryEventStatusTool` | Inspects status and telemetry of specific background memory processing events. |

Sources: [integrations/openclaw/tools/index.ts:5-12](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/index.ts#L5-L12), [integrations/openclaw/tools/memory-list.ts:9-11](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-list.ts#L9-L11), [integrations/openclaw/tools/memory-add.ts:11-14](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-add.ts#L11-L14), [integrations/openclaw/tools/memory-get.ts:8-10](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-get.ts#L8-L10), [integrations/openclaw/tools/memory-update.ts:9-11](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-update.ts#L9-L11), [integrations/openclaw/tools/memory-delete.ts:9-11](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-delete.ts#L9-L11), [integrations/openclaw/tools/memory-event-list.ts:6-9](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-event-list.ts#L6-L9)

### Search, Retrieval, and Listing Handlers

The `memory_search` tool accepts queries, result limits, scoping filters (`session`, `long-term`, `all`), categories, and advanced search metadata filters. When `scope` is set to `session`, it queries specifically against the current session's run ID; when set to `all`, it combines long-term results with session-scoped items while deduplicating records by memory ID.

```typescript
if (scope === "session") {
  if (currentSessionId) {
    results = await provider.search(query, applyFilters(buildSearchOptions(uid, limit, undefined, currentSessionId)));
  }
} else if (scope === "long-term") {
  results = await provider.search(query, applyFilters(buildSearchOptions(uid, limit)));
} else {
  const longTerm = await provider.search(query, applyFilters(buildSearchOptions(uid, limit)));
  let session: MemoryItem[] = [];
  if (currentSessionId) {
    session = await provider.search(query, applyFilters(buildSearchOptions(uid, limit, undefined, currentSessionId)));
  }
  const seen = new Set(longTerm.map((r) => r.id));
  results = [...longTerm, ...session.filter((r) => !seen.has(r.id))];
}
```
Sources: [integrations/openclaw/tools/memory-search.ts:49-63](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-search.ts#L49-L63)

The `memory_get` tool calls `provider.get(memoryId)` directly and formats the output with creation and update timestamps, whereas `memory_list` returns an itemized audit listing without semantic scoring.

```typescript
try {
  const memory = await provider.get(memoryId);
  deps.captureToolEvent("memory_get", { success: true, latency_ms: Date.now() - start });
  return {
    content: [{ type: "text", text: `Memory ${memory.id}:\n${memory.memory}\n\nCreated: ${memory.created_at ?? "unknown"}\nUpdated: ${memory.updated_at ?? "unknown"}` }],
    details: { memory },
  };
```
Sources: [integrations/openclaw/tools/memory-get.ts:18-24](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-get.ts#L18-L24), [integrations/openclaw/tools/memory-list.ts:33-43](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-list.ts#L33-L43)

> [!NOTE]
> `memory_list` de-duplicates entries when `scope` is `"all"` by collecting long-term results first and filtering out any session-scoped items sharing an existing record ID.
Sources: [integrations/openclaw/tools/memory-list.ts:37-43](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-list.ts#L37-L43)

### Storage, Mutation, and Deletion Safeguards

The `memory_add` tool supports single-fact strings or arrays of facts via the `facts` parameter. Before storage, incoming content passes through `stripNoiseFromContent` and `isNoiseMessage` validation filters.

```typescript
const allFacts = rawFacts
  .map((f) => stripNoiseFromContent(f))
  .filter((f) => f.length > 0 && !isNoiseMessage(f));

if (allFacts.length === 0) {
  return { content: [{ type: "text", text: "All provided facts were filtered as noise. Nothing stored." }], details: { error: "all_noise" } };
}
```
Sources: [integrations/openclaw/tools/memory-add.ts:38-44](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-add.ts#L38-L44)

Mutative tools implement strict safety guardrails. Both `memory_update` and `memory_delete` check `isSubagentSession(getCurrentSessionId())` upon execution and immediately reject requests made within ephemeral subagent sessions.

```typescript
if (isSubagentSession(getCurrentSessionId())) {
  return { content: [{ type: "text", text: "Memory update is not available in subagent sessions." }], details: { error: "subagent_blocked" } };
}
```
Sources: [integrations/openclaw/tools/memory-update.ts:21-23](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-update.ts#L21-L23), [integrations/openclaw/tools/memory-delete.ts:29-31](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-delete.ts#L29-L31)

> [!WARNING]
> Bulk memory deletion (`memory_delete` with `all: true`) requires both the `all: true` flag and explicit `confirm: true` parameters to proceed; otherwise, execution aborts and returns an error details payload.
Sources: [integrations/openclaw/tools/memory-delete.ts:58-61](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/tools/memory-delete.ts#L58-L61)

## Token-Budgeted Category-Ranked Recall Engine

### Query Sanitization and Vector Retrieval

The recall engine processes raw prompt inputs by stripping untrusted sender metadata prefixes and bracketed tags via `sanitizeQuery` before executing search operations. It then queries the memory provider using `SearchOptions` configured with an over-fetched `top_k` value of `maxMemories * 2` and a custom score threshold.

```typescript
export function sanitizeQuery(raw: string): string {
  let cleaned = raw.replace(
    /Sender\s*\(untrusted metadata\):\s*```json[\s\S]*?```\s*/gi,
    "",
  );
  cleaned = cleaned.replace(/^\[.*?\]\s*/g, "");
  cleaned = cleaned.trim();
  return cleaned || raw;
}

// ============================================================================
// Public API
// ============================================================================

/**
 * Perform token-budgeted, category-ranked recall.
 */
export async function recall(
  provider: Mem0Provider,
  query: string,
  userId: string,
  config: SkillsConfig = {},
  sessionId?: string,
): Promise<RecallResult> {
  const recallConfig = config.recall ?? {};
  const tokenBudget = recallConfig.tokenBudget ?? DEFAULT_TOKEN_BUDGET;
  const maxMemories = recallConfig.maxMemories ?? DEFAULT_MAX_MEMORIES;
  const threshold = recallConfig.threshold ?? DEFAULT_THRESHOLD;
  const categoryOrder = recallConfig.categoryOrder ?? DEFAULT_CATEGORY_ORDER;
  const identityAlwaysInclude = recallConfig.identityAlwaysInclude !== false;

  // Build search options (v3.0.0: keyword_search, reranking, filter_memories removed)
  const searchOpts: SearchOptions = {
    user_id: userId,
    top_k: maxMemories * 2, // Over-fetch for ranking
    threshold,
    source: "OPENCLAW",
  };

```
Sources: [integrations/openclaw/recall.ts:225-263](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L225-L263)

When a `sessionId` is present, the engine performs a secondary search against session memories using `run_id` filtering, and subsequently deduplicates any items already retrieved in the long-term memory set.

```typescript
// Search session memories if we have a session
let sessionMemories: MemoryItem[] = [];
if (sessionId) {
  try {
    sessionMemories = await provider.search(cleanQuery, {
      ...searchOpts,
      run_id: sessionId,
      top_k: 5,
    });
  } catch {
    // Session search failure is non-critical
  }
}

// Deduplicate: session memories that are also in long-term
const longTermIds = new Set(longTermMemories.map((m) => m.id));
const uniqueSession = sessionMemories.filter((m) => !longTermIds.has(m.id));

```
Sources: [integrations/openclaw/recall.ts:279-296](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L279-L296)

> [!NOTE]
> `sanitizeQuery` removes framework noise like sender metadata blocks and timestamps, leaving conversational query rewriting explicitly to the agent layer via its skill protocol.
Sources: [integrations/openclaw/recall.ts:219-224](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L219-L224)

### Category Ranking and Importance Defaults

Retrieved memories are categorized by inspecting item metadata categories or `mem0` extraction categories, falling back to `"uncategorized"`. Memories are sorted using a multi-tiered comparator that prioritizes category configuration order, falls back to importance scores, and resolves ties using search relevance.

```typescript
function getMemoryCategory(memory: MemoryItem): string {
  // Check metadata first (skill-stored memories have explicit category)
  if (
    memory.metadata?.category &&
    typeof memory.metadata.category === "string"
  ) {
    return memory.metadata.category;
  }
  // Check categories array (mem0-extracted memories)
  if (memory.categories?.length) {
    return memory.categories[0];
  }
  return "uncategorized";
}

function getMemoryImportance(memory: MemoryItem): number {
  if (
    memory.metadata?.importance &&
    typeof memory.metadata.importance === "number"
  ) {
    return memory.metadata.importance;
  }
  // Default importance by category
  const cat = getMemoryCategory(memory);
  const defaults: Record<string, number> = {
    identity: 0.95,
    configuration: 0.95,
    rule: 0.9,
    preference: 0.85,
    decision: 0.8,
    technical: 0.8,
    relationship: 0.75,
    project: 0.75,
    operational: 0.6,
  };
  return defaults[cat] ?? 0.5;
}
```
Sources: [integrations/openclaw/recall.ts:57-93](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L57-L93)

```typescript
function rankMemories(
  memories: MemoryItem[],
  categoryOrder: string[],
): MemoryItem[] {
  const orderMap = new Map(categoryOrder.map((cat, i) => [cat, i]));

  return [...memories].sort((a, b) => {
    const catA = getMemoryCategory(a);
    const catB = getMemoryCategory(b);
    const orderA = orderMap.get(catA) ?? 999;
    const orderB = orderMap.get(catB) ?? 999;

    // Primary sort: category priority
    if (orderA !== orderB) return orderA - orderB;

    // Secondary sort: importance (higher first)
    const impA = getMemoryImportance(a);
    const impB = getMemoryImportance(b);
    if (impA !== impB) return impB - impA;

    // Tertiary sort: search relevance score
    return (b.score ?? 0) - (a.score ?? 0);
  });
}
```
Sources: [integrations/openclaw/recall.ts:107-130](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L107-L130)

| Category Name | Default Importance | Category Priority Index |
| :--- | :--- | :--- |
| `identity` | `0.95` | `0` (Highest) |
| `configuration` | `0.95` | `1` |
| `rule` | `0.9` | `2` |
| `preference` | `0.85` | `3` |
| `decision` | `0.8` | `4` |
| `technical` | `0.8` | `5` |
| `relationship` | `0.75` | `6` |
| `project` | `0.75` | `7` |
| `operational` | `0.6` | `8` |

Sources: [integrations/openclaw/recall.ts:25-35](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L25-L35), [integrations/openclaw/recall.ts:81-91](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L81-L91)

### Token Budgeting and Formatting

The budgeting step iterates through ranked memories to select items under a configured character-derived token estimation (`CHARS_PER_TOKEN = 4`), respecting the `maxMemories` limit and token constraints.

```typescript
// Rough token estimate: ~4 chars per token for English text
const CHARS_PER_TOKEN = 4;
```
Sources: [integrations/openclaw/recall.ts:37-38](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L37-L38)

```typescript
function budgetMemories(
  rankedMemories: MemoryItem[],
  tokenBudget: number,
  maxMemories: number,
  identityAlwaysInclude: boolean,
): MemoryItem[] {
  const selected: MemoryItem[] = [];
  let usedTokens = 0;

  for (const memory of rankedMemories) {
    if (selected.length >= maxMemories) break;

    const memTokens = estimateTokens(memory.memory);
    const isIdentity =
      getMemoryCategory(memory) === "identity" ||
      getMemoryCategory(memory) === "configuration";

    // Identity/config always included if flag is set
    if (identityAlwaysInclude && isIdentity) {
      selected.push(memory);
      usedTokens += memTokens;
      continue;
    }

    // Budget check for non-identity memories
    if (usedTokens + memTokens > tokenBudget) continue;

    selected.push(memory);
    usedTokens += memTokens;
  }

  return selected;
}
```
Sources: [integrations/openclaw/recall.ts:136-168](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L136-L168)

> [!WARNING]
> When `identityAlwaysInclude` is enabled (default), items categorized under `identity` or `configuration` bypass the token budget ceiling and are unconditionally forced into the selected context set.
Sources: [integrations/openclaw/recall.ts:149-158](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L149-L158), [integrations/openclaw/recall.ts:254](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/recall.ts#L254)

## CLI Subcommands and Authentication Helpers

### Command Subsections and Configuration Persistence

The OpenClaw CLI registers subcommands under `openclaw mem0` to handle memory operations and plugin management. Management tasks include platform authentication (`init`), connectivity checks (`status`), and configuration queries (`config show`, `config get`, `config set`, `event list`, `event status`). 

```typescript
* Registers all `openclaw mem0 <subcommand>` commands:
*
* Memory:
*   - add         : Add a memory from text (--user-id, --agent-id)
*   - search      : Search memories (--top-k, --scope, --agent-id, --user-id)
*   - get         : Get a specific memory by ID
*   - list        : List memories with optional filters (--user-id, --agent-id, --top-k)
*   - update      : Update a memory's text
*   - delete      : Delete a memory or all memories (--all, --confirm)
*   - import      : Import memories from a JSON file
*
* Management:
*   - init        : Authenticate with Mem0 Platform (email or API key)
*   - status      : Check API connectivity and show current config
*   - config show : Display current plugin configuration
*   - config get  : Get a single config value
*   - config set  : Update a plugin config field
*   - event list  : List recent background events
*   - event status: Get status of a specific event
*
```
Sources: [integrations/openclaw/cli/commands.ts:4-23](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/commands.ts#L4-L23)

Configuration settings and authentication credentials are saved in `~/.openclaw/openclaw.json` under `plugins.entries.openclaw-mem0.config`. The filesystem operations rely on safe wrappers in `fs-safe.ts` to isolate file I/O from network calls and comply with security scanners.

```typescript
* Plugin auth and settings are stored in ~/.openclaw/openclaw.json under
* plugins.entries.openclaw-mem0.config — the single source of truth.
*
* Uses fs-safe.ts for all filesystem operations to pass the OpenClaw
* code_safety scanner.
*/
```
Sources: [integrations/openclaw/cli/config-file.ts:4-9](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L4-L9)

| Config Field | Type | Default Value | Purpose |
| :--- | :--- | :--- | :--- |
| `apiKey` | `string` | `undefined` | Platform authentication token |
| `baseUrl` | `string` | `https://api.mem0.ai` | Mem0 API base URL |
| `userId` | `string` | `undefined` | Default user identity scope |
| `userEmail` | `string` | `undefined` | Authenticated user email address |
| `mode` | `string` | `undefined` | Operating mode for the plugin |
| `autoRecall` | `boolean` | `undefined` | Automatically inject memories into prompts |
| `autoCapture` | `boolean` | `undefined` | Automatically extract and save memories |
| `topK` | `number` | `undefined` | Default retrieval count for searches |
| `anonymousTelemetryId` | `string` | `undefined` | Telemetry tracking identifier |
| `keyFingerprint` | `string` | `undefined` | SHA-256 prefix of the active API key |

Sources: [integrations/openclaw/cli/config-file.ts:28-40](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L28-L40), [integrations/openclaw/cli/config-file.ts:19](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L19)

> [!WARNING]
> `readFullConfig` throws an error on JSON parse failures. This fail-closed behavior prevents `writeFullConfig` from overwriting a corrupted config file with an empty state.
Sources: [integrations/openclaw/cli/config-file.ts:50-51](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L50-L51), [integrations/openclaw/cli/config-file.ts:70-77](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L70-L77)

### Credential Resolution and Execution Trace

When executing commands, configuration values and authentication states are resolved through a sequence of file checks. The execution walkthrough follows the exact verified call chain `registerCliCommands` → `readPluginAuth` → `readFullConfig` → `exists`. 

1. `registerCliCommands` starts command setup in `integrations/openclaw/cli/commands.ts`.
Sources: [integrations/openclaw/cli/commands.ts:398](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/commands.ts#L398)
2. `readPluginAuth` is called in `integrations/openclaw/cli/config-file.ts` to load stored credentials.
Sources: [integrations/openclaw/cli/config-file.ts:126-144](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L126-L144)
3. `readFullConfig` is invoked to read the persistent JSON config store.
Sources: [integrations/openclaw/cli/config-file.ts:52-78](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L52-L78)
4. `exists` checks whether `~/.openclaw/openclaw.json` exists on disk via `fs-safe.ts`.
Sources: [integrations/openclaw/fs-safe.ts:15-17](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/fs-safe.ts#L15-L17)

Similarly, when reading configuration text, the call trace flows from `registerCliCommands` → `readPluginAuth` → `readFullConfig` → `readText`:

1. `registerCliCommands` initializes command bindings.
Sources: [integrations/openclaw/cli/commands.ts:398](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/commands.ts#L398)
2. `readPluginAuth` calls `readFullConfig`.
Sources: [integrations/openclaw/cli/config-file.ts:126-144](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L126-L144)
3. `readFullConfig` calls `readText` to load file data.
Sources: [integrations/openclaw/cli/config-file.ts:52-78](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L52-L78)
4. `readText` reads the file as UTF-8 text via `fs-safe.ts`.
Sources: [integrations/openclaw/fs-safe.ts:10-12](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/fs-safe.ts#L10-L12)

```mermaid
sequenceDiagram
    autonumber
    participant commands.ts
    participant config-file.ts
    participant fs-safe.ts
    participant node:fs

    commands.ts->>config-file.ts: readPluginAuth()
    config-file.ts->>config-file.ts: readFullConfig()
    config-file.ts->>fs-safe.ts: exists(OPENCLAW_CONFIG_FILE)
    fs-safe.ts->>node:fs: fs.existsSync()
    node:fs--r->fs-safe.ts: boolean
    fs-safe.ts--r->config-file.ts: boolean
    config-file.ts->>fs-safe.ts: readText(OPENCLAW_CONFIG_FILE)
    fs-safe.ts->>node:fs: fs.readFileSync()
    node:fs--r->fs-safe.ts: string
    fs-safe.ts--r->config-file.ts: string
```
Sources: [integrations/openclaw/cli/commands.ts:398](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/commands.ts#L398), [integrations/openclaw/cli/config-file.ts:52-144](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L52-L144), [integrations/openclaw/fs-safe.ts:10-17](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/fs-safe.ts#L10-L17)

> [!TIP]
> `writeFullConfig` re-reads disk content immediately before writing to deep-merge OpenClaw-managed fields (`installs`, `slots`), preventing concurrent processes from clobbering gateway state.
Sources: [integrations/openclaw/cli/config-file.ts:87-116](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/config-file.ts#L87-L116)

## Interactive Open Source Setup Wizard

### OSS Provider Configurations and Builders

The OpenClaw setup wizard defines provider definitions, config builders, and flag validation logic in `integrations/openclaw/cli/oss-wizard.ts`. Three distinct categories of providers are supported: LLM providers, embedder providers, and vector store providers. Each provider definition specifies default models, URLs, API key requirements, and environment variables.

| Provider Category | Supported Identifiers | Default Model / Port | Key Requirements |
| :--- | :--- | :--- | :--- |
| LLM | `openai`, `ollama`, `anthropic` | `gpt-5-mini`, `llama3.1:8b`, `claude-sonnet-4-5-20250514` | Requires API key for OpenAI and Anthropic; `ollama` requires a base URL. |
| Embedder | `openai`, `ollama` | `text-embedding-3-small`, `nomic-embed-text` | Requires API key for OpenAI; `ollama` defaults to `http://localhost:11434`. |
| Vector Store | `qdrant`, `pgvector` | Ports `6333` (Qdrant) and `5432` (PostgreSQL) | `qdrant` configures `onDisk: true`; `pgvector` requires user, password, and database name. |

Sources: [integrations/openclaw/cli/oss-wizard.ts:25-52](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L25-L52)

Config builders process user inputs or command-line flags to assemble configuration objects. `buildOssLlmConfig` validates the provider ID against `LLM_PROVIDERS` and returns the provider name alongside a config record containing the selected model and optional API key or Ollama URL.
Sources: [integrations/openclaw/cli/oss-wizard.ts:78-93](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L78-L93)

```typescript
export function buildOssLlmConfig(
  providerId: string,
  input: LlmConfigInput,
): { provider: string; config: Record<string, unknown> } {
  const def = LLM_PROVIDERS.find((p) => p.id === providerId);
  if (!def) throw new Error(`Unknown LLM provider: ${providerId}`);

  const config: Record<string, unknown> = {
    model: input.model || def.defaultModel,
  };
  if (input.apiKey) config.apiKey = input.apiKey;
  if (providerId === "ollama") {
    config.url = input.url || def.defaultUrl;
  }
  return { provider: providerId, config };
}
```
Sources: [integrations/openclaw/cli/oss-wizard.ts:78-93](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L78-L93)

### Embedding Dimension Calculation and Vector Connectivity

Embedding dimensions are resolved dynamically using `KNOWN_EMBEDDER_DIMS` or fall back to the provider default dimensions. The collection name is derived using `collectionNameForDims`, which formats the dimension count into a standard string.
Sources: [integrations/openclaw/cli/oss-wizard.ts:54-66](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L54-L66)

```typescript
export const KNOWN_EMBEDDER_DIMS: Record<string, number> = {
  "text-embedding-3-small": 1536,
  "text-embedding-3-large": 3072,
  "text-embedding-ada-002": 1536,
  "nomic-embed-text": 768,
  "mxbai-embed-large": 1024,
  "all-minilm": 384,
  "snowflake-arctic-embed": 1024,
};

export function collectionNameForDims(dims: number): string {
  return `mem0_${dims}d`;
}
```
Sources: [integrations/openclaw/cli/oss-wizard.ts:54-66](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L54-L66)

`buildOssVectorConfig` assigns vector store parameters, setting `dimension`, `embeddingModelDims`, and the computed `collectionName` when dimensions are provided.
Sources: [integrations/openclaw/cli/oss-wizard.ts:131-155](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L131-L155)

```typescript
export function buildOssVectorConfig(
  providerId: string,
  input: VectorConfigInput,
): { provider: string; config: Record<string, unknown> } {
  const config: Record<string, unknown> = {};

  if (providerId === "qdrant") {
    config.url = input.url || "http://localhost:6333";
    config.onDisk = true;
    if (input.apiKey) config.apiKey = input.apiKey;
  } else if (providerId === "pgvector") {
    config.host = input.host || "localhost";
    config.port = parseInt(input.port || "5432", 10);
    if (input.user) config.user = input.user;
    if (input.password) config.password = input.password;
    config.dbname = input.dbname || "postgres";
  }

  if (input.dims) {
    config.dimension = input.dims;
    config.embeddingModelDims = input.dims;
    config.collectionName = collectionNameForDims(input.dims);
  }
  return { provider: providerId, config };
}
```
Sources: [integrations/openclaw/cli/oss-wizard.ts:131-155](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L131-L155)

Connectivity verification functions test network reachability with a 3000ms timeout. `checkOllamaConnectivity` pings `/api/tags`, `checkQdrantConnectivity` requests `/healthz`, and `checkPgConnectivity` attempts a TCP socket connection using `node:net`.
Sources: [integrations/openclaw/cli/oss-wizard.ts:157-186](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L157-L186)

```typescript
export async function checkOllamaConnectivity(url: string): Promise<{ ok: boolean; error?: string }> {
  try {
    const resp = await fetch(`${url.replace(/\/+$/, "")}/api/tags`, { signal: AbortSignal.timeout(3000) });
    if (resp.ok) return { ok: true };
    return { ok: false, error: `Ollama returned HTTP ${resp.status}` };
  } catch {
    return { ok: false, error: `Cannot reach Ollama at ${url}. Install: https://ollama.com/download` };
  }
}

export async function checkPgConnectivity(host: string, port: number): Promise<{ ok: boolean; error?: string }> {
  return new Promise((resolve) => {
    import("node:net").then(({ createConnection }) => {
      const sock = createConnection({ host, port, timeout: 3000 });
      sock.once("connect", () => { sock.destroy(); resolve({ ok: true }); });
      sock.once("timeout", () => { sock.destroy(); resolve({ ok: false, error: `PostgreSQL not reachable at ${host}:${port}` }); });
      sock.once("error", () => { sock.destroy(); resolve({ ok: false, error: `PostgreSQL not reachable at ${host}:${port}. Ensure PostgreSQL with pgvector extension is running.` }); });
    });
  });
}

export async function checkQdrantConnectivity(url: string): Promise<{ ok: boolean; error?: string }> {
  try {
    const resp = await fetch(`${url.replace(/\/+$/, "")}/healthz`, { signal: AbortSignal.timeout(3000) });
    if (resp.ok) return { ok: true };
    return { ok: false, error: `Qdrant returned HTTP ${resp.status}` };
  } catch (err) {
    return { ok: false, error: `Cannot reach Qdrant at ${url}. Start it with: docker run -d -p 6333:6333 qdrant/qdrant` };
  }
}
```
Sources: [integrations/openclaw/cli/oss-wizard.ts:157-186](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L157-L186)

> [!WARNING]
> `validateOssFlags` enforces strict parameter dependencies: if an LLM or embedder provider requires an API key (`needsApiKey`), omitting `--oss-llm-key` or `--oss-embedder-key` returns an immediate validation error. Similarly, configuring `pgvector` without specifying `--oss-vector-user` causes validation to fail.
Sources: [integrations/openclaw/cli/oss-wizard.ts:211-238](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/cli/oss-wizard.ts#L211-L238)

## Related

- [TypeScript Agent Core](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/agent-plugins/typescript-agent-core)
- [OpenCode Integration](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/agent-plugins/opencode-integration)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/llms.txt) for all pages in this wiki.
