Skip to main content

n1mem · N1Mem 记忆 API Python SDK

powered by T1Mem engine · BYOK(自带 Key)· 同步零硬依赖

给 Agent 一个长期记忆后端:写入即可召回,召回基于命中记忆接地; 并且能把你已有的 Agent 记忆(身份文件 / 技能库 / 关键文档)一次性迁进来。

安装

pip install n1mem            # 同步版,零硬依赖(仅标准库)
pip install n1mem[async]     # 需要异步客户端时(依赖 httpx)

10 行代码跑通

from n1mem import N1Mem

m = N1Mem(api_key="tk_xxx")        # 或设环境变量 N1MEM_API_KEY 后不传参

print(m.health())                  # 服务健康 + provider 可用性
m.ingest("我今天换了新工位,在 3 楼靠窗")
print(m.recall("我坐哪儿"))
print(m.list_memories(limit=5))    # 看看存进去了什么

迁移:把已有 Agent 记忆导进来

n1mem.importers 在你本机把记忆资产枚举成条目(不上传原始目录结构), 再由 ingest_batch() 分批提交。全程离线可复现,不依赖服务端读你的磁盘。

from n1mem import N1Mem
from n1mem.importers import WorkBuddyAdapter

m = N1Mem(api_key="tk_xxx")
ad = WorkBuddyAdapter()                    # 默认导入身份层 + 技能层

plan = ad.plan(ad.enumerate())             # 先看要导什么,再决定导不导
r = m.ingest_batch(plan, source_id=ad.source_id)
print(r["inserted"], r["source_id"])

# 反悔:按批次整体撤销(被删内容会进 tombstone,防止同内容被后续导入"复活")
m.import_rollback(source_id=r["source_id"])

已支持的适配器:

适配器 来源 导入内容
WorkBuddyAdapter ~/.workbuddy L1 身份(常驻生效)· L2 技能 · L4 项目笔记
DocAdapter 指定目录 L3 关键文档(PRD / 架构 / 计划 / 复盘 / ADR / 规范),按章节切分

⚠️ 导入必须走 ingest_batch(),不要循环调用 ingest()。 ingest() 只发送 text,会丢掉 tier / mtype / source_id / blob: 结果是身份层从 resident 静默降级成普通事实(常驻身份失效且没有任何报错), 并且因为没有批次 id 而无法回滚。

安全(2026-09-17 起口径变更):导入时服务端会扫一遍疑似凭据(阿里云 AK / PyPI token / PEM 私钥 / 带密码的 DSN / 高熵串)与个人信息,命中条目照常入库并在回执里给出 detected_secrets(只给序号与类型,不回显值)。

N1Mem 是中间件,不做内容脱敏 —— 你决定存什么,我们尊重并严格执行。 服务端的责任是:系统安全、不主动泄密、主动保护隐私(租户隔离 / 最小权限 / 静态加密 / 访问留痕)。若你不想让某内容进库,请在入参里就不要发它。 blocked_secrets 为兼容字段,此后恒为空数组。

对话提炼:n1mem.distill(0.3.0 起随包提供)

把本机的会话记录提炼成记忆条目,而不是把原始对话整段灌进去 —— 单条对话最长可达数十万字符(实测 47 万),远超任何上下文窗口, 不分块直接发必然失败。

它的核心设计是把「算钱」和「花钱」分成两步,让费用在发生前就可见:

步骤 是否花钱
scan_dialogues() —— 数出待提炼的轮次 纯本地,零网络、零 LLM 调用
estimate(...) —— 换算成预估费用 纯本地
plan_chunks() / build_prompt() —— 分块、拼提示词 纯本地(可在 dry-run 里先看分块是否合理)
distill_chunk(...) —— 真正提炼一块 ⚠️ 本模块唯一会花钱的一步,必须由调用方显式触发
from n1mem import distill

st  = distill.scan_dialogues()                   # 本地扫描,不花钱
est = distill.estimate(st, price_in_per_m=1.0,   # 本地估算,仍不花钱
                       price_out_per_m=4.0)
print(est["turns"], est["est_cost_total_cny"])   # 先看清要花多少
# 确认之后,才逐块调用 distill_chunk(complete=…, chunk=…, model=…)

estimate() 的返回值刻意分成两组,别混着看:

  • certain_fields(turns / chars / skipped_* / merged_user)—— 本地数出来的确定值;
  • estimated_fields(token 数、金额)—— 按 assumptions(字符/token 比、块大小、单价) 换算的估算值;输出长度由模型决定,实际费用可能高于或低于此数。

超长条目跳过并计数(skipped_oversize),不会悄悄截断。

API

方法 对应端点 说明
health() GET /health 健康与 provider 状态,无需鉴权
metrics() GET /metrics Prometheus 文本指标
ingest(text, purpose="recall") POST /v1/ingest 写入一段记忆(持久化 + 建向量,写入即可召回)
recall(prompt, purpose="recall", mode=None) POST /v1/recall 按提示召回;返回 answer(已基于命中记忆接地)与 retrieved(命中明文)
ingest_batch(items, source_id=…) POST /v1/ingest/batch 批量导入,自动切块并汇总;幂等(同批重跑 inserted=0)
list_memories(limit=50, …, with_content=False) GET /v1/memories 列出本租户记忆;默认只给预览,要全文须显式开
forget(memory_id) POST /v1/forget 删除指定记忆(仅本租户可见,删除后无法召回)
import_rollback(source_id=…) POST /v1/import/rollback 按批次 / 来源目录撤销导入
forget_all(confirm=True) POST /v1/memories/all 清空本租户全部记忆(须显式 confirm=True)
ask / update — 尚未提供,调用会明确抛 NotImplementedError

异步版 AsyncN1Mem 接口完全一致:

from n1mem import AsyncN1Mem

async with AsyncN1Mem(api_key="tk_xxx") as m:
    await m.ingest("…")
    await m.ingest_batch(items)

环境变量

变量 说明 默认
N1MEM_API_KEY 你的 Key(BYOK)。N1Mem() 未显式传 api_key 时从这里取 空
N1MEM_SUBJECT 主体名:谁在调用(人 / 设备)。见下节 空
N1MEM_BASE_URL API 地址(构造参数 base_url 优先) https://api.n1mem.com
N1MEM_INSTANCE 实例标识:设备级授权载体 <local_id>:<secret>(0.3.1 新增)。开「实例强制」模式时必传 空

显式传入的构造参数优先于环境变量。

主体声明:N1MEM_SUBJECT(0.3.0 新增)

Key 回答「哪个组织」,N1MEM_SUBJECT 回答「谁」。

同一个 Key(同一组织)下可能有多台设备 / 多个人在调用。声明主体后,服务端按 (org, subject) 反查成员表,据此判定该主体是否已被接入。

from n1mem import N1Mem

m = N1Mem(api_key="tk_xxx", subject="workbuddy-pc")   # 也可设环境变量 N1MEM_SUBJECT

实例身份:N1MEM_INSTANCE(0.3.1 新增)

主体回答「谁」,实例回答「哪台设备」。

格式 <local_instance_id>:<密钥串>。服务端据此把写入绑定到具体设备,支持设备级的 「撤销 / 轮换」:撤销某个实例后,该设备的后续请求立即失效,不影响同组织其它设备。

from n1mem import N1Mem

m = N1Mem(api_key="tk_xxx", instance="my-pc:abc123")   # 也可设环境变量 N1MEM_INSTANCE

实例强制模式(服务端 N1MEM_REQUIRE_INSTANCE=1)开启前,客户端需先完成实例登记; 当前默认关闭,不传实例仍可正常调用。

SDK 会把主体作为 x-n1mem-agent 请求头发给服务端。

  • 须与组织里已登记的主体名逐字一致。拼错不会报错 —— 服务端只会认为「该主体未登记」。
  • 不设 ⇒ 不发这个头,行为与本能力引入前完全一致 ⇒ 随时可回退(去掉该键即可)。
  • 🔴 别拿 Agent 的类型名当主体名(如 workbuddy):那是「哪个 Agent」,不是「谁」。 一台机器同时跑多个 Agent 时,它们应当共享同一个主体;否则该共享的 private 记忆反而互相看不见。
  • 想确认服务端认到什么:调 /v1/member/status —— 未声明主体时它明确回报 missing_subject,不含糊。

配套 MCP Server 有同样的开关:见 n1mem-mcp。

错误处理

上游 4xx/5xx 统一抛 N1MemError,带 status / message / endpoint:

from n1mem import N1MemError
try:
    m.ingest("x")
except N1MemError as e:
    print(e.status, e.endpoint, e.message)   # 401 /v1/ingest {"detail":"invalid api key"}

参数用错(如 forget_all() 未确认、import_rollback() 两个参数都没给)会抛 ValueError / TypeError —— 在本地就失败,不浪费一次注定被拒的网络请求。

当前能力边界(诚实清单)

  • ingest() 持久化到 N1Mem 存储层并生成向量,返回 {stored, embedded, memory_id};写入后即可被召回。
  • recall() 走关键词 + 向量混合检索(hybrid);answer 基于命中记忆接地生成,未命中会诚实说明未命中,不编造。
  • 租户隔离由服务端按 API Key 反查 org 保证,不存在传参越权读取的路径。
  • ask / update 尚未提供,SDK 会明确抛 NotImplementedError,而不是静默返回空。

历史勘误

版本 曾经的错误说法 现状
≤ 0.1.2 README 写「Phase 0 不持久化、recall 取不回」 已随 C-2 存储层 + 召回接地修复而过时,勿再引用
≤ 0.1.5 包内 __version__ 停在 0.1.2,与 pyproject 不一致 0.2.0 已对齐,并有测试钉住(防再漂移)

与 t1mem_sdk 的区别

同目录下有两个包,不要混用:

包 对接对象 用途
n1mem 线上 C-2 API(https://api.n1mem.com) 对外发布,本 README 描述的对象
t1mem_sdk 本地 t1mem-core API(http://127.0.0.1:8080) 内部使用,接口为 /memories、/sessions、/stats

相关:MCP Server

想让 Claude / Cursor / OpenClaw 以工具方式调用记忆(而不是写代码), 装配套的 n1mem-mcp。

Metadata

Release files for n1mem 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for n1mem 0.3.1
File Size Uploaded
n1mem-0.3.1.tar.gz 45.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for n1mem 0.3.1
File Interpreter ABI Platform
n1mem-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 89.5 kB

Release files / n1mem-0.3.1.tar.gz

Download URL n1mem-0.3.1.tar.gz
Size 45.3 kB
Tags Source
SHA-256 checksum
How to use checksums
22807b3b5b41d521327b7b6829e3472d0a5d4d217ddcca71de2f0a66561aa09b
BLAKE2b-256 checksum
How to use checksums
0071120405efc5bc9750c36bd48c2cd40a1632722a674e3a7e026442b5450206
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / n1mem-0.3.1-py3-none-any.whl

Download URL n1mem-0.3.1-py3-none-any.whl
Size 44.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ec225e8efc0fc9613fddbded43e52811b9d50d52510d19dce5ea369a3a8f49db
BLAKE2b-256 checksum
How to use checksums
9c5bfc424f3072ede489ba214a113231780498d7da8da8644540ef0e12b08acf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

0.3.2

2 release files

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

1 release file

0.1.1

1 release file

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page