Persistent, searchable memory for OpenClaw.
Your agent remembers every conversation, learns your preferences, and builds knowledge over timeβacross all your channels.
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
openclaw plugins install openclaw-penfieldopenclaw penfield loginTell your agent to "Awaken with Penfield"
Penfield is in free beta. Sign up for access:
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.
- 16 Memory Tools
- OAuth 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
- Context Management: Save and restore memory checkpoints
openclaw plugins install openclaw-penfieldgit clone https://github.com/penfieldlabs/openclaw-penfield.git
cd openclaw-penfield
npm install
npm run build
openclaw plugins install -l .The plugin is auto-enabled when loaded. No configuration required for production use.
The plugin uses OAuth 2.0 Device Code Flow (RFC 8628) with automatic token refresh.
openclaw penfield loginThis will:
- Discover OAuth endpoints from the auth server
- Register a dynamic client (DCR) if needed
- Display a device code for user authentication
- Poll for token completion
{
"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)
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"]
}Hybrid search using BM25 + vector + graph.
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 typesimportance_threshold(optional): Minimum importanceenable_graph_expansion(optional): Enable traversal (default: true)
Example:
{
"query": "programming preferences",
"limit": 10,
"vector_weight": 0.5,
"bm25_weight": 0.3,
"graph_weight": 0.2
}Semantic search variant (higher vector weight).
Parameters:
query(required): Search querylimit(optional): Max resultsmemory_types(optional): Filter by typesimportance_threshold(optional): Minimum importance
Get a specific memory by ID.
Parameters:
memory_id(required): Memory ID to fetch
Update an existing memory.
Parameters:
memory_id(required): Memory ID to updatecontent(optional): Updated contentmemory_type(optional): Updated typeimportance(optional): Updated importanceconfidence(optional): Updated confidencetags(optional): Updated tags
Create a relationship between two memories.
Parameters:
from_memory_id(required): Source memory IDto_memory_id(required): Target memory IDrelationship_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
}Traverse the knowledge graph from a starting memory.
Parameters:
start_memory_id(required): Starting memory IDmax_depth(optional): Max traversal depth (default: 3, max: 10)relationship_types(optional): Filter by relationship typesmin_strength(optional): Minimum relationship strength
Save a checkpoint of current memory state.
Parameters:
memory_ids(required): Array of memory IDs to savesession_id(optional): Session identifier
Restore a previously saved checkpoint.
Parameters:
checkpoint_id(required): Checkpoint ID to restorefull_restore(optional): Create new copies of memories instead of referencing existing (default: false)merge_mode(optional): How to handle conflicts - "append", "replace", or "smart_merge" (default: "append")
List all saved checkpoints.
Parameters:
session_id(optional): Filter by session IDlimit(optional): Max results (default: 20, max: 100)
Analyze memory patterns and generate insights.
Parameters:
time_window(optional): Time window - "1d", "7d", "30d", or "90d" (default: "7d")focus_areas(optional): Areas to analyze - "memory_usage", "relationships", "importance", "topics", "patterns"memory_types(optional): Filter by memory types - "fact", "insight", "conversation", "correction", "reference", "task", "checkpoint", "identity_core", "personality_trait", "relationship", "strategy"
Save a file artifact to Penfield storage.
Parameters:
path(required): Artifact path (e.g., "/project/file.txt")content(required): Artifact contentcontent_type(optional): MIME type (default: "text/plain")
Retrieve a file artifact from Penfield storage.
Parameters:
path(required): Artifact path to retrieve
List artifacts in a directory.
Parameters:
prefix(optional): Directory prefix (e.g., "/project/")limit(optional): Max results (default: 100, max: 1000)
Delete a file artifact from Penfield storage.
Parameters:
path(required): Artifact path to delete
Load personality configuration and identity core memories.
Parameters: None
// 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
});// 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
});// Save context
const checkpoint = await penfield_save_context({
memory_ids: ["mem_1", "mem_2", "mem_3"],
session_id: "session_123"
});
// Restore later
await penfield_restore_context({
checkpoint_id: checkpoint.id,
full_restore: true
});npm installnpm run typechecknpm run lint
npm run lint:fixnpm run format
npm run format:checknpm run buildindex.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
βββ auth-service.ts # Background OAuth token refresh service
βββ api-client.ts # HTTP client wrapper
βββ 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 (16 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
βββ 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
The plugin uses two services registered with OpenClaw:
-
penfield-auth: Background token refresh service
- Started when plugin loads
- Checks token expiry every 60 minutes
- Auto-refreshes if within 240-minute buffer
-
penfield: Runtime lifecycle service
- Manages runtime initialization
- Handles cleanup on shutdown
| Tool | Method | Endpoint |
|---|---|---|
| awaken | GET | /api/v2/personality/awakening |
| connect | POST | /api/v2/relationships |
| delete_artifact | DELETE | /api/v2/artifacts |
| explore | POST | /api/v2/relationships/traverse |
| fetch | GET | /api/v2/memories/{id} |
| list_artifacts | GET | /api/v2/artifacts/list |
| list_contexts | GET | /api/v2/checkpoint |
| recall | POST | /api/v2/search/hybrid |
| reflect | POST | /api/v2/analysis/reflect |
| restore_context | POST | /api/v2/checkpoint/{id}/recall |
| retrieve_artifact | GET | /api/v2/artifacts |
| save_artifact | POST | /api/v2/artifacts |
| save_context | POST | /api/v2/checkpoint/create |
| search | POST | /api/v2/search/hybrid |
| store | POST | /api/v2/memories |
| update_memory | PUT | /api/v2/memories/{id} |
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
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
- Automatic token refresh 240 minutes before expiry
- RFC 8628 compliant Device Code Flow
- All API calls use HTTPS
MIT
For issues or questions:
- GitHub Issues: https://github.com/penfieldlabs/openclaw-penfield/issues