fleet-memory/hindsight-integrations/paperclip
Derek Bouius 3b9d2db091
security: bump vite across integrations (high CVE fix) (#913)
* security: bump vite across integrations to patched versions

Fixes Dependabot alerts for vite transitive dev dependency:
- GHSA-v2wj-q39q-566r (high): server.fs.deny bypass with queries
- GHSA-p9ff-h696-f583 (high): related vite server vulnerability

Adds a `vite` entry to the npm `overrides` in each integration's
package.json to force the patched version (>=8.0.5). To make this
possible in ai-sdk, chat, and openclaw — which pinned vitest ^4.0.18
whose vite peer is `^6.0.0 || ^7.0.0` — the minor-compatible bump
vitest ^4.0.18 -> ^4.1.2 is also included. vitest 4.1.x supports
vite 8.x (peer: ^6 || ^7 || ^8), so all six integrations converge on
vite 8.x consistently.

paperclip had no overrides block; one was added.

Verified locally: `npm ci && npx vitest run` passes in all six
integrations (ai-sdk 23, chat 28, openclaw 66, opencode 89, paperclip 27,
nemoclaw 36 tests).

* chore: regenerate hindsight-docs skill

Picks up FAQ and best-practice sections added in #905 that were not
regenerated at merge time, so that `verify-generated-files` passes
for this branch.
2026-04-08 09:11:21 +02:00
..
src fix(paperclip): address review fixes for paperclip integration (#900) 2026-04-07 09:32:24 +02:00
tests fix(paperclip): address review fixes for paperclip integration (#900) 2026-04-07 09:32:24 +02:00
package-lock.json security: bump vite across integrations (high CVE fix) (#913) 2026-04-08 09:11:21 +02:00
package.json security: bump vite across integrations (high CVE fix) (#913) 2026-04-08 09:11:21 +02:00
README.md feat(paperclip): add hindsight-paperclip TypeScript integration (#773) 2026-04-02 14:26:45 +02:00
tsconfig.json fix(paperclip): address review fixes for paperclip integration (#900) 2026-04-07 09:32:24 +02:00

@vectorize-io/hindsight-paperclip

Persistent memory for Paperclip AI agents using Hindsight.

Paperclip agents start every heartbeat cold — no memory of prior sessions, decisions, or patterns. This package gives them long-term memory that persists across heartbeats and sessions.

How It Works

  1. Before each heartbeat: recall() queries Hindsight for context relevant to the current task and injects it into the agent's prompt
  2. After each heartbeat: retain() stores the agent's output so future heartbeats can reference it

Memory is isolated per company and agent by default (paperclip::{companyId}::{agentId}), matching Paperclip's multi-tenant model.

Installation

npm install @vectorize-io/hindsight-paperclip

Configuration

Set environment variables (or pass as options to loadConfig()):

Variable Description Default
HINDSIGHT_API_URL Hindsight server URL Required
HINDSIGHT_API_TOKEN API token for Hindsight Cloud

Usage

HTTP Adapter Agents (Express middleware)

import express from 'express'
import { createMemoryMiddleware, loadConfig } from '@vectorize-io/hindsight-paperclip'
import type { HindsightRequest } from '@vectorize-io/hindsight-paperclip'

const app = express()
app.use(express.json())
app.use(createMemoryMiddleware(loadConfig()))

app.post('/heartbeat', async (req, res) => {
  const { memories, runId } = (req as HindsightRequest).hindsight
  const { context } = req.body

  const prompt = memories
    ? `Past context:\n${memories}\n\nCurrent task: ${context.taskDescription}`
    : `Task: ${context.taskDescription}`

  const output = await runYourAgent(prompt)
  res.json({ output })  // middleware auto-retains output
})

The middleware reads agentId, companyId, runId, and context.taskDescription from the Paperclip HTTP adapter request body automatically.

Process Adapter Scripts

import { recall, retain, loadConfig } from '@vectorize-io/hindsight-paperclip'

const config = loadConfig()
const { PAPERCLIP_AGENT_ID, PAPERCLIP_COMPANY_ID, PAPERCLIP_RUN_ID } = process.env

// Recall before executing
const memories = await recall({
  agentId: PAPERCLIP_AGENT_ID!,
  companyId: PAPERCLIP_COMPANY_ID!,
  query: process.env.TASK_DESCRIPTION ?? '',
}, config)

if (memories) {
  console.log(`[Memory Context]\n${memories}`)
}

// ... agent does its work ...

// Retain after
await retain({
  agentId: PAPERCLIP_AGENT_ID!,
  companyId: PAPERCLIP_COMPANY_ID!,
  content: agentOutput,
  documentId: PAPERCLIP_RUN_ID!,
}, config)

Direct Function Usage

import { recall, retain, loadConfig } from '@vectorize-io/hindsight-paperclip'

const config = loadConfig({
  hindsightApiUrl: 'https://api.hindsight.vectorize.io',
  hindsightApiToken: process.env.HINDSIGHT_API_TOKEN,
})

const memories = await recall(
  { companyId, agentId, query: `${task.title}\n${task.description}` },
  config
)

if (memories) {
  systemPrompt = `Past context:\n${memories}\n\n${systemPrompt}`
}

Bank ID Isolation

By default, each company+agent pair gets its own memory bank:

paperclip::{companyId}::{agentId}

You can change the isolation granularity:

// Shared memory across all agents in a company
loadConfig({ bankGranularity: ['company'] })
// → "paperclip::{companyId}"

// Agent's global memory across all companies
loadConfig({ bankGranularity: ['agent'] })
// → "paperclip::{agentId}"

// Custom prefix
loadConfig({ bankIdPrefix: 'myapp' })
// → "myapp::{companyId}::{agentId}"

Configuration Reference

interface PaperclipMemoryConfig {
  hindsightApiUrl: string          // HINDSIGHT_API_URL — required
  hindsightApiToken?: string       // HINDSIGHT_API_TOKEN
  bankGranularity?: ('company' | 'agent')[]  // default: ['company', 'agent']
  bankIdPrefix?: string            // default: 'paperclip'
  recallBudget?: 'low' | 'mid' | 'high'      // default: 'mid'
  recallMaxTokens?: number         // default: 1024
  retainContext?: string           // default: 'paperclip'
  timeoutMs?: number               // default: 15000
}

Skill File

An agent-readable skill file is included at src/skills/hindsight.md. Inject it into your agent's system prompt or as a Paperclip skill to give the agent direct access to Hindsight's REST API via curl.

Requirements

  • Node.js 20+ (uses native fetch)
  • Hindsight server (self-hosted or Hindsight Cloud)