Skip to content

Releases: hsuanshao/AgentMemory

v0.4.3 — security release: hashed user keys, throttled and audited key checks, HTTPS profile, JSON distillation input

Choose a tag to compare

@github-actions github-actions released this 24 Oct 02:48
Immutable release. Only release title and notes can be modified.
f433d90

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.sh

Then 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/upgrade issues a key only along with legacy data to move, or with AGENT_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-For counts 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.
  • amem closes 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-admin creates one administrator when called at once.

What's new

  • New installs keep the ports on this machine. install.sh asks 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 tls Compose 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

Choose a tag to compare

@github-actions github-actions released this 23 Oct 17:01
Immutable release. Only release title and notes can be modified.
30b62dc

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.sh

Then 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/overview and 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.passEnv names, never AGENT_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 reembed does it on demand. Embedding concurrency and timeouts can be set by environment.
  • /v3/session/add stores 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

Choose a tag to compare

@github-actions github-actions released this 23 Oct 02:41
Immutable release. Only release title and notes can be modified.
15c3141

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.sh

Schema migration 3 runs when memory-core starts:

  • every version in profile_files is copied into scenes, scene_versions and persona_versions;
  • profile_files is 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/rm each add a version.
    • Clearing a chat memory is the one operation that deletes history.
  • 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 by scene_id once another scene takes their name.
    • read returns each version's op, parents and author.
  • 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

Choose a tag to compare

@github-actions github-actions released this 22 Oct 02:47
Immutable release. Only release title and notes can be modified.
158399a

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 amem client 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 than read-only;
  • codex -c settings 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.sh

upgrade.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, default auto):

    • claude runs with 0 tools and no MCP servers;
    • codex runs 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_REQUEST and is dropped without retries, like a refused CLI call. An answer next to a stray tool call is kept.

  • memory-server check-config validates the configuration without starting the server.

  • upgrade.sh rolls 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。amem client 和各工具的 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.sh

upgrade.sh 會先建置新版本並檢查你的設定,通過後才啟動。如果檢查、建置或啟動失敗,會還原 .env,並用原本的 image 重新執行舊版本。這一版不需要遷移資料。升級後請更新每台 client 的 amem(REMOTE-CLIENTS 第 4 節)。

詳見 UPGRADE → 升級到 0.4.0。

新功能

蒸餾模型不會拿到任何工具(#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

Choose a tag to compare

@github-actions github-actions released this 21 Oct 04:12
Immutable release. Only release title and notes can be modified.
a3235c1

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.sh

Then 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 /health counts 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 worker section (defaults in brackets):

    • deadLetterTtlHours (24);
    • deadLetterMaxRedrives (3);
    • deadLetterRedriveAfterMinutes (60);
    • deadLetterSweepSeconds (300);
    • deadLetterRedriveBatch (10).

    See docs/ops/DISTILLATION.md §5.

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)。

    詳見 docs/ops/DISTILLATION.zh-tw.md 第 5 節。

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

Choose a tag to compare

@github-actions github-actions released this 20 Oct 16:10
Immutable release. Only release title and notes can be modified.
17ac26f

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.sh

From 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 dropped with 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 dropped log filter;
    • the dropped range on dead letters.
  • CLI: memory-server generations --status dropped.

Fixed

  • upgrade.sh dumps an external Postgres with the matching pg_dump (#35).
    • It first reads the server's version.
    • It then runs pg_dump from postgres:<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 .env rename (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

Choose a tag to compare

@github-actions github-actions released this 20 Oct 15:18
Immutable release. Only release title and notes can be modified.
9e6b595

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:

  1. 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.

  2. On the server:

    git fetch --tags && git checkout v0.3.0
    ./upgrade.sh

    upgrade.sh backs up the data, renames CORE_INSTANCE_ID to CORE_DEPARTMENT_ID in .env and 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.

  3. Update amem on every client machine. It rewrites service_id to department_id in client.json by 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.
  • memory-core migrates at start-up under a lock, so with several replicas only one migrates. memory-server migrate does 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.

  • /health no 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/status applied limit before filtering. Session rows shared one table key, and l2_pending was null on 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 要一起更新:

  1. 停掉會寫入伺服器的 agent。如果跑了多個 memory-core replica,要全部停掉:舊版 replica 讀不懂遷移後的資料。

  2. 在伺服器上執行:

    git fetch --tags && git checkout v0.3.0
    ./upgrade.sh

    upgrade.sh 會備份資料、把 .env 的 CORE_INSTANCE_ID 改成 CORE_DEPARTMENT_ID,然後重建服務。memory-core 啟動時會遷移儲存的資料。遷移只能往前:要回到 0.2.x,必須還原那份備份。

  3. 更新每台 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。
  • memory-core 啟動時會在 lock 之下自動遷移,所以有多個 replica 時只會由一個執行。memory-server migrate 可以手動執行同樣的步驟,也會一次把每個 SQLite 部門都遷移完。

  • 第 1 號遷移改寫 0.2 存下的資料:

    • 資料目錄;
    • system.db;
    • Postgres 的 registry、prompt 目標和配額名稱(保留你設定的值);
    • Redis 的 index、狀態文件、佇列中的 job 和 dead letter。

    第 2 號遷移把 reviewer 改成 member。

  • 如何新增遷移:docs/ops/SCHEMA-MIGRATIONS.zh-tw.md。

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

Choose a tag to compare

@github-actions github-actions released this 20 Oct 13:31
Immutable release. Only release title and notes can be modified.
6d3b93d

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 local coordination 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 --build

Dead 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) or failed with 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 local coordination, 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 empty status, plus model, latency, session and error columns. #/logs?status=failed opens 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 honours AGENT_MEMORY_POSTGRES_URL given on the command line with MIGRATE_TARGET=postgres-url. Before, the empty value in .env replaced it, which was the known issue in v0.2.2.
  • amem skip_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 from AMEM_SKIP_PROMPT_PREFIXES, the Claude Code plugin option, or client.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 沒有保存錯誤原因。使用 local coordination 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 共用。
    • 使用 local coordination 時,在記憶體中保留最新的 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

Choose a tag to compare

@github-actions github-actions released this 20 Oct 12:01
Immutable release. Only release title and notes can be modified.
ea2259a

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 --build

Update 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.sh stopped with unsupported 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). amem sent 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 amem only logged it. Long text is now sent as several messages, and requests are split into batches.

  • Memories keep the date of the conversation (#21). amem now 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

Choose a tag to compare

@github-actions github-actions released this 20 Oct 10:40
Immutable release. Only release title and notes can be modified.
85894b5

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 --build

Clients 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's ERROR: {…"message": …}. Without such a line, the end of the output is kept. With no output at all, the reason is no 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 amem archive includes LICENSE.

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 --build

client 不受影響,方便時再更新 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。