hermes-memory-pgvector 0.3.0__py3-none-any.whl

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.
@@ -0,0 +1,260 @@
1
+ Metadata-Version: 2.4
2
+ Name: hermes-memory-pgvector
3
+ Version: 0.3.0
4
+ Summary: Postgres + pgvector memory provider plugin for hermes-agent. Multi-agent storage layer with per-minion themes, 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.4
28
+ Requires-Dist: psycopg-pool<4,>=3.3.1
29
+ Requires-Dist: PyYAML<7,>=6.0
30
+ Provides-Extra: test
31
+ Requires-Dist: pytest<9,>=7.4; extra == "test"
32
+ Dynamic: license-file
33
+
34
+ # hermes-memory-pgvector
35
+
36
+ **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.
37
+
38
+ ```text
39
+ each minion → X-Hermes-Session-Key: <theme>
40
+ → hermes-agent gateway
41
+ → pgvector plugin
42
+ ├── memory_entries (mirrors built-in MEMORY.md / USER.md per theme)
43
+ └── conversations (every substantive turn, semantically searchable)
44
+ ```
45
+
46
+ ## Why it exists
47
+
48
+ Existing memory providers each solve a piece of the problem; the gap for **fleet deployments** is wide:
49
+
50
+ - **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.
51
+ - **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.
52
+ - **Holographic** is a fine in-process fact store but uses SQLite — a poor fit for many minions writing concurrently from many hosts.
53
+ - **Other providers** (Mem0, Hindsight, OpenViking, ByteRover, RetainDB, Supermemory) all either require a paid cloud, require LLM mediation for memory ops, or both.
54
+
55
+ 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.
56
+
57
+ ## Design philosophy
58
+
59
+ 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.
60
+ 2. **No LLM in the memory hot path.** Embeddings are vector math, not LLM calls. There is no deriver, no dialectic, no dream cycle — the failure modes that hurt Honcho cannot occur here by construction.
61
+ 3. **Per-agent themes by default, cross-theme recall on explicit demand.** Every row carries `agent_identity` (resolved from `X-Hermes-Session-Key` header, profile name, workspace, or `'default'`). Recall is scoped to the current theme unless the agent asks for `scope='all'`.
62
+ 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.
63
+ 5. **Admin/runtime separation.** DDL (`CREATE EXTENSION vector`, `CREATE TABLE`, `CREATE INDEX`) runs once with superuser. The runtime user has DML only on the migrated schema. `ensure_schema()` at runtime is verify-only with a clear `SchemaNotApplied` error if the operator forgot the migration.
64
+
65
+ ## Features (v0.3.0)
66
+
67
+ | Hook / surface | Behavior |
68
+ |---|---|
69
+ | `initialize()` | Verifies schema, opens `psycopg_pool.ConnectionPool`, bulk-imports existing `MEMORY.md` + `USER.md` content. |
70
+ | `on_memory_write(action, target, content, meta)` | Mirrors built-in `memory` writes into `memory_entries` (add / replace / remove). |
71
+ | `sync_turn(user, assistant, session_id)` | Captures every substantive (`>= 40` chars + not boilerplate) chat turn into `conversations`. |
72
+ | `prefetch(query)` | Top-K semantically similar `memory_entries` in current theme, injected ambient. |
73
+ | `recall_memory(query, scope, target, limit)` tool | Explicit cross-theme search of durable memory entries. |
74
+ | `recall_conversation(query, scope, limit)` tool | Explicit search over past chat turns. `scope ∈ {current, session, all, <theme>}`. |
75
+
76
+ Internals:
77
+
78
+ - **`psycopg_pool.ConnectionPool`** (min=1, max=4, lazy + thread-safe) shared across the agent thread and the async-writer drain thread.
79
+ - **`AsyncWriter`** — bounded queue + daemon drain thread. Memory write hooks return in microseconds. Worker embeds + writes in the background. Crash-resilient (auto-restart on next enqueue).
80
+ - **Single migration** (`pgvector/migrations/001_schema.sql`) — `memory_entries` + `conversations` + HNSW indexes. Same tuning operators typically use elsewhere.
81
+ - **Boilerplate filter** for turn capture — length floor + acknowledgement regex (`"ok"`, `"thanks"`, `"continue"`, …) so the recall table stays high-signal.
82
+
83
+ ## Multi-agent / per-minion themes
84
+
85
+ Each systemd-run minion sets one header on its OpenAI client; everything else flows automatically:
86
+
87
+ ```python
88
+ client = AsyncOpenAI(
89
+ base_url="http://127.0.0.1:8642/v1",
90
+ api_key=API_KEY,
91
+ default_headers={"X-Hermes-Session-Key": "marketing"}, # ← theme
92
+ )
93
+ ```
94
+
95
+ The gateway plumbs `X-Hermes-Session-Key` through as `gateway_session_key=…` in `MemoryProvider.initialize` kwargs. The plugin reads it with **priority over the profile default**, so `agent_identity='default'` from unprofiled API traffic does not collapse every minion into one shared scope.
96
+
97
+ Convention: lowercase, dash-separated, stable. Examples that work well:
98
+
99
+ - `marketing`, `sales`, `morning-report`, `incident`
100
+ - `intraday-<agent_name>` for fan-out workers (e.g. `intraday-trading`, `intraday-sre`, `intraday-marketing`)
101
+
102
+ ## Install
103
+
104
+ ### Option 1: clone + run the installer script (recommended)
105
+
106
+ ```bash
107
+ git clone https://github.com/andreab67/hermes-memory-pgvector.git
108
+ cd hermes-memory-pgvector
109
+ ./scripts/install.sh
110
+ ```
111
+
112
+ That:
113
+
114
+ 1. `pip install`s `psycopg[binary]`, `psycopg-pool`, `PyYAML` (with the upper-bound pins).
115
+ 2. Copies `pgvector/` into `$HERMES_HOME/plugins/pgvector/` (defaults to `~/.hermes/plugins/pgvector/`).
116
+ 3. Prints the admin migration + activation commands you run next.
117
+
118
+ ### Option 2: manual
119
+
120
+ ```bash
121
+ # Python deps
122
+ pip install 'psycopg[binary]>=3.3.4,<4' 'psycopg-pool>=3.3.1,<4' 'PyYAML>=6.0,<7'
123
+
124
+ # Plugin module
125
+ mkdir -p ~/.hermes/plugins
126
+ cp -r pgvector ~/.hermes/plugins/pgvector
127
+ ```
128
+
129
+ ### Then (admin once)
130
+
131
+ ```bash
132
+ # Apply the schema migration (CREATE EXTENSION needs superuser)
133
+ sudo -u postgres psql -d <your-memory-db> \
134
+ -f ~/.hermes/plugins/pgvector/migrations/001_schema.sql
135
+
136
+ # Hand ownership of the new tables to the hermes runtime role
137
+ sudo -u postgres psql -d <your-memory-db> -c "
138
+ ALTER TABLE memory_entries OWNER TO hermes;
139
+ ALTER SEQUENCE memory_entries_id_seq OWNER TO hermes;
140
+ ALTER TABLE conversations OWNER TO hermes;
141
+ ALTER SEQUENCE conversations_id_seq OWNER TO hermes;
142
+ "
143
+
144
+ # Activate
145
+ hermes config set memory.provider pgvector
146
+ sudo systemctl restart hermes.service # or however you run hermes
147
+ hermes memory status # expect: Provider: pgvector; Status: available
148
+ ```
149
+
150
+ ## Configuration
151
+
152
+ Lives in `$HERMES_HOME/config.yaml` under `plugins.pgvector` — every value optional, sensible defaults shown:
153
+
154
+ ```yaml
155
+ plugins:
156
+ pgvector:
157
+ dsn: "dbname=hermes_memory user=hermes host=/var/run/postgresql"
158
+ embed_url: "http://your-embed-endpoint:11434"
159
+ embed_model: "nomic-embed-text"
160
+ prefetch_limit: 5
161
+ min_similarity: 0.30
162
+ embed_on_write: true
163
+ scope_default: "current"
164
+ write_queue_maxsize: 256
165
+ bulk_sync_on_init: true
166
+ sync_turns: true
167
+ turn_min_chars: 40
168
+ ```
169
+
170
+ The embed endpoint can be any OpenAI-compatible `/v1/embeddings` or Ollama-native `/api/embed` URL that returns **768-dim vectors** (the schema is hard-coded to `vector(768)` to match `nomic-embed-text`). Use a different model only if it produces 768-dim output, or edit the migration before applying it.
171
+
172
+ ## Schema
173
+
174
+ ```sql
175
+ CREATE TABLE memory_entries (
176
+ id BIGSERIAL PRIMARY KEY,
177
+ agent_identity TEXT NOT NULL DEFAULT 'default',
178
+ target TEXT NOT NULL CHECK (target IN ('memory', 'user')),
179
+ content TEXT NOT NULL,
180
+ embedding vector(768),
181
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
182
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
183
+ metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
184
+ UNIQUE (agent_identity, target, content)
185
+ );
186
+
187
+ CREATE TABLE conversations (
188
+ id BIGSERIAL PRIMARY KEY,
189
+ session_id TEXT NOT NULL,
190
+ agent_identity TEXT NOT NULL DEFAULT 'default',
191
+ role TEXT NOT NULL CHECK (role IN ('user','assistant','system','tool')),
192
+ content TEXT NOT NULL,
193
+ ts TIMESTAMPTZ NOT NULL DEFAULT now(),
194
+ embedding vector(768),
195
+ metadata JSONB NOT NULL DEFAULT '{}'::jsonb
196
+ );
197
+ ```
198
+
199
+ Indexes: HNSW on each `embedding` column (m=16, ef_construction=64) plus per-agent + per-session btree timelines. Full DDL in [`pgvector/migrations/001_schema.sql`](pgvector/migrations/001_schema.sql).
200
+
201
+ ## Tests
202
+
203
+ ```bash
204
+ pip install -e ".[test]"
205
+
206
+ # Skip mode (no DB, no embed endpoint): everything skips gracefully
207
+ pytest tests/
208
+
209
+ # Live mode (against a throwaway Postgres + your embed endpoint)
210
+ export PG_TEST_DSN='dbname=hermes_test user=postgres host=/var/run/postgresql'
211
+ export PG_TEST_EMBED_URL='http://your-embed-endpoint:11434'
212
+ pytest tests/
213
+ ```
214
+
215
+ DB tests skip when `PG_TEST_DSN` is unset; live embed tests skip when `PG_TEST_EMBED_URL` is unset.
216
+
217
+ ## Roadmap
218
+
219
+ See [`ROADMAP.md`](ROADMAP.md) for the full milestone table. Highlights:
220
+
221
+ - **M1 (v0.1, v0.1.1)** ✅ Shared storage with per-agent themes, async writer, connection pool, bulk import from `MEMORY.md`/`USER.md`
222
+ - **M2 (v0.2)** ✅ Conversation transcript table with `sync_turn` capture + `recall_conversation` tool
223
+ - **M3 (v0.3)** ✅ Identity propagation for stateless API minions via `X-Hermes-Session-Key`
224
+ - **M4 (v0.4)** ⏳ `on_delegation()` + `on_session_end()` capture for agent-of-agents observability
225
+ - **M5 (v0.5–v0.6)** ⏳ TTL/decay, partial HNSW indexes per-theme, metrics, bulk-import CLI
226
+ - **M6 (v1.0)** ⏳ Stable config schema, full docs, CI coverage
227
+
228
+ The roadmap exists so the multi-agent positioning isn't a one-off claim — each milestone has to pass the test *"does this make N cooperating agents more capable?"* before it lands. The `What's not on the roadmap` section in `ROADMAP.md` lists what was deliberately rejected (LLM-mediated dialectic, fact-store ontologies, background derivers, in-plugin RBAC) so the boundaries are explicit.
229
+
230
+ ## Rollback
231
+
232
+ ```bash
233
+ hermes config set memory.provider none
234
+ sudo systemctl restart hermes.service
235
+
236
+ # Optional — drop the tables (data loss, irreversible)
237
+ sudo -u postgres psql -d <your-memory-db> -c "
238
+ DROP TABLE IF EXISTS conversations;
239
+ DROP TABLE IF EXISTS memory_entries;
240
+ "
241
+
242
+ # Optional — remove the plugin files
243
+ rm -rf ~/.hermes/plugins/pgvector
244
+ ```
245
+
246
+ ## Why a standalone plugin (not an upstream PR)?
247
+
248
+ Per the hermes-agent [`CONTRIBUTING.md`](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.md):
249
+
250
+ > We are no longer accepting new memory providers into this repo. The set of built-in providers under `plugins/memory/` is closed. If you want to add a new memory backend, publish it as a standalone plugin repo that users install into `~/.hermes/plugins/` (or via a pip entry point).
251
+
252
+ The discovery system (`plugins/memory/__init__.py` in hermes-agent) scans `$HERMES_HOME/plugins/<name>/` for any directory whose `__init__.py` calls `register_memory_provider`. This plugin's `pgvector/__init__.py` does exactly that — no upstream change required.
253
+
254
+ ## Contributing
255
+
256
+ 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.
257
+
258
+ ## License
259
+
260
+ [BSD 3-Clause](LICENSE) © 2026 Andrea Borghi.
@@ -0,0 +1,11 @@
1
+ hermes_memory_pgvector-0.3.0.dist-info/licenses/LICENSE,sha256=MscmBJ_uDrUAIuTQ4FBHWXOUCTLDSEAwS9r7zJJVBXk,1500
2
+ pgvector/__init__.py,sha256=YPoRAJPKaqW106dqM6PanOS7YhgIeR4ytt5PiURqKzs,32204
3
+ pgvector/embed.py,sha256=4j1l0P3YsaP2tBFOFqhAktizuUwWHxsm02tqgz7G5Po,3312
4
+ pgvector/plugin.yaml,sha256=Mlh0VZNV746PmGlBljPZiLQpWQtQfHejpuIIRCyulLk,562
5
+ pgvector/store.py,sha256=JuFmRy7E1rCER0QWjKZoI5hoVgE9D_Cd4E-3yUmMcPQ,19183
6
+ pgvector/writer.py,sha256=r_tRq7v0bvX65EDmuq4Gl9hpKUfTrAg2fyVFcAD93Bw,6099
7
+ pgvector/migrations/001_schema.sql,sha256=DAgA9GinZY3lASfOfzsY2iIw0-p-4BICjelJNAdcUKg,4150
8
+ hermes_memory_pgvector-0.3.0.dist-info/METADATA,sha256=ADNKowe9SZoOIAEjUhcroR1lciNEMi5O5JCdgvy6u4Q,13464
9
+ hermes_memory_pgvector-0.3.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ hermes_memory_pgvector-0.3.0.dist-info/top_level.txt,sha256=xGGaXFRcSRHEhn0HS1FN_UjCWr1G-WSPgxx4a0NJc0M,9
11
+ hermes_memory_pgvector-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Andrea Borghi
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1 @@
1
+ pgvector