Repository navigation
Releases: hsuanshao/AgentMemory
Release list
v0.4.3 — security release: hashed user keys, throttled and audited key checks, HTTPS profile, JSON distillation input
Before you upgrade
This release finishes the October security review. Check these before you upgrade; each one links to its section in UPGRADE → To 0.4.3.
| If … | Then … |
|---|---|
| Docker runs rootless | memory-core sees every client as one address, so 20 wrong keys from anyone lock everyone out for 15 minutes. Set AGENT_MEMORY_THROTTLE_LOCK_AFTER=0, or put a reverse proxy on the host and trust it (rootless Docker) |
| Many people share one address (an office NAT, a VPN gateway) | A lockout refuses valid keys too, for everyone behind the address: check the addresses on Panel → Metadata → Audit after upgrading, and raise or turn off the lock (refused keys) |
| memory-core sits behind a reverse proxy other than the bundled Panel and Caddy | Name it in AGENT_MEMORY_TRUSTED_PROXIES, or every client counts as the proxy's address |
A script calls internal/upgrade with issue_key to get a fresh admin key |
It is refused unless there is legacy data to move or AGENT_MEMORY_ALLOW_KEY_RECOVERY=true (keys) |
A script creates users or the first admin with its own key (user_key) |
Use sk-mem- and at least 32 letters, digits, - or _ |
A department has custom memory prompts that mention the input's old labels, such as [New messages to extract] |
Refer to the JSON fields instead (distillation input) |
Existing installs keep listening where they did (upgrade.sh adds BIND_ADDR=0.0.0.0); new installs listen on 127.0.0.1 unless told otherwise.
Warning
Going back to 0.4.2 after this upgrade means restoring the backup. memory-core runs schema migration 6 at startup, which replaces every stored user key by its SHA-256 digest; 0.4.2 refuses data at schema version 6. upgrade.sh takes the backup; UPGRADE → Roll back restores it.
git fetch --tags && git checkout v0.4.3
./upgrade.shThen update amem on each client (REMOTE-CLIENTS §4).
Security
Advisories: GHSA-x7mg-477v-vq57, GHSA-pfg6-rm9f-v293, GHSA-rhcg-v6f6-2959, GHSA-2374-jpw4-x82w, GHSA-4h9p-q8r4-vxc7, GHSA-w56f-hx28-m78m.
- User keys are stored as SHA-256 digests (schema migration 6, converted in place; existing keys keep working). A lost key cannot be read back; a system admin issues a new one.
internal/upgradeissues a key only along with legacy data to move, or withAGENT_MEMORY_ALLOW_KEY_RECOVERY=true. - Refused credentials are throttled per client address: from the 5th in 15 minutes each refusal waits longer (up to 5 s), the 20th locks the address out for 15 minutes (429 with
Retry-After).X-Forwarded-Forcounts only from trusted proxies (AGENT_MEMORY_TRUSTED_PROXIES). Limits:AGENT_MEMORY_THROTTLE_{DELAY_AFTER,LOCK_AFTER,LOCK_MINUTES}, 0 turns them off. - Credential audit log: refusals, lockouts and keys issued with the server API key, with time, address, forwarding chain, user agent and the start of the key's digest, never the key. Kept 90 days. System admins see their department's on Panel → Metadata → Audit; the operator sees all with
/v3/internal/audit/list. - The distillation model gets all its input as JSON data: L1 extraction and dedup, L2 scenes and L3 persona, as skill extraction does since 0.4.2.
amemcloses the recall blocks it opened when it cuts a context, does not follow redirects (nor do the operator commands), creates its files private from the start, reads every word after--as the query, and can trust a private CA (--ca-cert).- Panel: the session key is kept per browser tab, a revoked key stops working within 10 s, a Content-Security-Policy is sent, and the browser's address is forwarded to Core.
- Smaller: internal errors answer with their code and request id only; an agent's owner who left its team can no longer manage the agent; a binding records the caller who set it; name filters treat
%and_literally;init-admincreates one administrator when called at once.
What's new
- New installs keep the ports on this machine.
install.shasks who reaches the server: this machine (BIND_ADDR=127.0.0.1, the default), other machines over HTTP, or other machines over HTTPS. - An optional
tlsCompose profile puts Caddy with HTTPS in front of memory-core and the Panel (TLS guide).
Fixes
- Tasks whose skill proposals all expired are closed hourly.
Full list: CHANGELOG → 0.4.3.
v0.4.2 — security release: departments administered by their own users, private agents, approved skills, server-side redaction
Before you upgrade
This release tightens access. Check these before you upgrade; each one links to its section in UPGRADE → To 0.4.2.
| If … | Then … |
|---|---|
A Panel, script or client sends a department id that never ran init-admin |
Run init-admin for it after upgrading (departments) |
Scripts or monitoring call meta/*, pipeline/*, stats/overview, … with only the server API key |
They now get 401: give them a system admin's user key, or use the internal/… routes (server API key) |
The Panel runs outside Compose, or an override sets CORE_API_KEY for it |
Remove CORE_API_KEY; the Panel no longer uses it |
| The server API key was handed to department admins | Change it after the upgrade: it is a root credential across departments |
| The distillation CLI goes through a cloud provider (Bedrock, Vertex AI, Azure) or a wrapper script | List the variables it needs in AGENT_MEMORY_LLM_CLI_PASS_ENV (CLI) |
| You rely on extracted skills appearing by themselves | Approve them on Panel → Skills, or set AGENT_MEMORY_SKILL_REQUIRE_APPROVAL=false (skills) |
| Each person has their own agent, but the agents are team-visible | Set each to "visibility": "private" |
Warning
Going back to 0.4.1 after this upgrade means restoring the backup. memory-core runs schema migrations 4 (an index of the atoms without an embedding) and 5 (department redaction rules) at startup, and 0.4.1 refuses data at a newer schema version. upgrade.sh takes the backup; UPGRADE → Roll back restores it.
git fetch --tags && git checkout v0.4.2
./upgrade.shThen update amem on each client (REMOTE-CLIENTS §4).
Security
Advisories: GHSA-g73h-mwv4-hq6c, GHSA-w9gw-jgqg-wf4m, GHSA-c99j-f426-8w84, GHSA-v283-7qch-6992, GHSA-2jjp-45cp-qxfq, GHSA-2w2h-pg86-437m.
- Each department is administered by its own users.
meta/*,pipeline/*,stats/overviewand generation logs take a user key of the department and apply that user's role; prompts, knowledge and chat-memory clearing take a system admin's. The server API key opens only the operator routes (internal/*,department/destroy). The Panel no longer holds it (#68). - A private agent is its owner's. Its memory, scenes, persona and skills are usable by its owner, the team's admins and system admins only; an archived agent is refused (#61).
- Recall output quotes what is stored, so stored text cannot open or close the blocks integrations inject; new scene paths are plain (#62, #63).
- Departments are created only by
init-admin, and storage opens nothing else; a destroyed department stays gone, also for background work and across replicas (#64, #65). - The distillation CLI gets an allowlisted environment: the basics, its own settings, and what
llm.cli.passEnvnames, neverAGENT_MEMORY_*(#66). - Skill extraction proposes; people approve. The model gets the conversation as JSON data, may change only the skills it was shown, and its changes wait on the Panel's Skills page for the conversation's user, a team admin or a system admin (#69).
- Secrets are redacted on the server on every write path, in English, the major languages of Asia and more, and by shape (#58).
What's new
- Department redaction rules (#60, #57): system admins add their own patterns in the Panel (Metadata → Redaction), with a preview, on top of the built-in and deployment rules.
- Missing embeddings are filled in later (#59): memory-core retries atoms stored without an embedding, and
memory-server reembeddoes it on demand. Embedding concurrency and timeouts can be set by environment. /v3/session/addstores raw turns again, per team, agent, user and session (#67).
Fixes
- A CLI that closes its input early is judged by its output, not by the broken pipe (#69).
- Several flaky tests; CI now runs the Postgres suites on PostgreSQL 17.
Full list: CHANGELOG → 0.4.2.
v0.4.1 — scenes and personas as append-only versions; newer data is refused
Before you upgrade
Warning
Going back to 0.4.0 after this upgrade means restoring the backup. Scenes and personas move to new tables at startup, which 0.4.0 does not read. If 0.4.0 runs on the upgraded data:
- it shows the scenes and persona from before the upgrade;
- what it writes is not carried over by a later upgrade.
upgrade.sh takes the backup; UPGRADE → Roll back restores it.
git fetch --tags && git checkout v0.4.1
./upgrade.shSchema migration 3 runs when memory-core starts:
- every version in
profile_filesis copied intoscenes,scene_versionsandpersona_versions; profile_filesis kept, but no longer written;- clients see the same scenes and persona, and the API paths are unchanged.
Then update amem on each client (REMOTE-CLIENTS §4).
Details: UPGRADE → To 0.4.1.
What's new
Scenes (L2) and personas (L3) are append-only versions (#52, part of #51). This is the groundwork for recording which memories a scene is built from.
- Nothing is rewritten or deleted.
- An L2 update, a merge, an API write and
/v3/scenario/rmeach add a version. - Clearing a chat memory is the one operation that deletes history.
- An L2 update, a merge, an API write and
- Lineage.
- Every scene has a fixed
scene_id. - A merge records the versions it absorbed and retires them.
- Retired scenes stay readable by
version, or byscene_idonce another scene takes their name. readreturns each version'sop,parentsandauthor.
- Every scene has a fixed
- Key fields are columns; the rest stays flexible. Name, summary, heat, op, author and time are columns. The body stays markdown, and other attributes are kept as they are.
- The persona stores its body only. The Scene Navigation is rendered from the current scenes when the persona is read, so the persona no longer gets a new version each time a scene changes.
- Your edits win over a running L2. A scene you write or remove through the API while L2 waits for its model keeps your version. L2 drops the operations it planned on the older view; those memories stay in L1.
- Newer data is refused. memory-core stops with an error, instead of misreading data or migrating over it, when SQLite, Postgres or Redis holds data written by a newer version. This protects later rollbacks; 0.4.0 does not have the check.
Full changelog: CHANGELOG.md · v0.4.0...v0.4.1
v0.4.0 — BSL 1.1 license; the distillation model never gets tools; L1 supersedes out-of-date memories
Before you upgrade
Warning
1. The license changes. From 0.4.0 the server is licensed under the Business Source License 1.1 (#48).
- Free: evaluation, development and testing; personal and non-profit use; and production use by an organization with at most 1 department and 10 members across all its deployments.
- Commercial license required: larger production use, or offering AgentMemory as a hosted service.
- Each version becomes Apache 2.0 four years after its release. The
amemclient and the plugins stay MIT, and 0.3.2 and earlier remain MIT. - See COMMERCIAL.md.
2. memory-core refuses to start when AGENT_MEMORY_LLM_CLI_ARGS grants the distillation CLI capability (#47). The refused arguments include:
--dangerously-*,--yolo,--allowedTools,--mcp-config, a permissive--permission-mode;- codex
--enable,--search,--profile, a sandbox other thanread-only; - codex
-csettings that add MCP servers, web search, features or approval.
The error names the argument. Remove it before upgrading.
3. The distillation codex no longer reads config.toml. Move the settings it needs into -c arguments.
git fetch --tags && git checkout v0.4.0
./upgrade.shupgrade.sh builds the new version and checks your configuration before starting it. If the check, the build or the start fails, it restores .env and brings the previous version back on its previous image. No data migration is needed in this release. Then update amem on each client (REMOTE-CLIENTS §4).
Details: UPGRADE → To 0.4.0.
What's new
The distillation model gets no tools (#47, the direction agreed in #37). Distillation reads untrusted conversation text.
-
Agent CLIs. memory-core turns off their own tools before they read a prompt (
llm.cli.hardening, defaultauto):clauderuns with 0 tools and no MCP servers;codexruns with its connectors, plugins, shell, code execution, browsing and web search off, a read-only sandbox, and--ignore-user-config.
Every CLI is told it has no tools. See DISTILLATION §6.
-
Self-hosted models. A reply that is only a tool call fails with the new code
LLM_TOOL_REQUESTand is dropped without retries, like a refused CLI call. An answer next to a stray tool call is kept. -
memory-server check-configvalidates the configuration without starting the server. -
upgrade.shrolls back on any failure between the backup and a healthy new version. -
Fix: the Docker build could ship the previous binary when the sources came from an archive.
Memory that keeps up with the conversation (#49, @blackhorseya, closes #43).
- L1 now sees the session's recent memories, so a later turn can mark an out-of-date one (
supersedes) and rewrite it in place. - L2 writes scenes as the current state, not as a change log.
Docs (#45, #46): README badges, the new logo, a clearer introduction, and this CHANGELOG.
Thanks to @blackhorseya for #49, for four careful review rounds on #47 (ten findings, all fixed), and for agreeing to the license change.
All changes since v0.3.2: #45, #46, #48, #49, #47, the release PR #50, and a README update on main. Compare v0.3.2…v0.4.0
升級前請先看
Warning
1. 授權變更。 從 0.4.0 開始,server 端改用 Business Source License 1.1(#48)。
- 免費: 評估、開發與測試;個人與非營利使用;以及所有部署合計最多 1 個部門、10 位成員的組織用於正式環境。
- 需要商業授權: 更大規模的正式環境使用,或把 AgentMemory 做成託管服務提供給他人。
- 每個版本發布滿四年後轉為 Apache 2.0。
amemclient 和各工具的 plugin 維持 MIT,0.3.2 以前的版本也維持 MIT。 - 詳見 COMMERCIAL.zh-tw.md。
2. 只要 AGENT_MEMORY_LLM_CLI_ARGS 讓蒸餾用的 CLI 拿到額外能力,memory-core 就不會啟動(#47)。會被拒絕的參數包括:
--dangerously-*、--yolo、--allowedTools、--mcp-config、寬鬆的--permission-mode;- codex 的
--enable、--search、--profile、read-only以外的 sandbox; - 會加入 MCP server、網路搜尋、feature 或 approval 的 codex
-c設定。
錯誤訊息會指出是哪個參數,升級前請先拿掉。
3. 蒸餾用的 codex 不再讀 config.toml。 需要的設定請改放到 -c 參數。
git fetch --tags && git checkout v0.4.0
./upgrade.shupgrade.sh 會先建置新版本並檢查你的設定,通過後才啟動。如果檢查、建置或啟動失敗,會還原 .env,並用原本的 image 重新執行舊版本。這一版不需要遷移資料。升級後請更新每台 client 的 amem(REMOTE-CLIENTS 第 4 節)。
新功能
蒸餾模型不會拿到任何工具(#47,依照 #37 討論出的方向)。蒸餾讀的是不可信的對話內容。
-
Agent CLI: memory-core 會在它們讀到 prompt 之前,先關掉它們自帶的工具(
llm.cli.hardening,預設auto):claude以 0 個工具、不載入 MCP server 的狀態執行;codex關掉 connector、plugin、shell、程式執行、瀏覽和網路搜尋,使用唯讀 sandbox,並加上--ignore-user-config。
每個 CLI 也都會被告知它沒有工具。詳見 DISTILLATION 第 6 節。
-
自架模型: 回應只有工具呼叫時,以新的錯誤代碼
LLM_TOOL_REQUEST失敗,直接 drop、不重試,和 CLI 的工具被拒絕一樣。答案旁邊順帶出現的工具呼叫會被拿掉,答案本身照常使用。 -
memory-server check-config: 只檢查設定,不啟動 server。 -
upgrade.sh會自動還原: 從備份之後到新版本健康檢查通過之前,任何一步失敗都會還原。 -
修正: 原始碼來自壓縮檔時,Docker 建置可能沿用舊的執行檔。
記憶會跟上對話的最新狀態(#49,@blackhorseya,修正 #43)。
- L1 抽取時會看到這個 session 最近的記憶,後面的對話可以把過時的那筆標記出來(
supersedes),就地改寫。 - L2 把場景寫成目前的狀態,不再寫成變更紀錄。
文件(#45、#46):README 的 badge、新 logo、更清楚的介紹,以及這份 CHANGELOG。
感謝 @blackhorseya 貢獻 #49,對 #47 做了四輪仔細的 review(共 10 點,全部已修正),也同意這次的授權變更。
v0.3.2 之後的所有變更: #45、#46、#48、#49、#47、release PR #50,以及 main 上一次 README 更新。比較 v0.3.2…v0.4.0
v0.3.2 — dead letters expire and redrive themselves; amem captures mid-turn messages
Why this release
Dead letters no longer pile up. Before 0.3.2:
- nothing ever removed a dead letter;
- nothing requeued one after its cause had passed;
- most distillation time on agentic CLIs went to retrying tool refusals that could never succeed.
Also, amem now captures what you type while Claude Code is still working. Those messages used to be missing from memory.
Upgrading
No data or configuration changes are required. From 0.3.x:
git fetch --tags && git checkout v0.3.2
./upgrade.shThen update amem on each client machine to get the capture fix (REMOTE-CLIENTS §4).
Note: dead letters written before 0.2.3 carry no time. The first sweep after the upgrade treats them as older than a day and removes them. Redrive any you still want before upgrading. Their failures stay in the generation logs.
What's new
Dead letters look after themselves (#41). A sweeper runs every 5 minutes:
| A dead letter… | What happens |
|---|---|
| first failed more than a day ago, or was redriven 3 times | removed; the generation logs keep its failures and input ids |
| failed for a passing reason (quota, timeout, outage, an invalid answer) | redriven on its own after 1 h, then 2 h, then 4 h; at most 10 per sweep |
| was refused a tool call (#37) | kept until the configured model changes, then redriven like the others |
-
A refused tool call is no longer retried: L1/L2 drop the input at once instead of after three ~45 s attempts.
-
Dead letters now record their model, their re-runs and when they first failed. The Panel shows re-runs, and
/healthcounts redriven and expired letters. -
A redrive whose queue write failed could lose the rest of its batch. Every letter not yet queued is now kept.
-
New settings in the
workersection (defaults in brackets):deadLetterTtlHours(24);deadLetterMaxRedrives(3);deadLetterRedriveAfterMinutes(60);deadLetterSweepSeconds(300);deadLetterRedriveBatch(10).
amem captures messages sent while Claude Code is working (#40, @blackhorseya). Claude Code records them as queued_command attachments, not user entries.
- They are captured as part of the current turn, with their own timestamp.
- Task notifications and messages from other sessions are not captured.
- With
skip_prompt_prefixes, a matching message dropped mid-turn is skipped on its own, and the turn around it is kept.
Thanks to @blackhorseya for #40 and for the review of #41.
All changes since v0.3.1: #40 and #41, plus the version bump #42. Compare v0.3.1…v0.3.2
為什麼要發這個版本
Dead letter 不會再一直累積。 0.3.2 之前:
- dead letter 從來不會被移除;
- 失敗原因消失後,也不會被重新排回佇列;
- 使用會主動用工具的 CLI 時,大部分蒸餾時間都花在重試「工具被拒絕」上,而這種重試永遠不會成功。
另外,amem 現在會擷取你在 Claude Code 工作期間輸入的訊息,這些訊息以前都沒有進入記憶。
升級
不需要改動資料或設定。從 0.3.x 升級:
git fetch --tags && git checkout v0.3.2
./upgrade.sh接著更新每台 client 機器上的 amem,才會套用擷取的修正(REMOTE-CLIENTS 第 4 節)。
注意: 0.2.3 以前寫入的 dead letter 沒有時間紀錄。升級後第一次清理會把它們當成已超過一天,直接移除。如果還有想保留的,請在升級之前先重跑。它們的失敗紀錄仍保留在生成紀錄中。
新功能
Dead letter 會自動處理(#41)。每 5 分鐘清理一次:
| Dead letter 的狀況 | 處理方式 |
|---|---|
| 第一次失敗超過一天,或已重跑 3 次 | 移除;生成紀錄仍保留它的失敗原因和輸入 id |
| 暫時性失敗(額度、逾時、服務中斷、回應無效) | 1 小時後自動重跑,之後間隔 2 小時、4 小時;每次最多 10 筆 |
| 工具被拒絕(#37) | 保留到設定的模型變更後,再像其他 dead letter 一樣重跑 |
-
工具被拒絕時不再重試:L1/L2 直接 drop 這一批,不必再試 3 次、每次約 45 秒。
-
Dead letter 會記錄失敗時的模型、重跑次數和第一次失敗的時間。Panel 會顯示重跑次數,
/health會統計自動重跑和到期移除的數量。 -
修正重跑時寫入佇列失敗、同一批其餘 dead letter 會遺失的問題。現在所有還沒排入的都會保留。
-
worker區段新增以下設定(括號內為預設值):deadLetterTtlHours(24);deadLetterMaxRedrives(3);deadLetterRedriveAfterMinutes(60);deadLetterSweepSeconds(300);deadLetterRedriveBatch(10)。
amem 會擷取 Claude Code 工作期間送出的訊息(#40,@blackhorseya)。Claude Code 把這些訊息記成 queued_command 附件,而不是一般的使用者訊息。
- 現在它們會當成目前這一輪的一部分被擷取,並保留各自的時間。
- task notification 和其他 session 傳來的訊息不會被擷取。
- 使用
skip_prompt_prefixes時,符合前綴的插話只略過那一則,不影響它所在的那一輪。
感謝 @blackhorseya 貢獻 #40,並仔細 review 了 #41。
v0.3.1 之後的所有變更:#40、#41,以及版號更新 #42。比較 v0.3.1…v0.3.2
v0.3.1 — distillation keeps going past failing input; upgrade.sh backs up PostgreSQL 17
Why this release
Distillation no longer stalls on a batch it cannot process, and upgrade.sh can back up PostgreSQL 17. First, upgrade.sh could not back up an external PostgreSQL 17 (or newer) server. With your own server (AGENT_MEMORY_POSTGRES_URL, no bundled postgres profile), the backup ran the pg_dump from postgres:16-alpine. pg_dump refuses a server newer than itself, so the backup failed with aborting because of server version mismatch and the upgrade stopped. The only way past it was to back up by hand and re-run with UPGRADE_SKIP_BACKUP=1.
Upgrading
No data, configuration or client changes since 0.3.0. Jobs already queued keep working. From 0.3.0:
git fetch --tags && git checkout v0.3.1
./upgrade.shFrom an earlier version, follow docs/UPGRADE.md → To 0.3.0; upgrade.sh from this release does it in one run, including the backup on PostgreSQL 17. amem 0.3.0 keeps working; 0.3.1 is the same client.
Changed
-
Distillation no longer stalls on input it cannot process (#38). L1 (per session) and L2 (per agent) used to retry a batch that failed every attempt forever, and nothing after it in that session or agent was distilled. On the last attempt the batch is now dropped:
- the cursor moves on;
- the run is logged as
droppedwith its error and the ids of the skipped input; - the dead letter keeps a job that redoes exactly that input (
range), so an admin can re-run it after changing the model.
Nothing is deleted, and no model gets any new capability (see #37).
-
Panel:
- a Dropped column per layer and a "Dropped input" link on the dashboard;
- the
droppedlog filter; - the dropped range on dead letters.
-
CLI:
memory-server generations --status dropped.
Fixed
upgrade.shdumps an external Postgres with the matchingpg_dump(#35).- It first reads the server's version.
- It then runs
pg_dumpfrompostgres:<major>-alpine, so it keeps working on 16, 17 and later. - If the version can't be read (unreachable server, wrong credentials), it stops with a clear message.
- The bundled Postgres was not affected.
- Upgrade guide: the settings step now lists the 0.3.0
.envrename (CORE_INSTANCE_ID→CORE_DEPARTMENT_ID).
為什麼要發這個版本
蒸餾不再卡在無法處理的那一批,upgrade.sh 也能備份 PostgreSQL 17 了。 首先,upgrade.sh 無法備份外部的 PostgreSQL 17(或更新)伺服器。 使用自己的伺服器時(AGENT_MEMORY_POSTGRES_URL,沒有啟用內建的 postgres profile),備份用的是 postgres:16-alpine 裡的 pg_dump。pg_dump 不接受比自己新的伺服器,所以備份會失敗並出現 aborting because of server version mismatch,升級也跟著中止。唯一的繞法是先手動備份,再加 UPGRADE_SKIP_BACKUP=1 重跑。
升級
和 0.3.0 相比,資料、設定和 client 都沒有改變,佇列中既有的 job 也照常運作。從 0.3.0 升級:
git fetch --tags && git checkout v0.3.1
./upgrade.sh從更早的版本升級,請依 docs/UPGRADE.zh-tw.md →「升級到 0.3.0」 進行;這一版的 upgrade.sh 可以一次完成,在 PostgreSQL 17 上也能正常備份。amem 0.3.0 可以繼續使用,0.3.1 的 client 內容相同。
變更
-
蒸餾不再卡在無法處理的內容上(#38)。L1(以 session 為單位)和 L2(以 agent 為單位)以前遇到每次嘗試都失敗的一批,會一直重試,同一個 session 或 agent 後面的內容就都不會被蒸餾。現在在最後一次嘗試仍失敗時,這一批會被 drop:
- 游標繼續前進;
- 這次執行記錄為
dropped,附上錯誤和被略過輸入的 id; - dead letter 保存只重做這一段的 job(
range),admin 換了模型後可以重跑。
不會刪除任何資料,也不會給任何模型新的權限(見 #37)。
-
Panel:
- dashboard 每層多一欄 Dropped,並有「Dropped input」連結;
- 生成紀錄可以篩選
dropped; - dead letter 顯示被 drop 的範圍。
-
CLI:
memory-server generations --status dropped。
修正
upgrade.sh用版本相符的pg_dump備份外部 Postgres(#35)。- 先讀取伺服器的版本。
- 再用
postgres:<主版本>-alpine執行pg_dump,所以 16、17 以及之後的版本都能正常備份。 - 讀不到版本時(連不上或帳密錯誤),會停下來並顯示清楚的訊息。
- 內建的 Postgres 不受這個問題影響。
- 升級指南:設定那一步補上 0.3.0 的
.env改名(CORE_INSTANCE_ID→CORE_DEPARTMENT_ID)。
v0.3.0 — departments, versioned migrations, team leader role
What you must do
0.3.0 renames the "instance" to the "department", in the API, the settings and the stored data. An AgentMemory server holds departments, a department holds teams, and a team holds members and agents. Update the server and every client together:
-
Stop the agents that write to the server. If you run several memory-core replicas, stop all of them: an older replica cannot read migrated data.
-
On the server:
git fetch --tags && git checkout v0.3.0 ./upgrade.shupgrade.shbacks up the data, renamesCORE_INSTANCE_IDtoCORE_DEPARTMENT_IDin.envand rebuilds. memory-core migrates the stored data as it starts. The migration is one-way: going back to 0.2.x means restoring that backup. -
Update
amemon every client machine. It rewritesservice_idtodepartment_idinclient.jsonby itself. In Claude Code, if you had set Service ID, set Department ID to the same value.
A client older than 0.3.0 gets 401: "x-memory-service-id was renamed in 0.3.0; update the client".
| Before | 0.3.0 | |
|---|---|---|
| Header | x-memory-service-id |
x-memory-department-id |
amem |
service_id, AMEM_SERVICE_ID, --service-id |
department_id, AMEM_DEPARTMENT_ID, --department-id |
.env / Panel |
CORE_INSTANCE_ID |
CORE_DEPARTMENT_ID |
memory-core.yaml |
maxOpenInstances, max*PerInstance |
maxOpenDepartments, max*PerDepartment (old names are rejected by name) |
| API | /v3/instance/destroy, meta/instance-quota/get, internal/meta/user/list-by-instance |
the department equivalents |
| Team roles | admin, member, reviewer |
admin, leader, member (reviewers become members) |
Full guide: docs/UPGRADE.md → To 0.3.0.
What's new
Versioned storage migrations (#32)
-
Stored data now carries a version:
- SQLite
user_version; - Postgres
agent_memory.schema_migrations; - Redis
{prefix}:schema_version.
- SQLite
-
memory-core migrates at start-up under a lock, so with several replicas only one migrates.
memory-server migratedoes the same explicitly and also migrates every SQLite department up front. -
Migration 1 renames what 0.2 stored:
- the data directory;
system.db;- the Postgres registry, prompt targets and quota names (keeping your values);
- Redis indexes, state documents, queued jobs and dead letters.
Migration 2 turns reviewers into members.
-
How to add the next migration: docs/ops/SCHEMA-MIGRATIONS.md.
Team leader role and role-based visibility (#33)
-
A leader uses memory like a member and sees how the whole team's distillation is doing: pipeline state, generation logs and dead letters of every member. A leader cannot open other members' conversations or facts, and cannot manage members.
-
Pipeline state, generation logs and dead letters are now filtered by who asks:
Caller Sees Server API key alone, or a system admin The whole department Team admin or leader Their whole team Member The team's shared L2/L3 work, and their own Before 0.3.0, every signed-in user saw every scope of the department.
-
Redriving dead letters with a user key needs a system admin.
-
/healthno longer shows the worker's last error. -
Panel: the scope table shows team, agent and user names. A row links to the memory browser (
/memory?team=…&agent=…&user=…) only when you may read it.
Fixes
pipeline/statusappliedlimitbefore filtering. Session rows shared one table key, andl2_pendingwasnullon session rows (#33).- When the distillation LLM is a CLI (
claude,agy, …) and it answers nothing, the error now includes what it wrote to stderr (#31).
Docs: MULTI-TENANCY.md is now COLLABORATION.md (departments, teams, members and agents). The Bearer key is called the server API key: it covers every department.
你需要做的事
0.3.0 把「instance」改名為「部門(department)」,API、設定和儲存的資料都一起改。 一台 AgentMemory 伺服器容納多個部門,部門裡有團隊,團隊裡有成員和 agent。伺服器和所有 client 要一起更新:
-
停掉會寫入伺服器的 agent。如果跑了多個 memory-core replica,要全部停掉:舊版 replica 讀不懂遷移後的資料。
-
在伺服器上執行:
git fetch --tags && git checkout v0.3.0 ./upgrade.shupgrade.sh會備份資料、把.env的CORE_INSTANCE_ID改成CORE_DEPARTMENT_ID,然後重建服務。memory-core 啟動時會遷移儲存的資料。遷移只能往前:要回到 0.2.x,必須還原那份備份。 -
更新每台 client 機器上的
amem,它會自己把client.json的service_id改成department_id。在 Claude Code 裡,如果之前設定過 Service ID,請把 Department ID 設成同樣的值。
0.3.0 之前的 client 會收到 401,訊息是「x-memory-service-id was renamed in 0.3.0; update the client」。
| 之前 | 0.3.0 | |
|---|---|---|
| Header | x-memory-service-id |
x-memory-department-id |
amem |
service_id、AMEM_SERVICE_ID、--service-id |
department_id、AMEM_DEPARTMENT_ID、--department-id |
.env / Panel |
CORE_INSTANCE_ID |
CORE_DEPARTMENT_ID |
memory-core.yaml |
maxOpenInstances、max*PerInstance |
maxOpenDepartments、max*PerDepartment(設定檔還用舊名稱時,會直接報錯並指出新名稱) |
| API | /v3/instance/destroy、meta/instance-quota/get、internal/meta/user/list-by-instance |
對應的 department 路由 |
| Team 角色 | admin、member、reviewer |
admin、leader、member(reviewer 改為 member) |
完整說明:docs/UPGRADE.zh-tw.md →「升級到 0.3.0」。
新功能
有版本的儲存遷移(#32)
-
儲存的資料開始記錄版本:
- SQLite 用
user_version; - Postgres 用
agent_memory.schema_migrations; - Redis 用
{prefix}:schema_version。
- SQLite 用
-
memory-core 啟動時會在 lock 之下自動遷移,所以有多個 replica 時只會由一個執行。
memory-server migrate可以手動執行同樣的步驟,也會一次把每個 SQLite 部門都遷移完。 -
第 1 號遷移改寫 0.2 存下的資料:
- 資料目錄;
system.db;- Postgres 的 registry、prompt 目標和配額名稱(保留你設定的值);
- Redis 的 index、狀態文件、佇列中的 job 和 dead letter。
第 2 號遷移把 reviewer 改成 member。
Team leader 角色與依角色檢視運作狀態(#33)
-
Leader 像 member 一樣使用記憶,另外可以看到整個 team 的蒸餾運作情形:每位成員的管線狀態、生成紀錄和 dead letter。Leader 不能開啟其他成員的對話或事實,也不能管理成員。
-
管線狀態、生成紀錄和 dead letter 會依查詢者篩選:
呼叫者 看得到 只帶伺服器 API key,或系統管理者 整個部門 Team admin 或 leader 自己的整個 team Member team 共用的 L2/L3 工作,以及自己的工作 0.3.0 之前,任何登入的使用者都看得到部門內的所有範圍。
-
帶 user key 重跑 dead letter 需要系統管理者。
-
/health不再顯示 worker 最後一次的錯誤。 -
Panel:範圍表格顯示 team、agent 和使用者的名稱。只有你有權讀取的那一列,才會連到記憶瀏覽器(
/memory?team=…&agent=…&user=…)。
修正
pipeline/status原本先取筆數再篩選。同一個 agent 的多個 session 在表格裡共用同一個 key。session 那幾列的l2_pending是null(#33)。- 蒸餾用的 LLM 是 CLI(
claude、agy等)且沒有輸出任何內容時,錯誤訊息現在會附上它寫到 stderr 的內容(#31)。
文件:MULTI-TENANCY.md 改名為 COLLABORATION.zh-tw.md(部門、團隊、成員與 agent)。Bearer key 統一叫做伺服器 API key,它涵蓋所有部門。
Agent Memory v0.2.3
Why this release
Distillation could fail silently, and the work it lost could not be recovered. On a real install, the LLM that distils memories ran out of quota. 93 pipeline jobs (L1, L2, L3, skill extraction) failed every retry and were set aside as dead letters. Nothing showed it:
- A failed L1/L2/L3 run left no generation log, and neither did a run that wrote nothing.
- A dead letter was stored without its error. With the
localcoordination backend it was only counted, then lost. - There was no way to put a dead letter back in the queue; it took editing Redis by hand.
- The logs named only the command (
cli:agy), not the model that ran.
v0.2.3 makes all of this visible and recoverable.
Upgrading
No data or configuration changes. From any version since 0.1.1:
git fetch --tags && git checkout v0.2.3
docker compose up -d --buildDead letters written before the upgrade remain readable but have no error recorded. Update amem on the clients if you want skip_prompt_prefixes (below).
What's new and fixed
Distillation runs and dead letters (#28)
-
Every run is logged. Each L1/L2/L3 run that reaches the LLM is logged as
succeeded,empty(the LLM answered but nothing was written) orfailedwith its error. -
The real model is recorded, including a CLI's
--model, e.g.cli:agy:gemini-3.8-flash-high. -
Dead letters keep their last error and time.
- With Redis they are shared by all replicas.
- With
localcoordination, the newest 1,000 are kept in memory.
-
Panel → Dashboard → Distillation:
- the LLM in use;
- runs per layer over 24 h with the failure rate;
- the latest failures;
- dead letters per kind;
- a Re-run button for system admins.
Generation logs gain the
emptystatus, plus model, latency, session and error columns.#/logs?status=failedopens filtered. -
CLI on the server:
docker compose exec memory-core memory-server generations docker compose exec memory-core memory-server dead-letters docker compose exec memory-core memory-server dead-letters redrive --limit 10
-
API:
POST /v3/memory-generation-log/summary;POST /v3/pipeline/dead-letter/{list,redrive}.
A redrive queues jobs again as first attempts, oldest first. With several replicas, each one is taken by one node only.
-
Guide: docs/ops/DISTILLATION.md explains what is recorded, where to look, common LLM failures, changing the model, and redriving gradually.
Fixes and smaller changes
migrate-to-postgres.sh(#25): it now honoursAGENT_MEMORY_POSTGRES_URLgiven on the command line withMIGRATE_TARGET=postgres-url. Before, the empty value in.envreplaced it, which was the known issue in v0.2.2.amemskip_prompt_prefixes(#27, @blackhorseya): prompts that start with a configured prefix, such as messages an orchestrator types into an agent, are neither recalled for nor captured. The setting can come fromAMEM_SKIP_PROMPT_PREFIXES, the Claude Code plugin option, orclient.json. It is empty by default.
Thanks to @blackhorseya for #27.
為什麼要發這個版本
蒸餾可能在沒人發現的情況下失敗,遺失的工作也無法補回。 在一個實際運作的安裝上,負責蒸餾記憶的 LLM 額度用完了。93 個 pipeline job(L1、L2、L3、skill 擷取)每次重試都失敗,被移到 dead letter,但完全沒有跡象:
- 失敗的 L1/L2/L3 執行不會留下生成紀錄,沒有寫出任何東西的執行也一樣。
- Dead letter 沒有保存錯誤原因。使用
localcoordination backend 時只會計數,然後就消失。 - 沒有辦法把 dead letter 重新排回佇列,只能手動修改 Redis。
- 紀錄裡只有指令名稱(
cli:agy),看不出實際用的是哪個模型。
v0.2.3 讓這些狀況都看得到,也都能補救。
升級
資料和設定都沒有改變。從 0.1.1 之後的任何版本升級:
git fetch --tags && git checkout v0.2.3
docker compose up -d --build升級前寫入的 dead letter 仍然讀得到,但沒有記錄錯誤原因。如果要使用 skip_prompt_prefixes(見下方),請更新 client 端的 amem。
新功能與修正
蒸餾執行紀錄與 dead letter(#28)
-
每次執行都有紀錄。 每一次呼叫到 LLM 的 L1/L2/L3 執行,都會記錄為
succeeded、empty(LLM 有回應但沒有寫出任何東西)或failed(附上錯誤)。 -
記下實際使用的模型,包含 CLI 的
--model,例如cli:agy:gemini-3.8-flash-high。 -
Dead letter 會保留最後一次的錯誤和時間。
- 使用 Redis 時由所有 replica 共用。
- 使用
localcoordination 時,在記憶體中保留最新的 1,000 筆。
-
Panel → Dashboard → Distillation:
- 目前使用的 LLM;
- 過去 24 小時各層的執行次數與失敗率;
- 最近的失敗;
- 各類 job 的 dead letter;
- system admin 可以使用的 Re-run 按鈕。
Generation logs 新增
empty狀態,以及模型、延遲、session、錯誤等欄位。#/logs?status=failed會直接套用篩選。 -
伺服器上的 CLI:
docker compose exec memory-core memory-server generations docker compose exec memory-core memory-server dead-letters docker compose exec memory-core memory-server dead-letters redrive --limit 10
-
API:
POST /v3/memory-generation-log/summary;POST /v3/pipeline/dead-letter/{list,redrive}。
重跑時會把 job 當成第一次嘗試重新排入佇列,最舊的先跑。有多個 replica 時,每一筆只會由其中一個節點取走。
-
指南:docs/ops/DISTILLATION.zh-tw.md 說明會記錄哪些資訊、在哪裡查看、常見的 LLM 失敗原因、如何更換模型,以及如何分批重跑。
修正與其他調整
migrate-to-postgres.sh(#25):搭配MIGRATE_TARGET=postgres-url時,現在會採用在指令上傳入的AGENT_MEMORY_POSTGRES_URL。之前.env裡的空值會把它覆蓋掉,這就是 v0.2.2 的已知問題。amem的skip_prompt_prefixes(#27,@blackhorseya):以設定的前綴開頭的 prompt,例如協調程式自動輸入給 agent 的訊息,不會觸發召回,也不會被擷取。這個設定可以來自AMEM_SKIP_PROMPT_PREFIXES、Claude Code plugin 選項或client.json,預設為空。
感謝 @blackhorseya 貢獻 #27。
Agent Memory v0.2.2
Upgrading
No data or configuration changes. From any version since 0.1.1:
git fetch --tags && git checkout v0.2.2
docker compose up -d --buildUpdate amem on every client. Two of the three fixes are in the client (REMOTE-CLIENTS §4).
Fixes
-
PostgreSQL stores every message (#23). PostgreSQL refuses the character U+0000, which SQLite stores, and a tool that printed binary data was enough to trigger it. That caused two problems:
- On PostgreSQL, live writes containing it failed.
migrate-to-postgres.shstopped withunsupported Unicode escape sequence.
Core now drops U+0000 where text enters, and the migration drops it from data already stored in SQLite.
-
Long replies and long sessions are no longer lost (#22).
amemsent turns that broke Core's request limits:- a message over 8,192 characters;
- more than 100 messages in one request, or more than 500 tool messages.
Core rejected each such turn as a whole, and
amemonly logged it. Long text is now sent as several messages, and requests are split into batches. -
Memories keep the date of the conversation (#21).
amemnow sends the time each message was recorded:- Claude Code: each transcript line's time.
- Antigravity: each step's time.
A turn that is imported or sent later keeps its own date instead of the day it arrived.
Known issue
MIGRATE_TARGET=postgres-url ./migrate-to-postgres.sh --non-interactive ignores AGENT_MEMORY_POSTGRES_URL given on the command line, because the empty value in .env replaces it. Fixed on main (#25). Until the next release, set the URL in .env first.
升級
資料和設定都沒有改變。從 0.1.1 之後的任何版本升級:
git fetch --tags && git checkout v0.2.2
docker compose up -d --build每台 client 都要更新 amem,三個修正裡有兩個在 client 端(REMOTE-CLIENTS §4)。
修正
-
PostgreSQL 可以存下所有訊息(#23)。PostgreSQL 不接受 U+0000 這個字元,但 SQLite 可以存,只要工具印出二進位資料就會觸發。造成兩個問題:
- 在 PostgreSQL 上,含有這個字元的即時寫入會失敗。
migrate-to-postgres.sh會停在unsupported Unicode escape sequence。
現在 Core 會在文字進入時去掉 U+0000,搬移時也會從 SQLite 既有的資料中去掉。
-
長回覆和長 session 不會再遺失(#22)。
amem送出的一輪超過了 Core 的請求上限:- 單則訊息超過 8,192 字元;
- 一次請求超過 100 則訊息,或超過 500 則工具訊息。
Core 會整輪拒絕,
amem只記在 log 裡。現在長文字會拆成多則訊息送出,請求也會分批。 -
記憶保留對話當時的日期(#21)。
amem現在會送出每則訊息被記錄的時間:- Claude Code:transcript 每一行的時間。
- Antigravity:每個 step 的時間。
事後匯入或延遲送出的一輪,會保留它自己的日期,不再是送達那天的日期。
已知問題
MIGRATE_TARGET=postgres-url ./migrate-to-postgres.sh --non-interactive 會忽略在指令上傳入的 AGENT_MEMORY_POSTGRES_URL,因為 .env 裡的空值會把它覆蓋掉。已在 main 修正(#25)。下一版發布之前,請先把 URL 寫進 .env。
Agent Memory v0.2.1
Upgrading
No data or configuration changes. From 0.2.0, or anything since 0.1.1:
git fetch --tags && git checkout v0.2.1
docker compose up -d --buildClients keep working. Update amem when convenient (REMOTE-CLIENTS §4).
Fixes
Clear failure reasons from CLI LLMs (#17, #18, #19, @blackhorseya)
When a CLI LLM such as codex exec failed, the error shown in the Panel's pipeline "last error" and in the logs used to be:
`codex` exited with exit status: 1: OpenAI Codex v0.163.0 -------- workdir: … user <system> You are a scene-segmentation …
It held the first 300 characters of output, which were the banner and the echoed prompt. The real cause, such as Selected model is at capacity, never appeared. Now:
- Only what the tool prints after the echoed prompt is used. The conversation being distilled no longer reaches the logs or the Panel.
- The last line starting with
error:is used, for example codex'sERROR: {…"message": …}. Without such a line, the end of the output is kept. With no output at all, the reason isno error output. - Lengths are counted in characters, so Chinese text is never cut mid-character.
Other
- The project is now under the MIT License, and each
amemarchive includesLICENSE.
Thanks to @blackhorseya for #17, #18 and #19.
升級
資料和設定都沒有改變。從 0.2.0 或 0.1.1 之後的任何版本升級:
git fetch --tags && git checkout v0.2.1
docker compose up -d --buildclient 不受影響,方便時再更新 amem(REMOTE-CLIENTS §4)。
修正
CLI LLM 失敗時會顯示真正的原因(#17、#18、#19,@blackhorseya)
以前 codex exec 這類 CLI LLM 失敗時,Panel 的 pipeline「last error」和 log 裡看到的是:
`codex` exited with exit status: 1: OpenAI Codex v0.163.0 -------- workdir: … user <system> You are a scene-segmentation …
這是輸出的前 300 個字元,內容只有 banner 和回顯的 prompt,真正的原因(例如 Selected model is at capacity)完全看不到。現在:
- 只看工具在回顯 prompt 之後印出的內容,正在蒸餾的對話不會再出現在 log 和 Panel。
- 取最後一行以
error:開頭的內容,例如 codex 的ERROR: {…"message": …}。沒有這種行時保留輸出的結尾;完全沒有輸出時,顯示no error output。 - 長度以字元計算,中文不會被切在字的中間。
其他
- 專案採用 MIT License,每個
amem壓縮檔都附上LICENSE。
感謝 @blackhorseya 貢獻 #17、#18、#19。