@dial481

Penfield

Native OpenClaw plugin for Penfield memory integration

当前版本
v2.0.0
code-plugin社区source-linked

Penfield Memory for OpenClaw (openclaw-penfield)

npm version License: MIT

Persistent, searchable memory for OpenClaw.

Your agent remembers every conversation, learns your preferences, and builds knowledge over time—across all your channels.

What is this?

An OpenClaw plugin that connects your agent to Penfield, giving it:

  • Long-term memory — Conversations persist forever, not just one session
  • Semantic search — "What did I say about the Tokyo trip?" actually works
  • Knowledge graphs — Memories connect to memories, building real understanding
  • Cross-channel recall — Remember WhatsApp convos from Discord

Quick Start

openclaw plugins install openclaw-penfield
openclaw penfield login

Tell your agent to "Awaken with Penfield"

Get Access

Sign up for free trial access:

portal.penfield.app/sign-up

Features

Native OpenClaw plugin providing direct integration with Penfield's memory and knowledge graph API. This plugin offers 4-5x performance improvement over the MCP server approach by eliminating the mcporter → MCP → Penfield stack.

  • 17 Memory Tools
  • OAuth 2.1 Device Code Flow: Secure authentication following RFC 8628
  • Hybrid Search: BM25 + vector + graph search capabilities
  • Knowledge Graph: Build and traverse relationships between memories
  • Context Management: Save and restore memory checkpoints
  • Artifact Storage: Store and retrieve files in Penfield
  • Reflection & Analysis: Analyze memory patterns and generate insights

Installation

openclaw plugins install openclaw-penfield

From Source (for contributors)

git clone https://github.com/penfieldlabs/openclaw-penfield.git
cd openclaw-penfield
npm install
npm run build
openclaw plugins install -l .

Configuration

The plugin is auto-enabled when loaded. No configuration required for basic use.

Plugin Allowlist

OpenClaw recommends explicitly trusting non-bundled plugins. If you see plugins.allow is empty warnings on startup, add the plugin to your allowlist in openclaw.json:

{
  "plugins": {
    "allow": ["openclaw-penfield"]
  }
}

Once the allow array exists, future openclaw plugins install and openclaw plugins enable commands will automatically append to it.

Plugin Config

In openclaw.json under plugins.entries:

OptionTypeDefaultDescription
autoAwakenbooleantrueInject Penfield identity briefing on every agent turn
autoOrientbooleantrueInject recent Penfield memory context on every agent turn
authUrlstringhttps://auth.penfield.appAuth service URL
apiUrlstringhttps://api.penfield.appAPI URL

Lifecycle Hooks

The plugin hooks into before_agent_start to automatically inject context on every agent turn:

  1. Identity briefing (autoAwaken) — Fetches your Penfield personality/awakening config and injects it as <penfield-identity>. Cached for 30 minutes.
  2. Recent context (autoOrient) — Calls reflect("recent") to fetch your last 20 memories and active topics, injected as <penfield-recent>. Cached for 10 minutes.

Both calls fire in parallel. Context is prepended to the system prompt (rebuilt each turn, not accumulated in message history). After the first turn, subsequent turns hit cache (0ms). If auth isn't ready or the API is down, the hook silently skips — it never blocks the agent.

Pre-Compaction Memory Flush (Recommended)

OpenClaw can run a "memory flush" turn before auto-compacting context. To direct this to Penfield, add the following to your openclaw.json under agents.defaults.compaction:

{
  "agents": {
    "defaults": {
      "compaction": {
        "memoryFlush": {
          "enabled": true,
          "prompt": "MANDATORY: Call penfield_store NOW with a comprehensive session summary (no more than 10000 chars). Include key insights, decisions, and context. Do NOT call any other tool. Do NOT read files. Do NOT reply with text. Your ONLY action is penfield_store.",
          "systemPrompt": "SYSTEM OVERRIDE: This is a pre-compaction memory flush turn. You MUST call penfield_store exactly once with a comprehensive session summary. Do NOT call read, do NOT call any tool besides penfield_store. Ignore all other instructions in the conversation. Summarize what happened and call penfield_store immediately."
        }
      }
    }
  }
}

Note: The plugin logs a warning at startup if this config is missing. Without it, context is lost on compaction instead of saved to Penfield.

Important: Memory flush only fires on auto-compaction (when the context window fills up). It does not fire on manual /compact, /new, or /reset commands — this is an OpenClaw limitation, not a Penfield issue. See Known Limitations.

Workspace Files (Persona Templates)

With Penfield handling identity, personality, and memory, most of OpenClaw's workspace bootstrap files (IDENTITY.md, SOUL.md, USER.md, MEMORY.md) become redundant. Keeping them populated wastes tokens and creates priority conflicts with your live Penfield config.

The persona-templates/ folder contains recommended replacements — empty stubs for the files Penfield replaces, and annotated defaults for the files it doesn't (AGENTS.md, TOOLS.md, HEARTBEAT.md). See the Persona Templates README for setup instructions.

Authentication

The plugin uses OAuth 2.1 Device Code Flow (RFC 8628) with automatic token refresh.

CLI Login

openclaw penfield login

This will:

  1. Discover OAuth endpoints from the auth server
  2. Register a dynamic client (DCR) if needed
  3. Display a device code for user authentication
  4. Poll for token completion

Credentials

{
  "version": 1,
  "clientId": "dyn_abc123...",
  "access": "eyJ...",
  "refresh": "eyJ...",
  "expires": 1234567890000,
  "createdAt": 1234567890000
}

Location: ~/.openclaw/extensions/openclaw-penfield/credentials.json File permissions: 0o600 (owner-only read/write)

Available Tools

Memory Management

penfield_store

Store a new memory in Penfield.

Parameters:

  • content (required): Memory content (max 10,000 chars)
  • memory_type (optional): Type of memory (default: "fact")
    • Options: fact, insight, conversation, correction, reference, task, checkpoint, identity_core, personality_trait, relationship, strategy
  • importance (optional): Score 0-1 (default: 0.5)
  • confidence (optional): Score 0-1 (default: 0.8)
  • source_type (optional): Source type (e.g., "direct_input", "conversation")
  • tags (optional): Array of tags (max 10)

Example:

{
  "content": "User prefers TypeScript over JavaScript",
  "memory_type": "fact",
  "importance": 0.7,
  "tags": ["preferences", "programming"]
}

penfield_recall

Hybrid search using BM25 + vector + graph. Returns compact responses (essential fields only).

Parameters:

  • query (required): Search query (1-4,000 chars)
  • limit (optional): Max results (default: 20, max: 100)
  • bm25_weight (optional): Keyword weight (default: 0.4)
  • vector_weight (optional): Semantic weight (default: 0.4)
  • graph_weight (optional): Relationship weight (default: 0.2)
  • memory_types (optional): Filter by types
  • importance_threshold (optional): Minimum importance
  • enable_graph_expansion (optional): Enable traversal (default: true)
  • start_date (optional): Filter memories created on or after this date (ISO 8601, e.g. "2025-01-01")
  • end_date (optional): Filter memories created on or before this date (ISO 8601, e.g. "2025-12-31")
  • sort (optional): Sort order — "relevance" (default), "created_desc", or "created_asc"
  • max_content_length (optional): Truncate content to N characters (50-10,000). Full content available via penfield_fetch.

Example:

{
  "query": "programming preferences",
  "limit": 10,
  "vector_weight": 0.5,
  "bm25_weight": 0.3,
  "graph_weight": 0.2,
  "start_date": "2025-06-01"
}

penfield_search

Semantic search variant (higher vector weight). Returns compact responses (essential fields only).

Parameters:

  • query (required): Search query (1-4,000 chars)
  • limit (optional): Max results (default: 20, max: 100)
  • memory_types (optional): Filter by types
  • importance_threshold (optional): Minimum importance
  • start_date (optional): Filter memories created on or after this date (ISO 8601)
  • end_date (optional): Filter memories created on or before this date (ISO 8601)
  • sort (optional): Sort order — "relevance" (default), "created_desc", or "created_asc"
  • max_content_length (optional): Truncate content to N characters (50-10,000)

penfield_fetch

Get a specific memory by ID.

Parameters:

  • memory_id (required): Memory ID to fetch (UUID format)

penfield_update_memory

Update an existing memory.

Parameters:

  • memory_id (required): Memory ID to update (UUID format)
  • content (optional): Updated content
  • memory_type (optional): Updated type
  • importance (optional): Updated importance
  • confidence (optional): Updated confidence
  • tags (optional): Updated tags

Knowledge Graph

penfield_connect

Create a relationship between two memories.

Parameters:

  • from_memory_id (required): Source memory ID (UUID format)
  • to_memory_id (required): Target memory ID (UUID format)
  • relationship_type (required): Type of relationship
    • Knowledge Evolution: supersedes, updates, evolution_of
    • Evidence & Support: supports, contradicts, disputes
    • Hierarchy & Structure: parent_of, child_of, sibling_of, composed_of, part_of
    • Cause & Prerequisites: causes, influenced_by, prerequisite_for
    • Implementation & Testing: implements, documents, tests, example_of
    • Conversation & Attribution: responds_to, references, inspired_by
    • Sequence & Flow: follows, precedes
    • Dependencies: depends_on
  • strength (optional): Relationship strength 0-1 (default: 0.8)

Example:

{
  "from_memory_id": "22618318-8d82-49c9-8bb8-1cf3a61b3c75",
  "to_memory_id": "20413926-2446-4f88-bfd6-749b37969f34",
  "relationship_type": "supports",
  "strength": 0.9
}

penfield_disconnect

Remove a relationship between two memories.

Parameters:

  • from_memory_id (required): Source memory ID (UUID format)
  • to_memory_id (required): Target memory ID (UUID format)

Example:

{
  "from_memory_id": "22618318-8d82-49c9-8bb8-1cf3a61b3c75",
  "to_memory_id": "20413926-2446-4f88-bfd6-749b37969f34"
}

penfield_explore

Traverse the knowledge graph from a starting memory.

Parameters:

  • start_memory_id (required): Starting memory ID (UUID format)
  • max_depth (optional): Max traversal depth (default: 3, max: 10)
  • relationship_types (optional): Filter by relationship types
  • min_strength (optional): Minimum relationship strength

Context Management

penfield_save_context

Save a cognitive state checkpoint for handoff to another agent or future session.

Parameters:

  • name (required): Name for this context checkpoint (max 200 chars)
  • description (optional): Detailed cognitive handoff description with memory references (max 10,000 chars). Include what was investigated, key discoveries, current hypotheses, open questions, and suggested next steps. Use memory_id: <uuid> patterns for reliable memory linking.
  • memory_ids (optional): Explicit array of memory IDs to include in the checkpoint (UUID format)

Memory linking works three ways (combined, deduplicated):

  1. Explicit memory_ids parameter — always linked
  2. memory_id: <uuid> patterns extracted from description text — always linked
  3. Hybrid search using description as query — best-effort additional context

penfield_restore_context

Restore a previously saved context checkpoint by name, UUID, or "awakening" for personality briefing.

Parameters:

  • name (required): Name or ID of context to restore. Can be a context name (exact match), a context UUID, or "awakening" for personality briefing.
  • limit (optional): Maximum number of memories to restore (default: 20, max: 100)

penfield_list_contexts

List all saved context checkpoints.

Parameters:

  • limit (optional): Max results (default: 20, max: 100)
  • offset (optional): Number of results to skip for pagination (default: 0)
  • name_pattern (optional): Filter by name (case-insensitive substring match)
  • include_descriptions (optional): Include full descriptions (default: false)

Analysis

penfield_reflect

Analyze memory patterns and generate insights.

Parameters:

  • time_window (optional): Time period - "recent" (default), "today"/"1d", "week"/"7d", "month"/"30d", or "90d"
  • start_date (optional): Filter memories on or after this date (ISO 8601, e.g. "2025-01-01"). Overrides time_window.
  • end_date (optional): Filter memories on or before this date (ISO 8601, e.g. "2025-01-31"). Overrides time_window.
  • include_documents (optional): Include document chunks in analysis (default: false)

Artifact Storage

penfield_save_artifact

Save a file artifact to Penfield storage.

Parameters:

  • path (required): Artifact path (e.g., "/project/file.txt")
  • content (required): Artifact content
  • content_type (optional): MIME type (default: "text/plain")

penfield_retrieve_artifact

Retrieve a file artifact from Penfield storage.

Parameters:

  • path (required): Artifact path to retrieve

penfield_list_artifacts

List artifacts in a directory.

Parameters:

  • prefix (optional): Directory prefix (e.g., "/project/")
  • limit (optional): Max results (default: 100, max: 1000)

penfield_delete_artifact

Delete a file artifact from Penfield storage.

Parameters:

  • path (required): Artifact path to delete

Personality

penfield_awaken

Load personality configuration and identity core memories.

Parameters: None

Usage Examples

Basic Memory Storage and Retrieval

// Store a memory
await penfield_store({
  content: "User prefers dark mode for coding",
  memory_type: "fact",
  importance: 0.8,
  tags: ["preferences", "ui"]
});

// Recall memories
const results = await penfield_recall({
  query: "user interface preferences",
  limit: 5
});

Building Knowledge Graphs

// Store two related memories
const mem1 = await penfield_store({
  content: "TypeScript provides static typing",
  memory_type: "fact"
});

const mem2 = await penfield_store({
  content: "Static typing helps catch bugs early",
  memory_type: "insight"
});

// Connect them
await penfield_connect({
  from_memory_id: mem1.id,
  to_memory_id: mem2.id,
  relationship_type: "supports",
  strength: 0.9
});

// Explore the graph
const graph = await penfield_explore({
  start_memory_id: mem1.id,
  max_depth: 2
});

Context Checkpoints

// Save context with explicit memory IDs
const checkpoint = await penfield_save_context({
  name: "API investigation",
  description: "Investigated timeout issues in the payment API.\nmemory_id: 550e8400-e29b-41d4-a716-446655440000",
  memory_ids: ["550e8400-e29b-41d4-a716-446655440000", "6ba7b810-9dad-11d1-80b4-00c04fd430c8"]
});

// Restore later
await penfield_restore_context({
  name: "API investigation"
});

// Restore by UUID
await penfield_restore_context({
  name: "550e8400-e29b-41d4-a716-446655440000"
});

// Load personality briefing
await penfield_restore_context({
  name: "awakening"
});

Known Limitations

Memory flush only fires on auto-compaction

OpenClaw's memoryFlush config only triggers when the context window fills up and auto-compaction kicks in. The following commands bypass memory flush entirely:

  • /compact — compacts immediately, no flush
  • /new — resets session, no flush
  • /reset — resets session, no flush

This means context from shorter sessions (that never hit the auto-compaction threshold) won't be automatically saved to Penfield. To preserve important context before ending a session, tell your agent: "Save this session to Penfield before we end."

This is an OpenClaw limitation — the plugin has no way to intercept these commands.

Auto-compaction threshold

Auto-compaction triggers when token usage reaches approximately contextWindow - reserveTokensFloor - softThresholdTokens. With defaults (200K context, 20K reserve, 4K soft threshold), flush fires around 176K tokens (~88% full). You can tune softThresholdTokens in agents.defaults.compaction to trigger earlier.

Development

Setup

npm install

Type Check

npm run typecheck

Lint

npm run lint
npm run lint:fix

Format

npm run format
npm run format:check

Build

npm run build

Architecture

index.ts                     # Plugin entry point and registration
src/
├── config.ts                # Zod configuration schema with DEFAULT_AUTH_URL/DEFAULT_API_URL
├── types.ts                 # TypeScript type definitions (OpenClaw plugin API types)
├── types/typebox.ts         # Centralized TypeBox exports
├── hooks.ts                 # Lifecycle hooks (auto-awaken, auto-orient, flush config check)
├── auth-service.ts          # Background OAuth token refresh service
├── api-client.ts            # HTTP client wrapper
├── response-compact.ts      # Response compaction (mirrors MCP field-stripping)
├── runtime.ts               # Runtime factory (receives authService from index.ts)
├── store.ts                 # Credential file I/O with TOKEN_EXPIRY_BUFFER_MS
├── cli.ts                   # CLI command registration (penfield login)
├── device-flow.ts           # RFC 8628 Device Code Flow implementation
└── tools/
    ├── index.ts             # Tool registry (17 tools)
    ├── store.ts             # penfield_store
    ├── recall.ts            # penfield_recall
    ├── search.ts            # penfield_search
    ├── fetch.ts             # penfield_fetch
    ├── update-memory.ts     # penfield_update_memory
    ├── connect.ts           # penfield_connect
    ├── disconnect.ts        # penfield_disconnect
    ├── explore.ts           # penfield_explore
    ├── save-context.ts      # penfield_save_context
    ├── restore-context.ts   # penfield_restore_context
    ├── list-contexts.ts     # penfield_list_contexts
    ├── reflect.ts           # penfield_reflect
    ├── save-artifact.ts     # penfield_save_artifact
    ├── retrieve-artifact.ts # penfield_retrieve_artifact
    ├── list-artifacts.ts    # penfield_list_artifacts
    ├── delete-artifact.ts   # penfield_delete_artifact
    └── awaken.ts            # penfield_awaken

Service Lifecycle

The plugin uses two services and one hook registered with OpenClaw:

  1. penfield-auth: Background token refresh service

    • Started when plugin loads
    • Checks token expiry every 60 minutes
    • Auto-refreshes if within 240-minute buffer
  2. penfield: Runtime lifecycle service

    • Manages runtime initialization
    • Handles cleanup on shutdown
  3. before_agent_start hook: Context injection

    • Injects identity briefing + recent memories on every turn (cached)
    • Checks memory flush config at startup and warns if not configured for Penfield

API Endpoint Mapping

ToolMethodEndpoint
awakenGET/api/v2/personality/awakening
connectPOST/api/v2/relationships
disconnectDELETE/api/v2/relationships/between
delete_artifactDELETE/api/v2/artifacts
explorePOST/api/v2/relationships/traverse
fetchGET/api/v2/memories/{id}
list_artifactsGET/api/v2/artifacts/list
list_contextsGET/api/v2/memories?memory_type=checkpoint
recallPOST/api/v2/search/hybrid
reflectPOST/api/v2/analysis/reflect
restore_contextGET/api/v2/memories/{id}, /api/v2/memories?memory_type=checkpoint, /api/v2/personality/awakening
retrieve_artifactGET/api/v2/artifacts
save_artifactPOST/api/v2/artifacts
save_contextPOST/api/v2/memories (memory_type=checkpoint), /api/v2/search/hybrid
searchPOST/api/v2/search/hybrid
storePOST/api/v2/memories
update_memoryPUT/api/v2/memories/{id}

Error Handling

All tools return errors in a consistent format:

{
  "error": "Error message here"
}

Common errors:

  • 401 Unauthorized: Token expired or invalid (auto-refreshes)
  • 429 Rate Limited: Too many requests (includes retry-after header)
  • 500 Internal Server Error: API error

Performance

This native plugin provides significant performance improvements over the MCP server approach:

  • 4-5x faster: Direct HTTP calls vs. mcporter → MCP → Penfield
  • Lower latency: No intermediate proxy servers
  • Reduced overhead: Fewer serialization/deserialization steps
  • Auto token refresh: No re-authentication delays

Security

  • Automatic token refresh 240 minutes before expiry
  • RFC 8628 compliant Device Code Flow
  • All API calls use HTTPS

License

MIT

Support

For issues or questions:

源码与版本

源码仓库

penfieldlabs/openclaw-penfield

打开仓库

源码提交

ee50822

查看提交

安装命令

openclaw plugins install clawhub:openclaw-penfield

元数据

  • 包名: openclaw-penfield
  • 创建时间: 2026/04/14
  • 更新时间: 2026/04/14
  • 执行代码:
  • 源码标签: v2.0.0

兼容性

  • 构建于 OpenClaw: 2026.3.24
  • 插件 API 范围: >=2026.1.29
  • 标签: latest
  • 文件数: 97