npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agntz/memrez

v3.0.0

Published

Durable tagged memory layer for agntz agents

Readme

@agntz/memrez

Durable tagged memory for agntz agents.

memrez stores facts, preferences, events, and summaries under namespace scopes. It plugs into agntz through the generic resource provider system, so agents get memory tools such as memory_read and memory_write while application code keeps control of runtime namespace grants.

memrez owns memory organization, not the calling agent. The agent's memory_write takes content only — choosing the scope, topics, and entry type, normalizing the text, and detecting duplicates are all the reasoner's job. By default that reasoner is a built-in LLM (llmReasoner()), so memory handling is genuinely offloaded: the agent says what to remember, memrez decides how it's filed.

Install

pnpm add @agntz/memrez

The default reasoner makes direct model calls and reads its API key from the provider env var (e.g. OPENAI_API_KEY). A missing key throws on the first write; set one, or pass your own reasoner.

Use with the embedded SDK

Declare memory in an LLM agent:

id: support-with-memory
kind: llm
model:
  provider: openai
  name: gpt-5.4
instruction: |
  Help the user. Use memory when it is relevant.
resources:
  memory:
    mode: read-write
    autoScan: true

Wire the provider and pass trusted runtime grants:

import { agntz } from "@agntz/sdk";
import { createMemrez, SqliteMemoryStore } from "@agntz/memrez";

const memrez = createMemrez({
  store: new SqliteMemoryStore("./memory.db"),
});

const client = await agntz({
  agents: "./agents",
  resources: { memory: memrez.provider() },
});

await client.agents.run({
  agentId: "support-with-memory",
  input: "Remember that I prefer metric units.",
  context: ["app/user/" + userId],
});

context is a namespace grant array for resources. It is different from legacy contextIds scratchpad buckets.

Direct API

const grants = ["app/user/" + userId];

await memrez.write(grants, "Prefers metric units.", {
  topicsHint: ["preferences"],
});

const entries = await memrez.read(grants, "preferences", { limit: 10 });
const multi = await memrez.read(grants, ["preferences", "goals"]); // one call, deduped
const topics = await memrez.scan(grants);

// Deterministic full read — the viewer/audit primitive. Pass
// includeSuperseded to see supersession chains.
const everything = await memrez.list(grants);
const auditTrail = await memrez.list(grants, { includeSuperseded: true });

// Correct an entry: the replacement inherits scope/topics/type and the
// original is superseded (never edited in place), preserving the audit trail.
const { entry } = await memrez.correct(grants, staleEntryId, "Has dumbbells and a bench.");

Direct calls use the same grant validation as resource tool calls.

Stores

import {
  createMemrez,
  InMemoryMemoryStore,
  PostgresMemoryStore,
  SqliteMemoryStore,
} from "@agntz/memrez";

createMemrez({ store: new InMemoryMemoryStore() });
createMemrez({ store: new SqliteMemoryStore("./memory.db") });
createMemrez({ store: new PostgresMemoryStore(process.env.DATABASE_URL!) });

Use in-memory storage for tests, SQLite for local or single-node deployments, and Postgres for multi-process deployments.

Resource behavior

  • autoScan injects visible memory topic summaries into the model context before tool calls.
  • Topic taxonomy and reasoner policy belong to Memrez-level configuration, not the agent resource declaration.
  • preload inlines full entries at invoke time so agents don't burn a turn recalling obvious context. Omit it for no full-entry preload; use preload: true for core-only preload, or the object form below for precise control.
  • preload.limit caps the preloaded entries (default 50), preload.maxChars caps the rendered context (default 12000), and preload.types filters entry types. Overflow is noted to the model.
  • preload: all, preload: [goals, equipment], and legacy preloadLimit still work as shorthands, but the object form is preferred.
  • memory_read accepts one topic or a list of topics in a single call.
  • mode: read exposes read tools only.
  • mode: read-write exposes read and write tools.
  • The memory provider validates writes against runtime grants and writePolicy.
  • The model never receives a namespace parameter.
resources:
  memory:
    kind: memory
    mode: read-write
    autoScan: true
    preload:
      core: true
      topics: [goals, equipment]
      limit: 30
      maxChars: 10000
      types: [fact, preference, summary]

The reasoner

The reasoner is how memrez organizes memory. It has two jobs:

  • tag — runs on every write: pick the namespace from the grants, assign topics (reusing existing ones), classify the entry type, normalize the content, flag duplicates.
  • curate — runs on every curate: merge duplicates, reconcile contradictions, compact stale events into summaries, maintain topic blurbs.

createMemrez({ store }) uses llmReasoner() for both — direct model calls, no agntz client or runner involved, so memrez stays strictly below the agent layer (an agent's memory_write can never re-enter the agent platform). Override it only when you need different reasoner models or the explicit deterministic kill switch:

import {
  createMemrez,
  llmReasoner,
  DeterministicReasoner,
} from "@agntz/memrez";

// Default — built-in LLM reasoner, keyed from env. Customize the models:
createMemrez({ store, reasoner: llmReasoner({ taggerModel: { provider: "anthropic", name: "claude-haiku-4-5" } }) });

// Kill-switch / tests — no LLM. Files content under `general`; curate is a no-op:
createMemrez({ store, reasoner: new DeterministicReasoner() });

The agntz-agent-loop reasoner is deliberately not supported yet. Tagging and curation are bounded structured model calls owned by memrez; keeping them out of the agent loop avoids circular setups where an agent writes memory, memrez runs an agent, and that agent can see memory tools again.

The core topic

Importance is a topic convention the reasoner maintains, not schema. The built-in tagger files durable profile facts (equipment, schedule, goals, hard constraints) under the Memrez core topic alongside their subject topic — one entry, two topic rows. Today that topic is core; future Memrez-level config will own renaming it for applications that already use a different label such as profile.

preload.core: true loads that always-load set into the agent context. The curator promotes and demotes entries by rewriting replacement topics during curation, and the per-scope core blurb serves as a one-line profile in autoScan output. No schema change, no agent involvement — the writing agent just passes content.

Curation

memrez.curate(grants) reconciles a scope through the reasoner's curate step (the DeterministicReasoner has none, so it's a no-op there). The store tracks which (scope, topic) pairs have writes newer than their last curation pass: store.listDirtyTopics() enumerates them globally (the work-discovery primitive for curation crons), and scan() surfaces the per-topic hasUncuratedWrites flag. The hosted worker wires this up as POST /memory/curate plus an optional MEMREZ_CURATE_INTERVAL sweep.

See the public docs for the full guide: /docs/tools/memory-memrez.