---
title: "Pi Agent Plugin"
description: "The Pi Agent Plugin integrates Mem0's persistent semantic memory directly into the Pi Coding Agent, managing the extension lifecycle, request attribution, tool execution, interactive user commands,..."
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/pi-agent-plugin"
---

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

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

- [integrations/pi-agent-plugin/src/commands.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/commands.ts)
- [integrations/pi-agent-plugin/src/attribution.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/attribution.ts)
- [integrations/opencode-plugin/opencode-mem0.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/opencode-plugin/opencode-mem0.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/pi-agent-plugin/src/entry.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/entry.ts)
- [integrations/agent-plugin-core/python/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/memory_core.py)
- [integrations/mem0-agent-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/mem0-agent-plugin/core/memory_core.py)
- [integrations/antigravity-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/memory_core.py)
- [integrations/claude-code-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_core.py)
- [integrations/kimi-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/kimi-plugin/core/memory_core.py)
- [integrations/codex-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/codex-plugin/core/memory_core.py)
- [integrations/cursor-plugin/core/memory_core.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/cursor-plugin/core/memory_core.py)
- [integrations/pi-agent-plugin/src/prompt.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/prompt.ts)
- [cli/python/src/mem0_cli/output.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/cli/python/src/mem0_cli/output.py)
- [integrations/agent-plugin-core/python/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/mcp_server.py)
- [integrations/mem0-agent-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/mem0-agent-plugin/core/mcp_server.py)
- [integrations/pi-agent-plugin/src/memory/formatting.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/formatting.ts)
- [integrations/pi-agent-plugin/src/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/index.ts)
- [integrations/mem0-agent-plugin/core/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/mem0-agent-plugin/core/memory_cli.py)
- [integrations/claude-code-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/mcp_server.py)
- [integrations/antigravity-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/mcp_server.py)
- [integrations/agent-plugin-core/python/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/memory_cli.py)
- [cli/node/src/output.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/cli/node/src/output.ts)
- [integrations/kimi-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/kimi-plugin/core/mcp_server.py)
- [integrations/codex-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/codex-plugin/core/mcp_server.py)
- [integrations/antigravity-plugin/core/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/antigravity-plugin/core/memory_cli.py)
- [integrations/claude-code-plugin/core/memory_cli.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/claude-code-plugin/core/memory_cli.py)
- [integrations/agent-plugin-core/python/hook_runner.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/hook_runner.py)
- [integrations/cursor-plugin/core/mcp_server.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/cursor-plugin/core/mcp_server.py)
- [integrations/agent-plugin-core/python/telemetry.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/python/telemetry.py)
</details>

## Overview

The Pi Agent Plugin integrates Mem0's persistent semantic memory directly into the Pi Coding Agent, managing the extension lifecycle, request attribution, tool execution, interactive user commands, and context injection. Designed to maintain long-term memory across sessions, the plugin automatically binds workspace project scopes, applies client attribution headers, and injects relevant memory policies into the agent's startup stream.

## Extension Lifecycle and Startup Registration

### Initialization and Configuration Binding

The extension entry point exports a default function, `mem0Extension`, which accepts an `ExtensionAPI` instance from `@earendil-works/pi-coding-agent`. Execution begins by invoking `loadConfig()` to read settings from the environment or disk configuration paths. 

```typescript
export default function mem0Extension(pi: ExtensionAPI): void {
  const config = loadConfig();

  if (!config.apiKey) {
    console.warn("[mem0] No API key found. Set MEM0_API_KEY or add apiKey to ~/.pi/agent/mem0-config.json. Extension disabled.");
    return;
  }
```
Sources: [integrations/pi-agent-plugin/src/entry.ts:24-30](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/entry.ts#L24-L30)

If `config.apiKey` is absent, a warning message is emitted to the console and the initialization terminates immediately, disabling the extension without throwing an unhandled exception.

> [!WARNING]
> Omitting `MEM0_API_KEY` or failing to supply an `apiKey` in `~/.pi/agent/mem0-config.json` halts extension registration entirely, bypassing tool, command, and lifecycle event bindings.

Sources: [integrations/pi-agent-plugin/src/entry.ts:27-30](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/entry.ts#L27-L30)

### User ID Resolution Strategy

When initializing scope context, the plugin resolves the active user identifier through `resolveUserId(configUserId: string)`. The resolution sequence evaluates configuration overrides, environment variables, and system user data in a strict fallback order.

| Priority | Source | Condition | Fallback / Return Value |
| :--- | :--- | :--- | :--- |
| 1 | `configUserId` parameter | Non-empty string | Returns `configUserId` directly |
| 2 | `process.env.USER` | Environment variable is set | Returns `process.env.USER` |
| 3 | `process.env.USERNAME` | Environment variable is set | Returns `process.env.USERNAME` |
| 4 | `os.userInfo().username` | System call succeeds | Returns system username string |
| 5 | Catch block / Final default | System call throws error | Returns `"default"` |

```typescript
export function resolveUserId(configUserId: string): string {
  if (configUserId) return configUserId;
  if (process.env.USER) return process.env.USER;
  if (process.env.USERNAME) return process.env.USERNAME;
  try { return os.userInfo().username; } catch { return "default"; }
}
```
Sources: [integrations/pi-agent-plugin/src/entry.ts:17-22](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/entry.ts#L17-L22)

### Client Setup and Event Handlers

Once authenticated, the plugin instantiates a `MemoryClient` with the verified API key and decorates it using `applySurfaceHeaders(mem0)`. It constructs initial scope and telemetry contexts before registering memory tools, CLI commands, and auto-capture listeners.

```typescript
const mem0 = new MemoryClient({ apiKey: config.apiKey });
// Every path below shares this client: automatic recall, capture, the memory
// tools and deletion as well as the slash commands. Attribution belongs here
// rather than on individual calls, or everything except the commands reports
// as generic SDK traffic.
applySurfaceHeaders(mem0);

const scopeCtx: ScopeContext = {
  userId: resolveUserId(config.userId),
  appId: "",
  runId: "unknown",
};

function getScopeCtx(): ScopeContext {
  return scopeCtx;
}

const telemetryCtx = { apiKey: config.apiKey };
const lifecycle = createMemoryLifecycle();

// ── Register tool + commands + auto-capture ─────────────────────────
registerMemoryTool(pi, mem0, config, getScopeCtx, telemetryCtx);
registerCommands(pi, mem0, config, getScopeCtx, telemetryCtx);
setupAutoCapture(pi, mem0, config, getScopeCtx, telemetryCtx, lifecycle);

captureEvent("pi.plugin.registered", {
  auto_capture: config.autoCapture,
  default_scope: config.defaultScope,
}, telemetryCtx);

```
Sources: [integrations/pi-agent-plugin/src/entry.ts:32-61](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/entry.ts#L32-L61)

The extension binds to three primary host agent lifecycle events:

- `session_start`: Begins the [memory lifecycle](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/python-core/memory-lifecycle) session, detects the application ID from the current working directory (`ctx.cwd`), extracts the run ID from the session file, and optionally overrides the user ID if configured.
- `before_agent_start`: Appends the `MEMORY_POLICY` prompt instruction and performs guaranteed memory recall by querying the memory client using resolved search filters.
- `session_shutdown`: Captures telemetry events signaling the termination of the active session.

```typescript
// ── session_start: detect project + session, reconstruct scope ──────
pi.on("session_start", async (_event, ctx) => {
  lifecycle.beginSession();
  scopeCtx.appId = detectAppId(ctx.cwd);

  const sessionFile = ctx.sessionManager?.getSessionFile?.();
  scopeCtx.runId = detectRunId(sessionFile);

  if (config.userId) {
    scopeCtx.userId = config.userId;
  }

  captureEvent("pi.session.start", {}, telemetryCtx);
});

// ── before_agent_start: append memory policy and recall ─────────────
pi.on("before_agent_start", async (event, _ctx) => {
  let extra = MEMORY_POLICY;

  // Guaranteed retrieval: prefetch memories relevant to this prompt so the
  // agent always has them, rather than depending on it to call the tool.
  const recall = await lifecycle.recall(
    event.prompt ?? "",
    config.contextInjection,
    (q) => mem0.search(q, { filters: resolveSearchFilters("project", scopeCtx) }),
  );
  if (recall) extra += "\n\n" + recall;

  return {
    systemPrompt: (event.systemPrompt ?? "") + "\n\n" + extra,
  };
});

// ── session_shutdown ────────────────────────────────────────────────
pi.on("session_shutdown", async () => {
  captureEvent("pi.session.stop", {}, telemetryCtx);
});
```
Sources: [integrations/pi-agent-plugin/src/entry.ts:62-98](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/entry.ts#L62-L98)

## Surface Attribution and Request Headers

### Attribution Metadata and Stack Bounding

The Pi Agent Plugin decorates outbound requests through the `MemoryClient` instance to identify traffic originating from the extension. Surface identification constants declare the platform source and application identity, while package version resolution reads the plugin version dynamically from `package.json` with a fallback to `"unknown"`.

```typescript
export const PLATFORM_SOURCE = "PI_AGENT";

/** Host app the plugin runs inside. Allowlisted server-side. */
export const PLATFORM_APPLICATION = "pi";

const PLUGIN_VERSION = (() => {
  try {
    return JSON.parse(
      fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8"),
    ).version as string;
  } catch {
    return "unknown";
  }
})();
```
Sources: [integrations/pi-agent-plugin/src/attribution.ts:5-18](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/attribution.ts#L5-L18)

To track client call chains without fragmenting client identifiers, `boundedStack` appends the plugin's client string while enforcing strict capacity constraints. It limits the stack to a maximum of 4 entries and 200 total characters by dropping whole entries rather than slicing strings mid-identifier.

> [!WARNING]
> Slicing client header strings would sever identifiers and leave malformed fragments that the platform parses as autonomous client names. Bounding drops entire entries to preserve token integrity.

Sources: [integrations/pi-agent-plugin/src/attribution.ts:20-40](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/attribution.ts:20-40](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/attribution.ts:20-40))

### Request Header Application

The `applySurfaceHeaders` function stamps surface identity parameters onto the shared `MemoryClient` headers object once during extension startup. Setting headers directly on the client instance ensures that automatic recall, memory capture, tool executions, and deletions all transmit attribution metadata.

| Header Name | Configuration Rule | Value / Behavior |
| :--- | :--- | :--- |
| `X-Mem0-Source` | Set-once if empty or whitespace | `PLATFORM_SOURCE` (`"PI_AGENT"`) |
| `X-Application` | Set-once if empty or whitespace | `PLATFORM_APPLICATION` (`"pi"`) |
| `X-Mem0-Client` | Append-only stack | `mem0-pi-agent/${PLUGIN_VERSION}` bounded by `boundedStack` |

```typescript
export function applySurfaceHeaders(client: MemoryClient): void {
  const headers = client.headers as Record<string, string>;
  if (!headers["X-Mem0-Source"]?.trim()) headers["X-Mem0-Source"] = PLATFORM_SOURCE;
  if (!headers["X-Application"]?.trim()) headers["X-Application"] = PLATFORM_APPLICATION;

  const existing = (headers["X-Mem0-Client"] ?? "")
    .split(",")
    .map((part) => part.trim())
    .filter(Boolean);
  headers["X-Mem0-Client"] = boundedStack(existing, `mem0-pi-agent/${PLUGIN_VERSION}`);
}
```
Sources: [integrations/pi-agent-plugin/src/attribution.ts:55-65](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/attribution.ts#L55-L65)

## Interactive User Commands and Diagnostics

### Command Registration and Memory Manipulation

The plugin registers interactive commands via the `ExtensionAPI` interface to allow developers to manually store, search, delete, and browse memories directly within the terminal interface. Each command validates user input, resolves scope filters, interacts with the `MemoryClient`, and dispatches structured feedback messages to the UI.

| Command Name | Description | Required Arguments | Underlying Action |
| :--- | :--- | :--- | :--- |
| `/mem0-remember` | Store a memory verbatim (no inference) | Text string | `mem0.add([{ role: "user", content: text }], { infer: false, ... })` |
| `/mem0-forget` | Delete memories matching a natural language query | Natural language query | `searchMemories(query)` followed by `mem0.delete(target.id)` |
| `/mem0-search` | Semantic search across memories | Search query | `mem0.search(query, { filters, threshold, topK: 10, rerank: true })` |
| `/mem0-tour` | Browse all memories grouped by category | Optional scope (`project`, `session`, `global`) | `mem0.getAll({ filters })` |

```typescript
pi.registerCommand("mem0-remember", {
  description: "Store a memory verbatim (no inference)",
  handler: async (args, ctx) => {
    const text = args?.trim();
    if (!text) {
      ctx.ui.notify("Usage: /mem0-remember <text>", "warning");
      return;
    }

    const addParams = resolveAddParams(config.defaultScope, getScopeCtx());
    const result = await mem0.add(
      [{ role: "user", content: text }],
      { ...addParams, customCategories: DEFAULT_CUSTOM_CATEGORIES, infer: false, source: PLATFORM_SOURCE },
    );
    captureCommandEvent("mem0-remember", {}, telemetryCtx);

    const storedItems = (Array.isArray(result) ? result : [])
      .map((m) => (m as { memory?: string }).memory)
      .filter((m): m is string => Boolean(m));
    const items = storedItems.length > 0 ? storedItems : [text];
    sendFeedback(
      "mem0-remember",
      [`**Stored to ${config.defaultScope} memory**`, ...items.map((m) => `- ${m}`)].join("\n"),
    );
  },
});
```
Sources: [integrations/pi-agent-plugin/src/commands.ts:48-73](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/commands.ts#L48-L73)

> [!NOTE]
> The search helper explicitly injects `source: PLATFORM_SOURCE` and `rerank: true` into the `SearchMemoryOptions` parameter block while utilizing a fixed top-K ceiling of 10.
> 
> Sources: [integrations/pi-agent-plugin/src/commands.ts:32-46](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/commands.ts#L32-L46)

### Deletion and Browsing Workflows

When a user invokes `/mem0-forget`, the command searches for matching memories using the default scope. If multiple matching records are returned, the plugin invokes `ctx.ui.select` to present compact formatted labels so the developer can pick the exact record to remove. If a single match is found, it triggers a confirmation prompt via `ctx.ui.confirm` before executing the deletion.

```typescript
pi.registerCommand("mem0-forget", {
  description: "Delete memories matching a natural language query",
  handler: async (args, ctx) => {
    const query = args?.trim();
    if (!query) {
      ctx.ui.notify("Usage: /mem0-forget <query>", "warning");
      return;
    }

    const memories = await searchMemories(query, config.defaultScope);

    if (memories.length === 0) {
      captureCommandEvent("mem0-forget", { result_count: 0 }, telemetryCtx);
      sendFeedback("mem0-forget", `**No matches for "${query}"** — nothing to forget.`);
      return;
    }

    const forgotten = (mem: Parameters<typeof formatMemoryCompact>[0]) => {
      captureCommandEvent("mem0-forget", { deleted_count: 1 }, telemetryCtx);
      sendFeedback(
        "mem0-forget",
        [`**Forgotten from ${config.defaultScope} memory**`, `- ${formatMemoryCompact(mem)}`].join("\n"),
      );
    };

    if (memories.length === 1) {
      const target = memories[0];
      const confirmed = await ctx.ui.confirm("Delete this memory?", formatMemoryCompact(target));
      if (!confirmed) {
        sendFeedback("mem0-forget", "**Cancelled** — no memories deleted.");
        return;
      }
      await mem0.delete(target.id);
      forgotten(target);
      return;
    }

    const labels = memories.map((m) => formatMemoryCompact(m));
    const selected = await ctx.ui.select(
      `Found ${pluralize(memories.length, "match", "matches")} for "${query}" — which should I delete?`,
      labels,
    );
    if (!selected) {
      sendFeedback("mem0-forget", "**Cancelled** — no memories deleted.");
      return;
    }
    const idx = labels.indexOf(selected);
    if (idx < 0) return;
    const target = memories[idx];
    await mem0.delete(target.id);
    forgotten(target);
  },
});
```
Sources: [integrations/pi-agent-plugin/src/commands.ts:75-127](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/commands.ts#L75-L127)

The `/mem0-tour` command accepts an optional scope argument (`project`, `session`, or `global`). If omitted, it falls back to `config.defaultScope`. It validates the raw input against permitted scope strings, retrieves all records matching the scope filters, groups them by category, and sends formatted output to the telemetry and UI streams.

```typescript
pi.registerCommand("mem0-tour", {
  description: "Browse all memories grouped by category",
  handler: async (args, ctx) => {
    const raw = args?.trim().toLowerCase();
    const validScopes: Scope[] = ["project", "session", "global"];
    if (raw && !validScopes.includes(raw as Scope)) {
      ctx.ui.notify(`Invalid scope "${raw}". Must be one of: ${validScopes.join(", ")}`, "warning");
      return;
    }
    const scope: Scope = (raw as Scope) || config.defaultScope;
    const filters = resolveSearchFilters(scope, getScopeCtx());
    const result = await mem0.getAll({ filters });
    const memories = result.results ?? [];

    if (memories.length === 0) {
      captureCommandEvent("mem0-tour", { memory_count: 0, scope }, telemetryCtx);
```
Sources: [integrations/pi-agent-plugin/src/commands.ts:157-172](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/commands.ts#L157-L172)

## Tool Execution and Agent Guidance

### Tool Registration and Parameter Schema

The plugin registers the `mem0_memory` tool through the `registerMemoryTool` function, exposing six specific memory actions to the agent. Parameter validation relies on TypeBox schema definitions and `StringEnum` types that govern valid operation inputs and scoping.

| Parameter Name | Type | Allowed Values / Description |
| :--- | :--- | :--- |
| `action` | StringEnum | `"search"`, `"add"`, `"get_all"`, `"update"`, `"delete"`, `"delete_all"` |
| `query` | String | Search text required for action `"search"` |
| `content` | String | Memory text required for actions `"add"` and `"update"` |
| `memory_id` | String | Target memory ID required for actions `"update"` and `"delete"` |
| `scope` | StringEnum | `"project"`, `"session"`, `"global"` |

```typescript
parameters: Type.Object({
  action: StringEnum(
    [
      "search",
      "add",
      "get_all",
      "update",
      "delete",
      "delete_all",
    ] as const,
    {
      description:
        "Memory operation to run: \"search\" (semantic recall of earlier work in this repository), \"add\" (save a new fact/preference/decision), \"get_all\" (list everything in scope, no query needed), \"update\" (replace an existing memory's text by id), \"delete\" (remove one memory by id), \"delete_all\" (wipe every memory in the scope -- destructive, only on explicit request).",
    },
  ),
  query: Type.Optional(
    Type.String({
      description:
        `Search text -- required for action "search". ${SEARCH_QUERY_DESCRIPTION}`,
    }),
  ),
  content: Type.Optional(
    Type.String({
      description:
        "Memory text -- required for action \"add\" (the fact to store) and \"update\" (the replacement text).",
    }),
  ),
  memory_id: Type.Optional(
    Type.String({
      description:
        "Target memory's ID -- required for \"update\" and \"delete\". Use an ID returned by a prior \"search\" or \"get_all\".",
    }),
  ),
  scope: Type.Optional(
    StringEnum(["project", "session", "global"] as const, {
      description:
        "Where to read/write: \"project\" (default -- this repo), \"session\" (this run only), or \"global\" (across ALL projects; only when the user explicitly wants cross-project recall). Omit for normal queries.",
    }),
  ),
}),
```
Sources: [integrations/pi-agent-plugin/src/memory/tools.ts:157-196](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L157-L196)

> [!WARNING]
> Action `delete_all` wipes every memory within the specified scope. Because this operation is destructive, execution requires explicit user authorization and must never be triggered implicitly by standard agent autonomy routines.
> 
> Sources: [integrations/pi-agent-plugin/src/memory/tools.ts:124-132](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L124-L132), [integrations/pi-agent-plugin/src/memory/tools.ts:169-170](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L169-L170)

### Execution Dispatch and Output Limits

The `buildToolExecute` factory returns an asynchronous handler that processes tool parameters, checks abort signals, resolves tool scopes, and dispatches calls to the underlying `MemoryClient`. Tool outputs are bound by strict output length constraints to protect agent context windows.

| Constraint Constant | Threshold Value | Enforcement Behavior |
| :--- | :--- | :--- |
| `MAX_OUTPUT_LINES` | 200 lines | Truncates lists exceeding line count |
| `MAX_OUTPUT_BYTES` | 50,000 bytes | Truncates string length exceeding byte limit |

```typescript
const MAX_OUTPUT_LINES = 200;
const MAX_OUTPUT_BYTES = 50_000;

function normalizeMemoryId(id: string): string {
  return id.replace(/^\[?mem0:([0-9a-f-]{36})\]?$/i, "$1");
}

function truncateOutput(text: string): string {
  const lines = text.split("\n");
  if (lines.length <= MAX_OUTPUT_LINES && text.length <= MAX_OUTPUT_BYTES) {
    return text;
  }

  const kept = lines.slice(0, MAX_OUTPUT_LINES);
  let result = kept.join("\n");
  if (result.length > MAX_OUTPUT_BYTES) {
    result = result.slice(0, MAX_OUTPUT_BYTES);
  }

  const dropped = lines.length - kept.length;
  if (dropped > 0 || text.length > MAX_OUTPUT_BYTES) {
    result += `\n\n[Output truncated: showing ${kept.length} of ${lines.length} lines]`;
  }
  return result;
}
```
Sources: [integrations/pi-agent-plugin/src/memory/tools.ts:19-43](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L19-L43)

Memory identifiers returned by search results or passed to updates are automatically normalized via `normalizeMemoryId`, which strips bracketed wrappers like `[mem0:uuid]` down to raw UUID strings. Telemetry wrappers track execution latency, success status, and result match counts across all tool invocations.

```typescript
function normalizeMemoryId(id: string): string {
  return id.replace(/^\[?mem0:([0-9a-f-]{36})\]?$/i, "$1");
}
```
Sources: [integrations/pi-agent-plugin/src/memory/tools.ts:22-24](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L22-L24), [integrations/pi-agent-plugin/src/memory/tools.ts:200-218](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L200-L218)

> [!NOTE]
> Tool execution checks `signal?.aborted` at the start of actions such as `search`, `add`, and `delete_all`, throwing an immediate `"Cancelled"` error if the asynchronous operation is aborted.
> 
> Sources: [integrations/pi-agent-plugin/src/memory/tools.ts:63](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L63), [integrations/pi-agent-plugin/src/memory/tools.ts:75](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L75), [integrations/pi-agent-plugin/src/memory/tools.ts:125](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L125)

### Agent Prompt Cues and Scoping Guidance

The plugin provides system prompt policies via `MEMORY_POLICY` and explicit prompt guidelines inside tool registrations to instruct the agent on proactive memory storage and proper scope selection.

```typescript
export const MEMORY_POLICY = `<mem0-memory-policy>
You have persistent semantic memory via the mem0_memory tool, powered by Mem0. Relevant memories may be auto-injected under <mem0-relevant-memories>.

Use mem0_memory with action "search" ${SEARCH_WHEN}.

Be proactive about saving:
- Save important facts, preferences, goals, decisions, lessons learned, identity, relationships, and routines the user shares.

Scope (do not change unless explicitly asked):
- "project" (default): memories for this project — use for all normal queries
- "session": memories from this session only
- "global": all memories across projects — ONLY when the user explicitly asks for cross-project search

Memory persists across sessions and devices via Mem0's cloud.
</mem0-memory-policy>`;
```
Sources: [integrations/pi-agent-plugin/src/prompt.ts:3-17](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/prompt.ts#L3-L17)

The agent is instructed to use the `"project"` scope by default for all normal queries, restricting `"global"` cross-project searches strictly to instances where the user has explicitly requested it. Normal queries omit the scope parameter entirely to let the system fall back to the project default automatically.

```typescript
"Always use the default project scope unless the user EXPLICITLY asks to search across all projects — only after the user selects /mem0-scope global use scope \"global\"",
"Do NOT pass scope at all for normal queries — omitting it uses the project default automatically",
```
Sources: [integrations/pi-agent-plugin/src/memory/tools.ts:154-155](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/tools.ts#L154-L155)

## Memory Formatting and Age Representation

### Presentation Formats and List Renderers

The Pi agent plugin delegates memory formatting, prose rendering, and age duration calculations directly to shared helpers provided by the core TypeScript agent library [TypeScript Agent Core](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/agent-plugins/typescript-agent-core). The local `formatting.ts` module re-exports `formatAge`, `formatMemoryCompact`, `formatMemoryList`, and `groupByCategory` alongside the `MemoryLike` interface type.

```typescript
export {
  formatAge,
  formatMemoryCompact,
  formatMemoryList,
  groupByCategory,
} from "../../../agent-plugin-core/typescript/src/formatting.ts";
```
Sources: [integrations/pi-agent-plugin/src/memory/formatting.ts:1-6](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/formatting.ts#L1-L6)

Memories are rendered in different presentation structures depending on whether they appear in compact dialog selections, user command feedbacks, or structured multi-item lists. Compact representations format single memories for command prompts, confirmations, and deletion feedback workflows, whereas list formats organize multiple retrieved entries into structured Markdown outputs. When browsing memories via commands like `/mem0-tour`, `groupByCategory` sorts and aggregates memories into categorized sections using default custom categories.

```typescript
import { formatMemoryList, formatMemoryCompact, groupByCategory } from "./memory/formatting.ts";
```
Sources: [integrations/pi-agent-plugin/src/commands.ts:7](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/commands.ts#L7), [integrations/pi-agent-plugin/src/commands.ts:92-97](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/commands.ts#L92-L97)

> [!NOTE]
> Formatting functions rely on the underlying `MemoryLike` schema definition to extract properties such as memory content, creation timestamps, and category groupings without coupling directly to specific platform transport schemas.
> 
> Sources: [integrations/pi-agent-plugin/src/memory/formatting.ts:1-6](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/pi-agent-plugin/src/memory/formatting.ts#L1-L6)

## Related

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


## Sitemap

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