Skip to content

paperclip: add sharedBankName config for cross-agent memory sharing#1589

Closed
SeBru1 wants to merge 1 commit into
vectorize-io:mainfrom
SeBru1:paperclip-shared-bank-name
Closed

paperclip: add sharedBankName config for cross-agent memory sharing#1589
SeBru1 wants to merge 1 commit into
vectorize-io:mainfrom
SeBru1:paperclip-shared-bank-name

Conversation

@SeBru1

@SeBru1 SeBru1 commented May 12, 2026

Copy link
Copy Markdown

Summary

Adds an optional sharedBankName string to the hindsight-integrations/paperclip plugin's instance config. When set, every agent in the company reads/writes the same Hindsight bank — overriding bankGranularity and the default paperclip::{companyId}::{agentId} derivation.

This is a small, additive, backwards-compatible change. No behavior changes for any existing install that doesn't set the new field.

Motivation

The current bankGranularity: [\"company\", \"agent\"] default isolates each agent's memory. That's the right default — memory shouldn't leak across unrelated agents.

But for multi-agent cohorts that need to collaborate on a shared pool of project context (e.g. a CEO/CTO/Staff/QA/Researcher team working a single backlog), there's no first-class way to point them at one bank.

Concrete use case: I run a 5-agent Paperclip company where each agent must see decisions, lessons, and project state created by the others. With current granularity, each agent talks to its own bank — hindsight_recall returns nothing the agent didn't write itself, and cross-agent compound knowledge never accrues.

Workarounds I considered:

  • bankGranularity: [\"company\"] collapses to a per-company bank — but the bank ID is still paperclip::{companyId}, which is fine for a single deployment but not when you want a human-readable bank name shared across companies or instances.
  • A wrapper plugin re-implementing the same logic against a fixed bank — significant maintenance cost for what's essentially a one-line override.

The cleanest fix is a tiny optional config override. That's this PR.

What changed

  • src/bank.ts: extend BankConfig with optional sharedBankName; deriveBankId returns the trimmed value verbatim when set, otherwise falls through to the existing granularity logic unchanged.
  • src/manifest.ts: add sharedBankName to instanceConfigSchema so it's configurable from Settings → Plugins → Hindsight Memory.
  • src/worker.ts: add the field to the internal PluginConfig type.
  • tests/plugin.spec.ts: 4 new tests — 3 unit tests for the override semantics (trimming, empty/whitespace fallthrough, normal override) + 1 integration test that verifies recall routes to the shared bank URL.
  • README.md: document the field and add a Shared bank for cross-agent collaboration section.

Backwards compatibility

The field is optional. Existing installs without sharedBankName keep the existing paperclip::{companyId}::{agentId} derivation untouched.

Test plan

  • npm run typecheck — clean
  • npm test — 19/19 tests pass (15 existing + 4 new)
  • npm run build — clean esbuild output
  • Verified locally against a 5-agent company: with sharedBankName: \"spool-farm\", recall/retain from all 5 agents now route to the single spool-farm bank.

Notes for review

Happy to adjust naming (sharedBankName vs bankName vs bankOverride), schema placement, or split into smaller commits if preferred. The full change is +89/-8 across 5 files.

Adds an optional `sharedBankName` string to the paperclip plugin's
instance config. When set, every agent in the company reads/writes
the same Hindsight bank — overriding `bankGranularity` and the
default `paperclip::{companyId}::{agentId}` derivation.

Why
---
The default `bankGranularity: ["company", "agent"]` isolates each
agent's memory. For multi-agent cohorts that need to collaborate on
a shared pool of project context (e.g. a CEO/CTO/Staff/QA/Researcher
team working a single backlog), there's no first-class way to point
them at a single bank without redefining identity.

What
----
- `src/bank.ts`: extend `BankConfig` with `sharedBankName?: string`;
  `deriveBankId` returns the trimmed value verbatim when set, falls
  through to the existing granularity logic otherwise.
- `src/manifest.ts`: surface `sharedBankName` in `instanceConfigSchema`
  so it's configurable from Settings → Plugins → Hindsight Memory.
- `src/worker.ts`: add the field to the internal `PluginConfig` type.
- `tests/plugin.spec.ts`: add unit tests for the override behavior
  (trimming, empty/whitespace fallthrough) and an integration-level
  test that verifies recall is routed to the shared bank URL when
  configured.
- README: document the field and add a "Shared bank for cross-agent
  collaboration" section.

Backwards compatible
--------------------
The field is optional. Existing installs (no `sharedBankName` set)
keep the existing `paperclip::{companyId}::{agentId}` derivation
unchanged. All 19 tests pass (3 pre-existing bank tests + 3 new bank
tests + 1 new worker-routing test + the rest of the suite).
@benfrank241

Copy link
Copy Markdown
Member

@SeBru1 thanks! Clean PR and the cross-agent collaboration case is legit. LGTM

@benfrank241

Copy link
Copy Markdown
Member

@SeBru1 — could you rename sharedBankName → bankId and add a dynamicBankId: boolean to match the pattern the other plugins use? same behavior, but a user moving between paperclip/ claude-code / openclaw would see the same field names mean the same thing. otherwise the implementation looks clean.

benfrank241 added a commit that referenced this pull request May 26, 2026
Add bankId and dynamicBankId config fields matching the pattern used
by openclaw, claude-code, and opencode. When bankId is set and
dynamicBankId is not true, all agents share the same bank — useful
for multi-agent cohorts that need collaborative memory.

- bank.ts: static override check before dynamic derivation
- manifest.ts: add dynamicBankId (boolean) and bankId (string) fields
- worker.ts: add fields to PluginConfig type
- tests: 5 new tests (static override, trimming, whitespace fallthrough,
  dynamicBankId=true bypass, integration routing)

Inspired by #1589 — thanks @SeBru1 for the original concept.
Closes #1589.
@benfrank241

Copy link
Copy Markdown
Member

@SeBru1 thanks for this — the shared-bank use case is exactly right, and the implementation was clean. we've folded it into #1761 with the naming change i mentioned (sharedBankName → bankId/dynamicBankId to match the convention across openclaw, claude-code, and opencode).

you're credited in both the commit and the PR description. if you spot anything off in #1761, feel free to comment there.

benfrank241 added a commit that referenced this pull request May 26, 2026
…1761)

* feat(paperclip): add per-user memory isolation via bankGranularity

Add 'user' as a bankGranularity option so each user gets their own
isolated memory bank. User identity is extracted from the specific
issue being worked on (via originId email or creatorEmail), not from
an arbitrary issue list query.

- bank.ts: add userId to BankContext, extractUserFromIssue() helper
- worker.ts: pass userId through all 4 bank-derivation sites, cache
  userId in plugin state so tool calls derive the same bank ID
- manifest.ts: add 'user' to bankGranularity enum
- tests: 6 new tests covering derivation, extraction, and integration

Inspired by #1561 — thanks @amirhmoradi for the original concept and
initial implementation.

* feat(paperclip): add bankId/dynamicBankId for static shared banks

Add bankId and dynamicBankId config fields matching the pattern used
by openclaw, claude-code, and opencode. When bankId is set and
dynamicBankId is not true, all agents share the same bank — useful
for multi-agent cohorts that need collaborative memory.

- bank.ts: static override check before dynamic derivation
- manifest.ts: add dynamicBankId (boolean) and bankId (string) fields
- worker.ts: add fields to PluginConfig type
- tests: 5 new tests (static override, trimming, whitespace fallthrough,
  dynamicBankId=true bypass, integration routing)

Inspired by #1589 — thanks @SeBru1 for the original concept.
Closes #1589.

* test(paperclip): add edge-case tests for bank feature interactions

19 additional tests covering:
- Feature interaction: static bankId vs user granularity precedence
- Static bankId edge cases: special chars, tabs/newlines, empty string
- Dynamic derivation edge cases: empty granularity, user-only, duplicates
- extractUserFromIssue: null fields, empty strings, multiple emails

* style(paperclip): fix lint formatting drift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants