Repository navigation
v0.231.0
Memory and knowledge are now separate stores (ADR 0125). Durable memories move from chunks into a new memories table on first boot, and the memory tools are renamed with no aliases. Read Upgrading before you update an agent whose skills, prompts or plugins call the old tool names. This release also adds named device tokens, tool usage telemetry, PDF page citations for saved artifacts, configurable starter prompts and the Plain Language plugin.
Upgrading (breaking)
- Memory tools are renamed, with no aliases:
memory_ingest→memory_save,memory_recall→memory_search,forget_memory→memory_forget.memory_statsis folded intomemory_list, which now ends with a per-kind total. Ingested documents are searched with the newknowledge_search(collection=…), andknowledge_ingest'sdomain=argument is nowcollection=. (#4799) - The one exception is subagent tool lists. Config, plugin and built-in subagent lists that name an old tool are translated to the new name at resolve time, with a warning. An unknown tool name in a subagent list now warns instead of vanishing silently. Skills, prompts and SOUL files that name the old tools are not translated, so update them. (#4817)
- One-time boot migration. On first start, durable memories move from
chunksintomemories, routed bysource_type. Operator-curated knowledge documents stay inchunks, which gains acollectioncolumn. The migration runs in one transaction after a backup toagent.db.pre-0125-p2, and it is idempotent. (#4793, #4799) - Plugin SDK:
memory_searchandmemory_saveare new.knowledge_searchandknowledge_addkeep theirdomain=signature. - Fleet plugins whose skills, prompts or tool calls use the old names need a release that raises their core floor to 0.231.0.
- Shared operator profile is opt-in.
memory.shared_profile(Settings ▸ Memory) is off by default. Nothing changes unless you turn it on. (#4827, #4837) - Plain Language is on by default. To turn it off, add
plugins: { disabled: [plain_language] }. (#4767)
Added
- Memory store and review. There is a new core
memoriesstore (#4790). Chat deletion also forgets that chat's memories (#4796). A Memory inspector Review tab lets you keep, edit, forget, reject or revert migrated memories and promote profile facts into the shared profile; nothing promotes automatically (#4838, #4841). - Supersession on save. A
memory_savewith asubjectretires matching pending agent/extracted rows on the same subject, kind and scope, and reports what it replaced. Operator-authored, confirmed and always-on rows are kept. A revert API (POST /api/memory/memories/{id}/revert) swaps a row back (#4826). Session-end fact extraction goes through the same path (#4825, #4839). - Status-log nudge. A subject-less
memory_savethat reads like a work-status log (PR merged, card shipped) still saves, but suggests the board, issue or PR instead (#4840). - Shared operator profile. When enabled, confirmed rows from a host-shared
profile.dbare delivered under "Operator profile (shared)".memory_save(shared=True)proposes a pending row for operator review. A private row on the same subject and kind wins (#4827, #4837). - Named device tokens without pairing.
POST /api/devicesand a "New access token" button in Settings ▸ Devices mint an audited, revocable device-scope token, shown once (#4787, #4792). Thedevice.mintedaudit entry records who minted it (#4846). - Tool usage telemetry. Content-free per-tool call metadata, reported by
GET /api/telemetry/toolsandprotoagent usage --by-toolwith--since,--fleetand--json(#4791, #4794). - PDF artifacts.
cite_artifact(artifact_id, page)opens an already-saved PDF artifact at a page (#4762, #4763, #4764).open_artifactopens a file artifact in the operator's browser (#4778). - Starter prompts per agent. Configure them with the
chat.show_starter_promptsandchat.starter_promptskeys, or in the Settings ▸ Chat editor (#4766, #4768, #4769). - Plain Language plugin. Writing rules from digital.gov's plain language guide, plus
/plain-review,/paraphrase-testandplain_language_check(#4767). - Fleet and friction.
protoagent fleet status --pluginsshows each member's loaded plugins and versions (#4785).record_frictiontakes an optionaltool=and stores the owning plugin (#4784). - Console. ⌘/Ctrl+[ and ⌘/Ctrl+] switch chat tabs (#4797). Chat blockquotes have a Copy button (#4798). The Inventory plugin is listed in Discover (#4759).
Changed
- Per-turn injection gives memory and knowledge separate budgets and labelled sections, so a large knowledge collection can no longer push out always-on memory (#4829).
- The Memory inspector reads memories, and
/api/memory/statssplits counts across memory, knowledge and history (#4815, #4830). - Built-in subagents, the operator MCP allowlist, the ACP runtime,
execute_code, zed-acp, the setup wizard, the eval harness, bundled skills and the docs all use the new tool names (#4814, #4816, #4818, #4819, #4820, #4821, #4822, #4823, #4824, #4828, #4844). protoagent fleet friction resolvetakes several ids, and--agentaccepts the workspace name (#4774). Friction detail keeps about 2,000 characters, head plus tail, instead of a 600-character clip (#4782, #4795).- Closing an empty chat tab no longer asks for confirmation (#4788).
- A delegation's live tool calls render as design-system tool cards (#4812).
Fixed
- The fleet hub releases a member connection when a proxied client leaves. Before this, held connections could fill the pool and leave the console stuck on "Loading…" (#4811).
- A plugin view subscribed with
background: trueno longer reloads itself, and a view on two docks mounts once (#4813, #4842). - A plugin page's published topic keeps all its segments (#4843).
- A plugin id can't match a core data directory, so
plugin_store()can't land in core's data. The testkit also stubsplugin_storeto a temp directory (#4845). recall_sessionlists the newest history entries first, with readable excerpts (#4777).- A second identical background
delegate_toto the same target is refused while the first is running; useforce=trueto send it anyway (#4835). - Goal kickoff names the verifier, so a goal with a command verifier isn't abandoned on iteration 0 (#4834).
eval_rerun_casefailures include the error message, the exit code and a stderr tail (#4836).
Docs
- The README gains a "Why protoAgent?" section (#4771), and the homepage gains a "For developers" section (#4770).
What's Changed
- feat(catalog): list the Inventory plugin in Discover and on the plugins page by @mabry1985 in #4759
- feat: Artifacts (1/3): one shared PDF page-hint helper used by save_file_artifact's copied and linked paths; a refused preview no longer claims "opens at page N" (#4761) by @mabry1985 in #4762
- feat: Artifacts (2/3): read-only cite_artifact(artifact_id, page, version) cites a page of an already-saved PDF artifact via the shared page-hint helper (#4761) by @mabry1985 in #4763
- feat: Artifacts (3/3): docs — README PDF section, rendering-artifacts skill and save_file_artifact's page docstring state the page rules once and point at cite_artifact (#4761) by @mabry1985 in #4764
- feat: Starter prompts (1/2, server): chat.show_starter_prompts + chat.starter_prompts config, resolved list served in runtime status by @mabry1985 in #4766
- feat: Starter prompts (2/2, console): the empty chat renders runtime.starter_prompts, hides the block when it is empty, and falls back to built-ins on an older server by @mabry1985 in #4768
- feat: Starter prompts (3/3, editor): Settings ▸ Chat gets a per-agent "Starter prompts" editor (show/hide, add, edit, remove, reorder, reset to defaults) by @mabry1985 in #4769
- feat(plugins): plain_language — clearer writing from digital.gov's plain language guide by @mabry1985 in #4767
- docs(readme): add a "Why protoAgent?" section, put the feature tour before Repository layout, and link ROADMAP.md by @mabry1985 in #4771
- feat: site(home): add a "For developers" section that says protoAgent hands coding work to Claude Code and Codex by @mabry1985 in #4770
- fix(changelog,site): correct the PR numbers in the bd-6krc6 / bd-dlgvs fragments, and stop the homepage claiming state is "on your machine" for headless installs by @mabry1985 in #4772
- feat: recall_session lists the NEWEST history entries with excerpts; session_search hits carry a readable entry id (protoAgent#4776) by @mabry1985 in #4777
- feat: open_artifact tool: open a file artifact in the operator's browser (protoAgent#4775) by @mabry1985 in #4778
- feat: Friction detail keeps ~2000 chars (head + tail) instead of a 600-char clip (protoAgent#4779) by @mabry1985 in #4782
- feat(fleet): friction resolve takes several ids; triage skill runs auto-approvable commands by @mabry1985 in #4774
- feat: record_friction takes an optional tool arg; ledger rows carry tool + owning plugin (protoAgent#4780) by @mabry1985 in #4784
- feat: protoagent fleet status --plugins lists each member's loaded plugin ids + versions (protoAgent#4781) by @mabry1985 in #4785
- feat: Devices (1/2, server): POST /api/devices mints a named device-scope access token with no pairing code; full-scope callers only, audited, token returned once (#4683) by @mabry1985 in #4787
- feat: Chat tab ✕ on an empty chat closes it with no confirm dialog (#4783) by @mabry1985 in #4788
- feat: ADR 0125 P2-A1: memories store (schema, FTS5 + vectors, CRUD) wired as STATE.memory_store; no readers yet (#4630 slice 1a) by @mabry1985 in #4790
- feat: Telemetry (1/2): tool_calls table written by AuditMiddleware for every lead + subagent tool call (#4786) by @mabry1985 in #4791
- feat: Devices (2/2, console): Settings ▸ Devices gets a "New access token" button that mints a named device-scope token via POST /api/devices and shows it once (#4683) by @mabry1985 in #4792
- feat: ADR 0125 P2-B: boot migration moves memory rows from chunks into memories, routed by source_type; chunks gains collection (#4630 slice 4) by @mabry1985 in #4793
- feat: Telemetry (2/2): GET /api/telemetry/tools +
protoagent usage --by-tool [--since] [--fleet] [--json](#4786) by @mabry1985 in #4794 - feat: ADR 0125 P2-A2: chat-delete forget covers memories rows in the same transaction as chunks + history (#4630 slice 1b) by @mabry1985 in #4796
- feat: Console: bump @protolabsai/ui + ui-css to ^0.70.0 so chat blockquotes get a "Copy quote" button (#4773) by @mabry1985 in #4798
- feat: Console: ⌘/Ctrl+[ and ⌘/Ctrl+] switch to the previous / next chat tab (alongside Ctrl+Tab) by @mabry1985 in #4797
- feat: Console: a delegation's live tool calls render as DS ToolCards (status glyph, mono name) instead of the bespoke checkmark list by @mabry1985 in #4812
- docs(friction): the detail cap is 2000 chars, head + tail by @mabry1985 in #4795
- feat: ADR 0125 P2-D1: switch-over: memory_save/memory_search/memory_list/memory_forget on memories, knowledge_search on chunks, boot migration wired, old tool names removed (#4630 slice 2) by @mabry1985 in #4799
- feat: ADR 0125 P2-D2e: knowledge package docstrings/comments describe the memories/chunks split and the new tool names (#4630) by @mabry1985 in #4814
- feat: ADR 0125 P2-E1: reference docs (memory-delivery, knowledge, starter-tools, mcp) describe memories vs knowledge and the new tool names (#4630) by @mabry1985 in #4816
- feat: ADR 0125 P2-E5: eval harness (runner, sweep, verify, tasks.json) scores memory_save/memory_search/knowledge_search (#4630) by @mabry1985 in #4818
- feat: ADR 0125 P2-D2c: operator MCP allowlist, ACP runtime tool rules and console tool labels use the new memory/knowledge tool names (#4630) by @mabry1985 in #4819
- feat: ADR 0125 P2-E4: bundled cowork/engineer skills and the memory-hardening dev doc use the new memory tool names (#4630) by @mabry1985 in #4821
- feat: ADR 0125 P2-D2f: harvest, settings schema, knowledge middleware and chat routes text use the new memory tool names (#4630) by @mabry1985 in #4820
- feat: ADR 0125 P2-D2b: subagent tool lists (config AND plugin-registered) translate the old memory tool names at resolve time with a warning; an unknown subagent tool name warns instead of vanishing (#4630) by @mabry1985 in #4817
- feat: ADR 0125 P2-D4: Memory inspector server routes read memories (hot list/edit/delete, a memories review verdict, stats split three ways) (#4630) by @mabry1985 in #4815
- feat: ADR 0125 P2-E3: acp-runtime + evals guides, tuning-and-cost and the ADR 0125 status line updated for Phase 2 (#4630) by @mabry1985 in #4824
- feat: ADR 0125 P2-G1: shared operator profile store (/profile.db, memories schema, profile|standing only) + memory.shared_profile setting, off by default (#4630 slice 5a) by @mabry1985 in #4827
- feat: ADR 0125 P2-D2a: built-in subagents + self-improvement review name memory_save/memory_search/memory_forget (#4630) by @mabry1985 in #4822
- feat: ADR 0125 P2-E2: configuration + env-var reference and the ingestion/subagents guides use the new memory tool names (#4630) by @mabry1985 in #4828
- feat: ADR 0125 P2-D2d: execute_code tool bridge, zed-acp integration and the setup wizard use the new memory tool names (#4630) by @mabry1985 in #4823
- feat: ADR 0125 P2-D5: Memory inspector Hot panel sends review verdicts for memories rows to the memories route; e2e mock serves memories-shaped hot rows (#4630) by @mabry1985 in #4830
- feat: ADR 0125 P2-F: projection gives memory and knowledge separate budgets and labelled sections; a 1,200-chunk collection can't push out always-on memory (#4630 slice 3) by @mabry1985 in #4829
- feat: Goal kickoff names the verifier, so an operator-set goal isn't abandoned on iteration 0 (protoAgent#4833) by @mabry1985 in #4834
- feat: delegate_to refuses a duplicate background delegation to the same peer while the first is still running (protoAgent#4832) by @mabry1985 in #4835
- feat: ADR 0125 P2-D3: the retirement extractor writes facts to memories (provenance=extracted), keeping its subject supersession inside memories (#4630) by @mabry1985 in #4825
- feat: eval_rerun_case returns the error message, exit code and stderr tail, not just "ValueError" (protoAgent#4831) by @mabry1985 in #4836
- feat: ADR 0125 P3-A: memory_save supersedes the live row on the same subject+kind, returns what it replaced and the live rows on that subject; inspector revert route (#4631 slice 1) by @mabry1985 in #4826
- feat: ADR 0125 P2-G2: opted-in agents receive confirmed shared-profile rows under "Operator profile (shared)" (a private row on the same subject+kind wins); memory_save(shared=True) proposes a pending row (#4630 slice 5b) by @mabry1985 in #4837
- feat: ADR 0125 P3-C: the retirement extractor saves through the supersession funnel, so an extracted fact and the agent's own row on the same subject settle to one live row ($185K/$120K test) (#4631 slice 3) by @mabry1985 in #4839
- feat: ADR 0125 P3-B: a status-line memory_save still saves but returns a nudge to the board/issue; tool description + operating model say what's worth saving (#4631 slice 2) by @mabry1985 in #4840
- feat: ADR 0125 P3-D1: review-pass server routes: list every memory with filters, edit kind/subject/content, and promote kind=profile rows into the shared profile once per subject (#4631 slice 4a) by @mabry1985 in #4838
- fix(fleet): release the member connection when a proxied client leaves by @mabry1985 in #4811
- fix(console): a background:true subscribe no longer reloads the plugin view (#4802) by @mabry1985 in #4813
- feat: ADR 0125 P3-D2: Memory inspector "Review" tab: keep / edit / forget migrated memories, set subject and kind, revert a supersession, confirm profile candidates into the shared profile (#4631 slice 4b) by @mabry1985 in #4841
- test(console): a view on two docks mounts one copy (#4813 follow-up) by @mabry1985 in #4842
- fix(console): a page's protoagent:publish keeps its topic segments: prefix the plugin id only when missing, like registry.emit (#4801) by @mabry1985 in #4843
- fix(config): web-research skill and engineer preset use the new memory tool names by @mabry1985 in #4844
- fix(plugins): reserve core store names as plugin ids so plugin_store can't land in core's directory; testkit stubs plugin_store to a temp dir (#4808 part 1) by @mabry1985 in #4845
- fix(devices): the device.minted audit entry records who minted the token by @mabry1985 in #4846
Full Changelog: v0.230.0...v0.231.0