|
1 | 1 | --- |
2 | 2 | sidebar_position: 11 |
3 | 3 | title: "Paperclip Persistent Memory with Hindsight | Integration Guide" |
4 | | -description: "Add long-term memory to Paperclip agents with Hindsight. Retain, recall, and reflect memories across sessions using the Paperclip integration." |
| 4 | +description: "Add long-term memory to all Paperclip agents with Hindsight. Install once as a plugin — every agent gets automatic recall before runs and retain after runs." |
5 | 5 | --- |
6 | 6 |
|
7 | 7 | # Paperclip |
8 | 8 |
|
9 | 9 | Persistent memory for [Paperclip AI](https://github.com/paperclipai/paperclip) agents using [Hindsight](https://hindsight.vectorize.io). |
10 | 10 |
|
11 | | -Paperclip agents start every heartbeat cold — no memory of prior sessions, decisions, or patterns. The `@vectorize-io/hindsight-paperclip` package gives them long-term memory that persists across heartbeats and sessions. |
| 11 | +Install the `@vectorize-io/hindsight-paperclip` plugin once. Every agent in your Paperclip instance automatically gets long-term memory that persists across runs, companies, and restarts — no code changes required. |
12 | 12 |
|
13 | | -## Quick Start |
| 13 | +## Installation |
14 | 14 |
|
15 | 15 | ```bash |
16 | | -npm install @vectorize-io/hindsight-paperclip |
| 16 | +pnpm paperclipai plugin install @vectorize-io/hindsight-paperclip |
17 | 17 | ``` |
18 | 18 |
|
19 | | -```typescript |
20 | | -import { recall, retain, loadConfig } from '@vectorize-io/hindsight-paperclip' |
21 | | - |
22 | | -const config = loadConfig() // reads HINDSIGHT_API_URL, HINDSIGHT_API_TOKEN |
23 | | - |
24 | | -// Before the heartbeat — inject context from prior sessions |
25 | | -const memories = await recall({ |
26 | | - companyId, |
27 | | - agentId, |
28 | | - query: `${task.title}\n${task.description}`, |
29 | | -}, config) |
30 | | - |
31 | | -if (memories) { |
32 | | - systemPrompt = `Past context:\n${memories}\n\n${systemPrompt}` |
33 | | -} |
34 | | - |
35 | | -// After the heartbeat — store what the agent did |
36 | | -await retain({ |
37 | | - companyId, |
38 | | - agentId, |
39 | | - content: agentOutput, |
40 | | - documentId: runId, |
41 | | -}, config) |
42 | | -``` |
| 19 | +Then configure in **Settings → Plugins → Hindsight Memory**. |
43 | 20 |
|
44 | | -Get an API key at [Hindsight Cloud](https://ui.hindsight.vectorize.io/signup). |
| 21 | +## Prerequisites |
45 | 22 |
|
46 | | -## How It Works |
| 23 | +Either: |
47 | 24 |
|
| 25 | +```bash |
| 26 | +# Self-hosted |
| 27 | +pip install hindsight-all |
| 28 | +export HINDSIGHT_API_LLM_API_KEY=your-openai-key |
| 29 | +hindsight-api |
48 | 30 | ``` |
49 | | -Paperclip Heartbeat |
50 | | - │ |
51 | | - ▼ |
52 | | - recall() ← Query Hindsight for prior context |
53 | | - │ |
54 | | - ▼ |
55 | | - Agent executes ← Prompt enriched with memories |
56 | | - │ |
57 | | - ▼ |
58 | | - retain() ← Store output for future heartbeats |
59 | | -``` |
60 | | - |
61 | | -Memory is isolated per company and agent by default (`paperclip::{companyId}::{agentId}`), matching Paperclip's multi-tenant model. |
62 | | - |
63 | | -## HTTP Adapter Integration |
64 | 31 |
|
65 | | -For agents running as HTTP webhook servers, use the Express middleware: |
| 32 | +Or [Hindsight Cloud](https://ui.hindsight.vectorize.io/signup) — no self-hosting required. |
66 | 33 |
|
67 | | -```typescript |
68 | | -import express from 'express' |
69 | | -import { createMemoryMiddleware, loadConfig } from '@vectorize-io/hindsight-paperclip' |
70 | | -import type { HindsightRequest } from '@vectorize-io/hindsight-paperclip' |
71 | | - |
72 | | -const app = express() |
73 | | -app.use(express.json()) |
74 | | -app.use(createMemoryMiddleware(loadConfig())) |
75 | | - |
76 | | -app.post('/heartbeat', async (req, res) => { |
77 | | - const { memories } = (req as HindsightRequest).hindsight |
78 | | - const { context } = req.body |
79 | | - |
80 | | - const prompt = memories |
81 | | - ? `Past context:\n${memories}\n\nCurrent task: ${context.taskDescription}` |
82 | | - : `Task: ${context.taskDescription}` |
| 34 | +## How It Works |
83 | 35 |
|
84 | | - const output = await runYourAgent(prompt) |
85 | | - res.json({ output }) // output is auto-retained by middleware |
86 | | -}) |
87 | 36 | ``` |
| 37 | +agent.run.started |
| 38 | + └─ recall(issueTitle + description) |
| 39 | + └─ cached in plugin state for this run |
88 | 40 |
|
89 | | -The middleware reads `agentId`, `companyId`, `runId`, and `context.taskDescription` from Paperclip's HTTP adapter request body, then auto-retains the agent's `output` field after each response. |
90 | | - |
91 | | -## Process Adapter Integration |
| 41 | +agent running… |
| 42 | + ├─ hindsight_recall(query) → returns cached context or live recall |
| 43 | + └─ hindsight_retain(content) → stores immediately |
92 | 44 |
|
93 | | -For agents running as scripts via Paperclip's Process adapter: |
94 | | - |
95 | | -```typescript |
96 | | -import { recall, retain, loadConfig } from '@vectorize-io/hindsight-paperclip' |
97 | | - |
98 | | -const config = loadConfig() |
99 | | -const { PAPERCLIP_AGENT_ID, PAPERCLIP_COMPANY_ID, PAPERCLIP_RUN_ID } = process.env |
100 | | - |
101 | | -const memories = await recall({ |
102 | | - agentId: PAPERCLIP_AGENT_ID!, |
103 | | - companyId: PAPERCLIP_COMPANY_ID!, |
104 | | - query: process.env.TASK_DESCRIPTION ?? '', |
105 | | -}, config) |
106 | | - |
107 | | -if (memories) { |
108 | | - console.log(`[Memory Context]\n${memories}`) |
109 | | -} |
110 | | - |
111 | | -// ... agent executes ... |
112 | | - |
113 | | -await retain({ |
114 | | - agentId: PAPERCLIP_AGENT_ID!, |
115 | | - companyId: PAPERCLIP_COMPANY_ID!, |
116 | | - content: agentOutput, |
117 | | - documentId: PAPERCLIP_RUN_ID!, |
118 | | -}, config) |
| 45 | +agent.run.finished |
| 46 | + └─ retain(output) → stored with runId as document_id |
119 | 47 | ``` |
120 | 48 |
|
121 | | -## Bank ID Isolation |
| 49 | +Memory is keyed to `companyId` + `agentId` — never to the run ID — so it accumulates across every run. |
122 | 50 |
|
123 | | -By default, each company+agent pair gets its own memory bank: |
124 | | - |
125 | | -| Setting | Bank ID format | |
126 | | -|---|---| |
127 | | -| Default | `paperclip::{companyId}::{agentId}` | |
128 | | -| Company-only | `paperclip::{companyId}` | |
129 | | -| Agent-only | `paperclip::{agentId}` | |
130 | | -| Custom prefix | `{prefix}::{companyId}::{agentId}` | |
| 51 | +## Configuration |
131 | 52 |
|
132 | | -```typescript |
133 | | -// Shared memory across all agents in a company |
134 | | -loadConfig({ bankGranularity: ['company'] }) |
| 53 | +| Field | Default | Description | |
| 54 | +|-------|---------|-------------| |
| 55 | +| `hindsightApiUrl` | `http://localhost:8888` | Hindsight server URL | |
| 56 | +| `hindsightApiKeyRef` | — | Paperclip secret name holding Hindsight Cloud API key | |
| 57 | +| `bankGranularity` | `["company", "agent"]` | Memory isolation: per company+agent, per company, or per agent | |
| 58 | +| `recallBudget` | `mid` | `low` = fastest, `mid` = balanced, `high` = most thorough | |
| 59 | +| `autoRetain` | `true` | Automatically retain run output after every run | |
135 | 60 |
|
136 | | -// Agent's global memory across all companies |
137 | | -loadConfig({ bankGranularity: ['agent'] }) |
| 61 | +## Bank ID Format |
138 | 62 |
|
139 | | -// Custom prefix |
140 | | -loadConfig({ bankIdPrefix: 'myapp' }) |
| 63 | +``` |
| 64 | +paperclip::{companyId}::{agentId} ← default (company + agent granularity) |
| 65 | +paperclip::{companyId} ← company granularity (shared across agents) |
| 66 | +paperclip::{agentId} ← agent granularity (agent memory across companies) |
141 | 67 | ``` |
142 | 68 |
|
143 | | -## Configuration |
| 69 | +## Agent Tools |
| 70 | + |
| 71 | +Agents can call these tools directly during a run: |
144 | 72 |
|
145 | | -| Option | Env Variable | Default | Description | |
146 | | -|---|---|---|---| |
147 | | -| `hindsightApiUrl` | `HINDSIGHT_API_URL` | Required | Hindsight server URL | |
148 | | -| `hindsightApiToken` | `HINDSIGHT_API_TOKEN` | — | API token for Hindsight Cloud | |
149 | | -| `bankGranularity` | — | `['company', 'agent']` | Which IDs to include in the bank ID | |
150 | | -| `bankIdPrefix` | — | `'paperclip'` | Prefix for bank IDs | |
151 | | -| `recallBudget` | — | `'mid'` | Search depth: `low`, `mid`, or `high` | |
152 | | -| `recallMaxTokens` | — | `1024` | Max tokens in recalled memory block | |
153 | | -| `retainContext` | — | `'paperclip'` | Provenance label stored with memories | |
154 | | -| `timeoutMs` | — | `15000` | Request timeout in milliseconds | |
| 73 | +**`hindsight_recall(query)`** — search memory for relevant context. Called automatically at run start; agents can also call it mid-run for targeted queries. |
155 | 74 |
|
156 | | -## Skill File |
| 75 | +**`hindsight_retain(content)`** — store a fact or decision immediately, without waiting for run end. |
157 | 76 |
|
158 | | -A markdown skill file is included at `src/skills/hindsight.md`. Inject it into your agent's system prompt to give the agent direct access to Hindsight's REST API via `curl` for mid-task recall and retention. |
| 77 | +## Adapter Compatibility |
159 | 78 |
|
160 | | -## Requirements |
| 79 | +Works with all Paperclip adapter types via the event system: |
161 | 80 |
|
162 | | -- Node.js 20+ (uses native `fetch`, no external HTTP dependencies) |
163 | | -- Hindsight server (self-hosted or [Hindsight Cloud](https://hindsight.vectorize.io)) |
| 81 | +| Adapter | Supported | |
| 82 | +|---------|-----------| |
| 83 | +| Claude | ✓ | |
| 84 | +| Codex | ✓ | |
| 85 | +| Cursor | ✓ | |
| 86 | +| HTTP | ✓ | |
| 87 | +| Process | ✓ | |
0 commit comments