hermes-memory-pgvector 0.5.4__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. hermes_memory_pgvector-0.6.0/PKG-INFO +236 -0
  2. hermes_memory_pgvector-0.6.0/README.md +199 -0
  3. hermes_memory_pgvector-0.6.0/hermes_memory_pgvector.egg-info/PKG-INFO +236 -0
  4. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_memory_pgvector.egg-info/SOURCES.txt +9 -1
  5. hermes_memory_pgvector-0.6.0/hermes_memory_pgvector.egg-info/requires.txt +11 -0
  6. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/__init__.py +2149 -1612
  7. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/__main__.py +530 -471
  8. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/embed.py +330 -311
  9. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/identity.py +219 -192
  10. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/migrations/001_schema.sql +95 -95
  11. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/migrations/002_agent_attribution.sql +158 -130
  12. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/migrations/003_hybrid_search_fts.sql +51 -51
  13. hermes_memory_pgvector-0.6.0/hermes_pgvector/migrations/004_runtime_grants.sql +53 -0
  14. hermes_memory_pgvector-0.6.0/hermes_pgvector/migrations/005_content_md5_unique.sql +63 -0
  15. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/plugin.yaml +16 -16
  16. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/store.py +1466 -1259
  17. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_pgvector/writer.py +206 -192
  18. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/pyproject.toml +92 -83
  19. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/setup.cfg +4 -4
  20. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_async_writer.py +110 -110
  21. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_config_coercion.py +184 -112
  22. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_embed_config.py +9 -1
  23. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_embed_timeouts.py +106 -0
  24. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_empty_content.py +332 -332
  25. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_exclude_identities_live.py +197 -197
  26. hermes_memory_pgvector-0.6.0/tests/test_fake_embed_server.py +164 -0
  27. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_hybrid_search.py +124 -123
  28. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_identity.py +298 -298
  29. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_install_shim.py +104 -104
  30. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_save_config_merge.py +68 -68
  31. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_session_switch_contract.py +140 -140
  32. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_smoke.py +319 -316
  33. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_store_v04.py +246 -246
  34. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_system_prompt_block.py +51 -51
  35. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_turn_dedup.py +280 -280
  36. hermes_memory_pgvector-0.6.0/tests/test_v060_hook_hardening.py +136 -0
  37. hermes_memory_pgvector-0.6.0/tests/test_v060_identity_writer.py +278 -0
  38. hermes_memory_pgvector-0.6.0/tests/test_v060_migrations_cli.py +512 -0
  39. hermes_memory_pgvector-0.6.0/tests/test_v060_provider_reads.py +657 -0
  40. hermes_memory_pgvector-0.6.0/tests/test_v060_provider_writes.py +1041 -0
  41. hermes_memory_pgvector-0.6.0/tests/test_v060_store.py +365 -0
  42. hermes_memory_pgvector-0.5.4/PKG-INFO +0 -503
  43. hermes_memory_pgvector-0.5.4/README.md +0 -470
  44. hermes_memory_pgvector-0.5.4/hermes_memory_pgvector.egg-info/PKG-INFO +0 -503
  45. hermes_memory_pgvector-0.5.4/hermes_memory_pgvector.egg-info/requires.txt +0 -6
  46. hermes_memory_pgvector-0.5.4/hermes_pgvector/migrations/004_runtime_grants.sql +0 -36
  47. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/LICENSE +0 -0
  48. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_memory_pgvector.egg-info/dependency_links.txt +0 -0
  49. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_memory_pgvector.egg-info/entry_points.txt +0 -0
  50. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/hermes_memory_pgvector.egg-info/top_level.txt +0 -0
  51. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_loader_embed_clobber.py +0 -0
  52. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_read_side_gate.py +0 -0
  53. {hermes_memory_pgvector-0.5.4 → hermes_memory_pgvector-0.6.0}/tests/test_tool_args_hardening.py +0 -0
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: hermes-memory-pgvector
3
+ Version: 0.6.0
4
+ Summary: Postgres + pgvector memory provider plugin for hermes-agent. Multi-agent storage layer with per-minion themes, identity governance, agent attribution + delegation provenance, async writer, no LLM in the memory hot path.
5
+ Author: Andrea Borghi
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/andreab67/hermes-memory-pgvector
8
+ Project-URL: Source, https://github.com/andreab67/hermes-memory-pgvector
9
+ Project-URL: Issues, https://github.com/andreab67/hermes-memory-pgvector/issues
10
+ Project-URL: Roadmap, https://github.com/andreab67/hermes-memory-pgvector/blob/main/ROADMAP.md
11
+ Keywords: hermes-agent,memory-provider,pgvector,postgres,multi-agent,llm-memory,semantic-search
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Database
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: System :: Distributed Computing
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: psycopg[binary]<4,>=3.3.6
28
+ Requires-Dist: psycopg-pool<4,>=3.3.3
29
+ Requires-Dist: PyYAML<7,>=6.0
30
+ Provides-Extra: test
31
+ Requires-Dist: pytest<9,>=7.4; extra == "test"
32
+ Provides-Extra: dev
33
+ Requires-Dist: build<2,>=1; extra == "dev"
34
+ Requires-Dist: twine<7,>=5; extra == "dev"
35
+ Requires-Dist: ruff<1,>=0.5; extra == "dev"
36
+ Dynamic: license-file
37
+
38
+ # hermes-memory-pgvector
39
+
40
+ **Postgres + pgvector memory provider for [hermes-agent](https://github.com/NousResearch/hermes-agent).** A shared memory substrate for a fleet of cooperating hermes-agent minions — built on Postgres and a single embedding endpoint you probably already run, with no LLM in the memory hot path.
41
+
42
+ ```text
43
+ each minion → X-Hermes-Session-Key: <theme>
44
+ → hermes-agent gateway
45
+ → pgvector plugin
46
+ ├── memory_entries (mirrors built-in MEMORY.md / USER.md per theme)
47
+ └── conversations (every substantive turn, semantically searchable)
48
+ ```
49
+
50
+ ## Why it exists
51
+
52
+ Existing memory providers each solve a piece of the problem; the gap for **fleet deployments** is wide:
53
+
54
+ - **Built-in `memory` tool** persists to per-host `MEMORY.md` / `USER.md`. Two minions on the same host stomp on each other; minions on different hosts have no shared substrate.
55
+ - **Honcho** offers cross-session user modelling but requires a full external service, an LLM in the memory hot path for its deriver + dialectic loops, and its own ontology layered on top of the built-in tool. In high-concurrency fleet use it produces retry storms, embedding-endpoint queue backups, and gateway↔Honcho circular dependencies.
56
+ - **Holographic** is a fine in-process fact store but uses SQLite — a poor fit for many minions writing concurrently from many hosts.
57
+ - **Other providers** (Mem0, Hindsight, OpenViking, ByteRover, RetainDB, Supermemory) all either require a paid cloud, require LLM mediation for memory ops, or both.
58
+
59
+ What was missing: a **storage layer** that gives the built-in `memory` model durable, multi-tenant, semantically-searchable backing, with no LLM in the hot path, scoped cleanly per-minion so a marketing agent's notes don't pollute a trading agent's recall. That's what this plugin provides.
60
+
61
+ ## Design philosophy
62
+
63
+ 1. **Storage layer, not a memory model.** The agent keeps using `memory(action='add', target='memory'|'user', …)`. We mirror those writes via `on_memory_write`. No new ontology for the agent to learn.
64
+ 2. **No LLM in the memory hot path.** Embeddings are vector math, not LLM calls. There is no deriver, no dialectic, no dream cycle.
65
+ 3. **Per-agent themes by default, cross-theme recall on explicit demand.** Every row carries `agent_identity`. Recall is scoped to the current theme unless the agent asks for `scope='all'`.
66
+ 4. **Fail-soft everywhere.** Embed endpoint down → degrade to text-only writes. Async writer queue full → drop with a one-time warning. DB down → log + skip. No exception escapes into the agent loop.
67
+ 5. **Admin/runtime separation.** DDL runs once with superuser via `hermes-pgvector migrate`; the runtime role gets DML only on the migrated schema.
68
+
69
+ ## What it does
70
+
71
+ | Hook / surface | Behavior |
72
+ |---|---|
73
+ | `initialize()` | Verifies schema, opens a `psycopg_pool.ConnectionPool`, bulk-imports existing `MEMORY.md` + `USER.md` content. |
74
+ | `on_memory_write(action, target, content, meta)` | Mirrors built-in `memory` writes into `memory_entries` (add / replace / remove). |
75
+ | `sync_turn(user, assistant, session_id)` / `on_session_end(messages)` | Captures every substantive chat turn into `conversations`; `on_session_end` is a dedup'd backstop. |
76
+ | `on_delegation(task, result, …)` | Records parent→child delegation provenance (`memory_agent_edges`) and stores the exchange as a recallable turn. |
77
+ | `prefetch(query)` / `queue_prefetch(query, session_id=...)` | Ambient recall: top-K similar `memory_entries` for the current theme, injected into the system prompt. `queue_prefetch` pre-computes it off the agent thread. |
78
+ | `recall_memory(query, scope, target, limit)` tool | Explicit cross-theme search of durable memory entries. |
79
+ | `recall_conversation(query, scope, limit)` tool | Explicit search over past chat turns. `scope ∈ {current, session, all, <theme>}`. |
80
+
81
+ Operator maintenance CLI: `hermes-pgvector migrate · stats · backfill · prune · cleanup · remap` (destructive commands default to dry-run) — see [docs/operations.md](docs/operations.md).
82
+
83
+ ## Install
84
+
85
+ ### Option 1: pip + discovery shim (recommended)
86
+
87
+ ```bash
88
+ pip install hermes-memory-pgvector
89
+ hermes-pgvector install # writes $HERMES_HOME/plugins/pgvector/ (older hosts only)
90
+
91
+ # Apply ALL migrations (schema + attribution + FTS + runtime grants + md5 unique index)
92
+ hermes-pgvector migrate --admin-dsn \
93
+ "dbname=<your-memory-db> user=postgres host=/var/run/postgresql"
94
+ # add --runtime-role NAME if your runtime role isn't `hermes`
95
+
96
+ hermes config set memory.provider pgvector
97
+ sudo systemctl restart hermes.service
98
+ hermes memory status # expect: Provider: pgvector; Status: available
99
+ ```
100
+
101
+ **Why the shim?** hermes-agent resolves a provider from bundled dirs, then `$HERMES_HOME/plugins/<name>/`, then the `hermes_agent.memory_providers` pip entry-point group (declared by this package since v0.5.0). On a host that reads the entry point, `pip install` alone is enough and `install` is a no-op you can skip; the shim remains for older hosts that only scan directories. A shim *directory* always wins over the entry point when one is present.
102
+
103
+ ### Option 2: clone + run the installer script (from source)
104
+
105
+ ```bash
106
+ git clone https://github.com/andreab67/hermes-memory-pgvector.git
107
+ cd hermes-memory-pgvector
108
+ ./scripts/install.sh
109
+ ```
110
+
111
+ Installs the pinned Python deps, copies `hermes_pgvector/` into `$HERMES_HOME/plugins/pgvector/`, and prints the migrate/activate commands.
112
+
113
+ ### Option 3: manual
114
+
115
+ ```bash
116
+ # Python deps
117
+ pip install 'psycopg[binary]>=3.3.6,<4' 'psycopg-pool>=3.3.3,<4' 'PyYAML>=6.0,<7'
118
+
119
+ # Plugin module
120
+ mkdir -p ~/.hermes/plugins
121
+ cp -r hermes_pgvector ~/.hermes/plugins/pgvector
122
+ ```
123
+
124
+ Then apply migrations and activate as in Option 1 above (`hermes-pgvector migrate --admin-dsn ...`, or `psql -f` each `migrations/*.sql` in order — see [docs/operations.md](docs/operations.md) for the full admin walkthrough and [docs/upgrading.md](docs/upgrading.md) if you're coming from an older version).
125
+
126
+ ## Configuration
127
+
128
+ Lives in `$HERMES_HOME/config.yaml` under `plugins.pgvector`, every key optional:
129
+
130
+ ```yaml
131
+ plugins:
132
+ pgvector:
133
+ dsn: "dbname=hermes_memory user=hermes host=/var/run/postgresql"
134
+ embed_url: "http://localhost:11434"
135
+ embed_model: "nomic-embed-text"
136
+ allowed_themes: "marketing,sales,trading" # empty/unset = allow any theme
137
+ ```
138
+
139
+ Full reference for every key (type, default, since-version, effect): [docs/configuration.md](docs/configuration.md). Scaling guidance (HNSW tuning, pool sizing, embed timeouts): [docs/scaling.md](docs/scaling.md).
140
+
141
+ ## Multi-agent / per-minion themes
142
+
143
+ Each systemd-run minion sets one header on its OpenAI client; everything else flows automatically:
144
+
145
+ ```python
146
+ client = AsyncOpenAI(
147
+ base_url="http://127.0.0.1:8642/v1",
148
+ api_key=API_KEY,
149
+ default_headers={"X-Hermes-Session-Key": "marketing"}, # ← theme
150
+ )
151
+ ```
152
+
153
+ The gateway plumbs `X-Hermes-Session-Key` through as `gateway_session_key=…` in `MemoryProvider.initialize` kwargs, taking priority over the profile default so unprofiled API traffic doesn't collapse every minion into one shared `default` scope.
154
+
155
+ Convention: lowercase, dash-separated, stable (identities are case-folded automatically — `Marketing` and `marketing` are the same theme). Governed sinks that always exist regardless of your themes: `whatsapp-dm` (collapsed DM/session keys), `external-group` (collapsed group/channel/thread keys), `_bench` (benchmark traffic), `default` (last resort). Set `plugins.pgvector.allowed_themes` to your product/worker list to enforce an allow-list — an unknown or typo'd header then falls back to `default` (one-time warning) instead of silently minting a new theme.
156
+
157
+ ## Compatibility policy
158
+
159
+ This plugin follows semantic versioning on its **public surface**:
160
+
161
+ - `plugins.pgvector.*` config keys (see [docs/configuration.md](docs/configuration.md))
162
+ - Tool names and parameters (`recall_memory`, `recall_conversation`)
163
+ - CLI commands, flags, and exit codes (`hermes-pgvector ...`)
164
+ - Database table/column names
165
+ - The `pgvector` provider name and the package's pip entry point
166
+
167
+ `MemoryStore` and every other Python class/module are **internal** — not covered by semver, safe to change between minor releases. A migration file, once released, is never edited in place; schema changes land as a new numbered migration.
168
+
169
+ ## Support matrix
170
+
171
+ Tested in CI on every push/PR:
172
+
173
+ | Component | Versions |
174
+ |---|---|
175
+ | Python | 3.11, 3.12, 3.13 |
176
+ | PostgreSQL | 16, 17, 18 |
177
+ | pgvector extension | `>= 0.5.0` required; CI uses the version bundled in the `pgvector/pgvector:pg1x` images |
178
+ | hermes-agent | Conformance-tested against the pinned ref in [`conformance/HERMES_AGENT_REF`](conformance/HERMES_AGENT_REF), plus a non-blocking weekly drift check against upstream `main` |
179
+
180
+ ## Docs
181
+
182
+ - [docs/configuration.md](docs/configuration.md) — every config key
183
+ - [docs/operations.md](docs/operations.md) — migrate, backfill, prune, cleanup, remap, stats, alerting
184
+ - [docs/scaling.md](docs/scaling.md) — HNSW tuning, pool sizing, embed latency budgets
185
+ - [docs/troubleshooting.md](docs/troubleshooting.md) — common failures and fixes
186
+ - [docs/upgrading.md](docs/upgrading.md) — version-to-version upgrade procedures
187
+ - [docs/release/RELEASING.md](docs/release/RELEASING.md) — maintainer release checklist
188
+ - [CHANGELOG.md](CHANGELOG.md) — every release, in [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format
189
+ - [ROADMAP.md](ROADMAP.md) — milestones, what shipped where, what's deliberately not planned
190
+ - [SECURITY.md](SECURITY.md) — supported versions, how to report a vulnerability
191
+
192
+ ## Tests
193
+
194
+ ```bash
195
+ pip install -e ".[test]"
196
+ pytest -q # no DB/embed endpoint: everything skips gracefully
197
+
198
+ # Live mode (against a throwaway Postgres + your embed endpoint)
199
+ export PG_TEST_DSN='dbname=hermes_test user=postgres host=/var/run/postgresql'
200
+ export PG_TEST_EMBED_URL='http://your-embed-endpoint:11434'
201
+ pytest -q
202
+ ```
203
+
204
+ ## Rollback
205
+
206
+ ```bash
207
+ hermes config set memory.provider none
208
+ sudo systemctl restart hermes.service
209
+
210
+ # Optional — drop every plugin-owned object (data loss, irreversible). Their
211
+ # sequences and indexes are dropped automatically with the tables; DROP VIEW
212
+ # must run before the tables it selects from.
213
+ sudo -u postgres psql -d <your-memory-db> -c "
214
+ DROP VIEW IF EXISTS v_agent_memory;
215
+ DROP TABLE IF EXISTS memory_maintenance_log;
216
+ DROP TABLE IF EXISTS memory_agent_edges;
217
+ DROP TABLE IF EXISTS memory_agents;
218
+ DROP TABLE IF EXISTS conversations;
219
+ DROP TABLE IF EXISTS memory_entries;
220
+ "
221
+
222
+ # Optional — remove the plugin files
223
+ rm -rf ~/.hermes/plugins/pgvector
224
+ ```
225
+
226
+ ## Why a standalone plugin (not an upstream PR)?
227
+
228
+ Per the hermes-agent [`CONTRIBUTING.md`](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.md): the set of built-in memory providers is closed, and new backends are expected to ship as standalone plugins installed into `~/.hermes/plugins/` or via a pip entry point — exactly what this package does.
229
+
230
+ ## Contributing
231
+
232
+ Bug reports + PRs welcome. Open an issue describing the failure mode + your environment (hermes-agent version, Postgres version, embed endpoint), or a PR with a focused change + test.
233
+
234
+ ## License
235
+
236
+ [BSD 3-Clause](LICENSE) © 2026 Green Yoga Inc
@@ -0,0 +1,199 @@
1
+ # hermes-memory-pgvector
2
+
3
+ **Postgres + pgvector memory provider for [hermes-agent](https://github.com/NousResearch/hermes-agent).** A shared memory substrate for a fleet of cooperating hermes-agent minions — built on Postgres and a single embedding endpoint you probably already run, with no LLM in the memory hot path.
4
+
5
+ ```text
6
+ each minion → X-Hermes-Session-Key: <theme>
7
+ → hermes-agent gateway
8
+ → pgvector plugin
9
+ ├── memory_entries (mirrors built-in MEMORY.md / USER.md per theme)
10
+ └── conversations (every substantive turn, semantically searchable)
11
+ ```
12
+
13
+ ## Why it exists
14
+
15
+ Existing memory providers each solve a piece of the problem; the gap for **fleet deployments** is wide:
16
+
17
+ - **Built-in `memory` tool** persists to per-host `MEMORY.md` / `USER.md`. Two minions on the same host stomp on each other; minions on different hosts have no shared substrate.
18
+ - **Honcho** offers cross-session user modelling but requires a full external service, an LLM in the memory hot path for its deriver + dialectic loops, and its own ontology layered on top of the built-in tool. In high-concurrency fleet use it produces retry storms, embedding-endpoint queue backups, and gateway↔Honcho circular dependencies.
19
+ - **Holographic** is a fine in-process fact store but uses SQLite — a poor fit for many minions writing concurrently from many hosts.
20
+ - **Other providers** (Mem0, Hindsight, OpenViking, ByteRover, RetainDB, Supermemory) all either require a paid cloud, require LLM mediation for memory ops, or both.
21
+
22
+ What was missing: a **storage layer** that gives the built-in `memory` model durable, multi-tenant, semantically-searchable backing, with no LLM in the hot path, scoped cleanly per-minion so a marketing agent's notes don't pollute a trading agent's recall. That's what this plugin provides.
23
+
24
+ ## Design philosophy
25
+
26
+ 1. **Storage layer, not a memory model.** The agent keeps using `memory(action='add', target='memory'|'user', …)`. We mirror those writes via `on_memory_write`. No new ontology for the agent to learn.
27
+ 2. **No LLM in the memory hot path.** Embeddings are vector math, not LLM calls. There is no deriver, no dialectic, no dream cycle.
28
+ 3. **Per-agent themes by default, cross-theme recall on explicit demand.** Every row carries `agent_identity`. Recall is scoped to the current theme unless the agent asks for `scope='all'`.
29
+ 4. **Fail-soft everywhere.** Embed endpoint down → degrade to text-only writes. Async writer queue full → drop with a one-time warning. DB down → log + skip. No exception escapes into the agent loop.
30
+ 5. **Admin/runtime separation.** DDL runs once with superuser via `hermes-pgvector migrate`; the runtime role gets DML only on the migrated schema.
31
+
32
+ ## What it does
33
+
34
+ | Hook / surface | Behavior |
35
+ |---|---|
36
+ | `initialize()` | Verifies schema, opens a `psycopg_pool.ConnectionPool`, bulk-imports existing `MEMORY.md` + `USER.md` content. |
37
+ | `on_memory_write(action, target, content, meta)` | Mirrors built-in `memory` writes into `memory_entries` (add / replace / remove). |
38
+ | `sync_turn(user, assistant, session_id)` / `on_session_end(messages)` | Captures every substantive chat turn into `conversations`; `on_session_end` is a dedup'd backstop. |
39
+ | `on_delegation(task, result, …)` | Records parent→child delegation provenance (`memory_agent_edges`) and stores the exchange as a recallable turn. |
40
+ | `prefetch(query)` / `queue_prefetch(query, session_id=...)` | Ambient recall: top-K similar `memory_entries` for the current theme, injected into the system prompt. `queue_prefetch` pre-computes it off the agent thread. |
41
+ | `recall_memory(query, scope, target, limit)` tool | Explicit cross-theme search of durable memory entries. |
42
+ | `recall_conversation(query, scope, limit)` tool | Explicit search over past chat turns. `scope ∈ {current, session, all, <theme>}`. |
43
+
44
+ Operator maintenance CLI: `hermes-pgvector migrate · stats · backfill · prune · cleanup · remap` (destructive commands default to dry-run) — see [docs/operations.md](docs/operations.md).
45
+
46
+ ## Install
47
+
48
+ ### Option 1: pip + discovery shim (recommended)
49
+
50
+ ```bash
51
+ pip install hermes-memory-pgvector
52
+ hermes-pgvector install # writes $HERMES_HOME/plugins/pgvector/ (older hosts only)
53
+
54
+ # Apply ALL migrations (schema + attribution + FTS + runtime grants + md5 unique index)
55
+ hermes-pgvector migrate --admin-dsn \
56
+ "dbname=<your-memory-db> user=postgres host=/var/run/postgresql"
57
+ # add --runtime-role NAME if your runtime role isn't `hermes`
58
+
59
+ hermes config set memory.provider pgvector
60
+ sudo systemctl restart hermes.service
61
+ hermes memory status # expect: Provider: pgvector; Status: available
62
+ ```
63
+
64
+ **Why the shim?** hermes-agent resolves a provider from bundled dirs, then `$HERMES_HOME/plugins/<name>/`, then the `hermes_agent.memory_providers` pip entry-point group (declared by this package since v0.5.0). On a host that reads the entry point, `pip install` alone is enough and `install` is a no-op you can skip; the shim remains for older hosts that only scan directories. A shim *directory* always wins over the entry point when one is present.
65
+
66
+ ### Option 2: clone + run the installer script (from source)
67
+
68
+ ```bash
69
+ git clone https://github.com/andreab67/hermes-memory-pgvector.git
70
+ cd hermes-memory-pgvector
71
+ ./scripts/install.sh
72
+ ```
73
+
74
+ Installs the pinned Python deps, copies `hermes_pgvector/` into `$HERMES_HOME/plugins/pgvector/`, and prints the migrate/activate commands.
75
+
76
+ ### Option 3: manual
77
+
78
+ ```bash
79
+ # Python deps
80
+ pip install 'psycopg[binary]>=3.3.6,<4' 'psycopg-pool>=3.3.3,<4' 'PyYAML>=6.0,<7'
81
+
82
+ # Plugin module
83
+ mkdir -p ~/.hermes/plugins
84
+ cp -r hermes_pgvector ~/.hermes/plugins/pgvector
85
+ ```
86
+
87
+ Then apply migrations and activate as in Option 1 above (`hermes-pgvector migrate --admin-dsn ...`, or `psql -f` each `migrations/*.sql` in order — see [docs/operations.md](docs/operations.md) for the full admin walkthrough and [docs/upgrading.md](docs/upgrading.md) if you're coming from an older version).
88
+
89
+ ## Configuration
90
+
91
+ Lives in `$HERMES_HOME/config.yaml` under `plugins.pgvector`, every key optional:
92
+
93
+ ```yaml
94
+ plugins:
95
+ pgvector:
96
+ dsn: "dbname=hermes_memory user=hermes host=/var/run/postgresql"
97
+ embed_url: "http://localhost:11434"
98
+ embed_model: "nomic-embed-text"
99
+ allowed_themes: "marketing,sales,trading" # empty/unset = allow any theme
100
+ ```
101
+
102
+ Full reference for every key (type, default, since-version, effect): [docs/configuration.md](docs/configuration.md). Scaling guidance (HNSW tuning, pool sizing, embed timeouts): [docs/scaling.md](docs/scaling.md).
103
+
104
+ ## Multi-agent / per-minion themes
105
+
106
+ Each systemd-run minion sets one header on its OpenAI client; everything else flows automatically:
107
+
108
+ ```python
109
+ client = AsyncOpenAI(
110
+ base_url="http://127.0.0.1:8642/v1",
111
+ api_key=API_KEY,
112
+ default_headers={"X-Hermes-Session-Key": "marketing"}, # ← theme
113
+ )
114
+ ```
115
+
116
+ The gateway plumbs `X-Hermes-Session-Key` through as `gateway_session_key=…` in `MemoryProvider.initialize` kwargs, taking priority over the profile default so unprofiled API traffic doesn't collapse every minion into one shared `default` scope.
117
+
118
+ Convention: lowercase, dash-separated, stable (identities are case-folded automatically — `Marketing` and `marketing` are the same theme). Governed sinks that always exist regardless of your themes: `whatsapp-dm` (collapsed DM/session keys), `external-group` (collapsed group/channel/thread keys), `_bench` (benchmark traffic), `default` (last resort). Set `plugins.pgvector.allowed_themes` to your product/worker list to enforce an allow-list — an unknown or typo'd header then falls back to `default` (one-time warning) instead of silently minting a new theme.
119
+
120
+ ## Compatibility policy
121
+
122
+ This plugin follows semantic versioning on its **public surface**:
123
+
124
+ - `plugins.pgvector.*` config keys (see [docs/configuration.md](docs/configuration.md))
125
+ - Tool names and parameters (`recall_memory`, `recall_conversation`)
126
+ - CLI commands, flags, and exit codes (`hermes-pgvector ...`)
127
+ - Database table/column names
128
+ - The `pgvector` provider name and the package's pip entry point
129
+
130
+ `MemoryStore` and every other Python class/module are **internal** — not covered by semver, safe to change between minor releases. A migration file, once released, is never edited in place; schema changes land as a new numbered migration.
131
+
132
+ ## Support matrix
133
+
134
+ Tested in CI on every push/PR:
135
+
136
+ | Component | Versions |
137
+ |---|---|
138
+ | Python | 3.11, 3.12, 3.13 |
139
+ | PostgreSQL | 16, 17, 18 |
140
+ | pgvector extension | `>= 0.5.0` required; CI uses the version bundled in the `pgvector/pgvector:pg1x` images |
141
+ | hermes-agent | Conformance-tested against the pinned ref in [`conformance/HERMES_AGENT_REF`](conformance/HERMES_AGENT_REF), plus a non-blocking weekly drift check against upstream `main` |
142
+
143
+ ## Docs
144
+
145
+ - [docs/configuration.md](docs/configuration.md) — every config key
146
+ - [docs/operations.md](docs/operations.md) — migrate, backfill, prune, cleanup, remap, stats, alerting
147
+ - [docs/scaling.md](docs/scaling.md) — HNSW tuning, pool sizing, embed latency budgets
148
+ - [docs/troubleshooting.md](docs/troubleshooting.md) — common failures and fixes
149
+ - [docs/upgrading.md](docs/upgrading.md) — version-to-version upgrade procedures
150
+ - [docs/release/RELEASING.md](docs/release/RELEASING.md) — maintainer release checklist
151
+ - [CHANGELOG.md](CHANGELOG.md) — every release, in [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format
152
+ - [ROADMAP.md](ROADMAP.md) — milestones, what shipped where, what's deliberately not planned
153
+ - [SECURITY.md](SECURITY.md) — supported versions, how to report a vulnerability
154
+
155
+ ## Tests
156
+
157
+ ```bash
158
+ pip install -e ".[test]"
159
+ pytest -q # no DB/embed endpoint: everything skips gracefully
160
+
161
+ # Live mode (against a throwaway Postgres + your embed endpoint)
162
+ export PG_TEST_DSN='dbname=hermes_test user=postgres host=/var/run/postgresql'
163
+ export PG_TEST_EMBED_URL='http://your-embed-endpoint:11434'
164
+ pytest -q
165
+ ```
166
+
167
+ ## Rollback
168
+
169
+ ```bash
170
+ hermes config set memory.provider none
171
+ sudo systemctl restart hermes.service
172
+
173
+ # Optional — drop every plugin-owned object (data loss, irreversible). Their
174
+ # sequences and indexes are dropped automatically with the tables; DROP VIEW
175
+ # must run before the tables it selects from.
176
+ sudo -u postgres psql -d <your-memory-db> -c "
177
+ DROP VIEW IF EXISTS v_agent_memory;
178
+ DROP TABLE IF EXISTS memory_maintenance_log;
179
+ DROP TABLE IF EXISTS memory_agent_edges;
180
+ DROP TABLE IF EXISTS memory_agents;
181
+ DROP TABLE IF EXISTS conversations;
182
+ DROP TABLE IF EXISTS memory_entries;
183
+ "
184
+
185
+ # Optional — remove the plugin files
186
+ rm -rf ~/.hermes/plugins/pgvector
187
+ ```
188
+
189
+ ## Why a standalone plugin (not an upstream PR)?
190
+
191
+ Per the hermes-agent [`CONTRIBUTING.md`](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.md): the set of built-in memory providers is closed, and new backends are expected to ship as standalone plugins installed into `~/.hermes/plugins/` or via a pip entry point — exactly what this package does.
192
+
193
+ ## Contributing
194
+
195
+ Bug reports + PRs welcome. Open an issue describing the failure mode + your environment (hermes-agent version, Postgres version, embed endpoint), or a PR with a focused change + test.
196
+
197
+ ## License
198
+
199
+ [BSD 3-Clause](LICENSE) © 2026 Green Yoga Inc