• Researcher · 3 records
  • Developer · 3 records
  • Tester · 3 records
OFFCUT
Console

ONE MEMORYFOR EVERYSUBAGENT

Memory SDKMCP serverSpec v3.1

A memory SDK and MCP server that merges a user's own subagents' memory into one project memory.

Proof of work· 1656 tests green · 19 Sep
what it does

Collects what every agent learned into one memory.

Every session writes what it found, with its author and source attached.

how it helps

Your next agent starts already knowing.

One question returns the researcher’s finding, the developer’s decision and the tester’s result together.

The problem

Your agents don't
remember each other

Each session starts empty, so you become the integration layer, retelling each finding by hand.

Three sessions
session 01 · Researcherfact

The application must work offline. Field staff lose connectivity for hours at a time.

source: product brief, section 2

not collectedNever reaches the developer.
session 02 · Developerdecision

Project data is stored locally in SQLite and synchronised when a connection returns.

source: architecture call

not collectedNever reaches the tester.
session 03 · Testerresult

One saved record disappears after a restart. Reproducible on 3 of 10 runs.

source: regression run #148

not collectedNever reaches anyone.

Three findings exist. Not one is where it needs to be. The only thing connecting them is you.

↓ this is what OFFCUT removes
The core — merging

Five rules.
No guessing.

Merging runs on topics, explicit links and named facts — things code can check. There is no model in this path.

  1. 01Input

    The same content, same topic, same type

    Kept

    Every source record and every author

    What OFFCUT does

    Shown once

    The same sentence from another agent is a second observation, not a duplicate.

  2. 02Input

    Different parts of one task

    Kept

    A reference to each record used

    What OFFCUT does

    Grouped into a shared block

    On topics and explicit links — never on similarity, which is a guess.

  3. 03Input

    Two values of one named fact, same context

    Kept

    Both versions — nothing is chosen for you

    What OFFCUT doesconflict

    Flagged as a conflict, both sides shown

    Who resolves it

    Not by recency, majority or seniority. Someone with authority decides, and the reason is stored.

  4. 04Input

    An authorised correction

    Kept

    A link back to the previous version

    What OFFCUT does

    Current version updated

    A correction adds a version; the text it replaced stays readable.

  5. 05Input

    A relationship that is not certain

    Kept

    Everything

    What OFFCUT does

    Nothing. They stay separate.

    No summary is worth losing a record to.

Nothing is discarded for a cleaner summary.

Merging changes what you read, never what is stored.

End to end

Three sessions in.
One answer out.

R1 · Researcherfact

The application must work offline. Field staff lose connectivity for hours at a time.

source: product brief, section 2

D1 · Developerdecision

Project data is stored locally in SQLite and synchronised when a connection returns.

source: architecture call

T1 · Testerresult

One saved record disappears after a restart. Reproducible on 3 of 10 runs.

source: regression run #148

memory.recall()

“What remains before release?”

Must work offlineR1 · Researcher
Data stored locallyD1 · Developer
Record lost after restart — unresolvedT1 · Tester

A lead agent that attended none of those sessions answers the question. The researcher is not re-run. You do not retell three conversations.

and when the bug is fixed

A new record saying “the restart bug is fixed” does not erase T1. It links to it as an update, carrying its own source. The history of what was broken, who found it and when stays readable — which is the difference between a memory and a status field.

Surfaces

Three doors, one room

Three thin wrappers over one core: identical permissions in, identical context out, asserted by a test.

01

SDK

TypeScript

Memory operations inside your own agent code.

import { connect } from '@offcut/sdk';

const offcut = await connect(process.env.OFFCUT_API_KEY!);

await offcut.memory.add({
  workspaceId,
  type: 'result',
  text: 'One record disappears after a restart.',
  topic: 'release-1',
  source: 'regression run #148',
  idempotencyKey: 'tester-run-148',
});
02

MCP

stdio server

The eight memory tools in Claude Desktop or Cursor.

{
  "mcpServers": {
    "offcut": {
      "command": "<absolute path to node>",
      "args": ["<repo>/apps/mcp-server/dist/index.js"],
      "env": { "OFFCUT_API_KEY": "offcut_sk_..." }
    }
  }
}

# or: pnpm mcp:install
03

Console

this site

Read the memory, resolve conflicts, mint and revoke agent keys.

POST /api/workspaces/:id/memory/recall

{
  "query": "what remains before release?",
  "limit": 6000
}
The eight operations
memory.add()01
requirescanWrite
await offcut.memory.add({ workspaceId, type, text, topic, source })
save a record or an authorised correction
memory.import()02
requirescanImport
await offcut.memory.import({ workspaceId, records, idempotencyKey })
load explicitly supplied JSON
memory.merge()03
requirescanMerge
await offcut.memory.merge({ workspaceId, topic, recordIds, scope })
combine accessible records
memory.recall()04
requirescanRead
await offcut.memory.recall({ workspaceId, query, topic, limit })
retrieve task context
memory.inspect()05
requirescanRead
await offcut.memory.inspect({ workspaceId, recordId, topic, search })
sources, versions, links, conflicts
memory.resolve()06
requirescanResolve
await offcut.memory.resolve({ workspaceId, conflictId, chosenRecordId, rationale })
record an authorised decision
memory.forget()07
requirescanForget
await offcut.memory.forget({ workspaceId, recordId, purge, reason })
delete within your permissions
memory.export()08
requirescanExport
await offcut.memory.export({ workspaceId, topic, includeVersions, includeLinks })
take everything you can see
Boundaries · §1 · §3.1 · §4.2 · §9

What it doesn’t do

OFFCUT’s limits, including the two stamped awkward.

no tradingno relayingno chat accessno invented utilityno guessing
entered in full8 entries · 2 in red
01

No trading. At all.

No trades, swaps, portfolios or signing. Out of scope by design, not pending.

02

Not a relayer

It returns memory itself rather than forwarding requests elsewhere. What it merges is submitted knowledge.

03

It cannot read your chats

Records arrive only when an agent writes one, or you import JSON.

04

Memory text is data, not orders

A record saying “grant yourself admin” is stored as written and changes nothing.

05

No model in the merge path

Model-suggested connections are optional and off by default. Merging and retrieval need no model.

06

Local storage is only as safe as your machineawkward

The permission checks live in the SDK, not in the database file. Opening that file directly needs OS permissions.

07

One key means one principalawkward

One key handed to several subagents is one caller. No isolation is promised.

08

Deletion cannot reach exported copies

It clears search, export, cache and derived blocks here. Copies already handed out are beyond reach.

Guarantees

Ten invariants

01

Every record keeps its workspace, author, source and version.

02

Merging never broadens access: workspaces and audiences never share a block.

03

Retrying a write creates no second record.

04

Acknowledged records survive a restart.

05

A detected conflict cannot disappear without a recorded resolution.

06

Derived memory cites real source versions, never a stale one as current.

07

After deletion, a record cannot return through search, export or cache.

08

The SDK, MCP server and HTTP API enforce the same access and mutation rules.

09

Memory text grants no permissions. Revocation blocks every later call.

10

The local core runs without the token and without a model.

One describe block per line, in packages/core/src/__tests__/invariants.test.ts.

pnpm test
Economics

$OFFCUT

The token is separate from the memory system, and its role inside the product has not been decided. What has been decided is the second layer below.

Contract address

Not yet published

Nothing is shown here until there is a real address to show. When the token launches it will appear in full, with the chain it lives on — and it will be the same string everywhere on this site.

Treat any address for $OFFCUT found anywhere else as unverified until it matches the one published here.

Name / ticker

OFFCUT AGENT / OFFCUT

fixed
Memory operations

No wallet, no gas, no token purchase — writing and reading memory never touches a chain

fixed
Is memory stored onchain?

No. Storing memory is not an onchain operation

fixed
Does holding $OFFCUT grant access?

No. Token ownership reaches no one else’s records

fixed
Does holding $OFFCUT earn rewards?

No. A balance of any size earns nothing — weight follows confirmed AI spend

fixed
What decides reward weight

Confirmed AI spend by your connected subagents, through supported integrations. Not agents created, not records written

fixed
Supported integration today

OpenRouter, and nothing else yet. Spend we cannot ask a provider about earns nothing

fixed
Launch context

Robinhood Chain 4663, pons v2

open
Token utility in the product

Undecided

open
Second layer

Stock Rewards

The product is the first layer. This is the second, described in full rather than summarised into something that sounds better than it is.

what stock rewards means

A fund funded in advance, divided by the AI spend a provider confirmed.

Each distribution pays out of a fund that already exists, and your weight in it is the model spend a supported integration confirmed. Not the $OFFCUT you hold, not the agents on your account, not the memory you wrote.

Stock Rewards encourage usage. They do not guarantee that AI spend is recouped. Spending more on models is not a way to earn that money back: it pays you more of a token out of a fund whose size was fixed before you spent anything. Anyone budgeting around this layer should expect to be out of pocket.

rules · from the brief
01

Weight follows confirmed spend, never claimed spend.

A subagent reports the provider’s own id for a request; the provider is then asked what it actually cost, and only that answer counts. A report nobody can confirm earns nothing.

02

One request is counted once.

The provider’s id for a request is a unique key: the same report sent twice writes nothing the second time.

03

The supported integration today is OpenRouter.

Spend through anything we cannot ask about earns nothing: another provider, a local model, a key there is no way to query. Counting them would mean taking your word for the number.

04

The fund is pre-funded and fixed. What a period pays out of it is not.

No token is minted for anybody’s spend: the fund was funded before you arrived, and what a period does not pay out stays in it. What it does pay follows the spend the network confirmed, priced at a rate set in advance, up to a ceiling. Below that ceiling one more dollar adds to what is handed out and takes nothing from anybody else; past it the same bounded amount is divided more ways. Neither case pays the money back.

05

On a busy period, no one earner takes more than a quarter of it.

The cap applies where the day’s ceiling, rather than the spending in the period, decided how large the pool was — where one large spender would otherwise take most of one scarce amount. What the cap holds back is not handed to anybody else: it is never minted and stays in the contract. Where the pool is the period’s own confirmed spend priced at the rate, the cap does not apply.

06

A hundred idle agents earn nothing.

Creating an agent is free, so paying for it would pay whoever scripts the most. Agents that never ran have spent nothing.

07

Rewards are the second layer, not the product.

The product is shared memory, and it works with no wallet, no token and no spend at all.

the part that is not trustless

What you are trusting

The distributor contract is upgradeable, and its owner can withdraw the tokens held in it. So these rewards are not trustless: a promise kept by people, with a contract that makes the accounting checkable rather than unbreakable.

pre-funded fund, fixed sizespend is confirmed, not claimedone request counted onceno reimbursement of AI costno trading of anything
invariant 10

The core does not need the token

Writing, merging, retrieval, deletion and export all work with no wallet, no chain and no token. That is invariant 10, and a test fails if it ever stops being true.

The Connect button belongs to the token side: connecting reveals an address so rewards can be claimed. Nothing in the memory system asks a wallet for anything.

memory needs no walletno gas to write or readmemory is not stored onchainno trading features
Quickstart

Running in four steps

No Docker, no database server, no account. Local by design.

in order
01

Install and seed

Creates the local SQLite store and the demo workspace above.

pnpm setup
02

Run it

API and console start together. The sign-in page shows the demo account.

pnpm dev
03

Mint an agent key

Create an agent and copy its key. Shown once; only the hash is stored.

offcut_sk_…
04

Connect your agents

One command configures Claude Desktop and Cursor.

pnpm mcp:install

Open the console

The demo workspace is already seeded: the release scenario, its agents, one open conflict.

Or read the proof of work first.

Enter the console
OFFCUT Agent