honeyhive-goodmem
GoodMem memory as HoneyHive-traced operations. Every call appears as a span alongside the rest of your agent's work, so memory reads and writes are visible in the same trace as the model calls they feed.
Version 0.2.0. Verified against GoodMem server v1.0.320.
Upgrading from 0.1.0. This is an observability package, which makes 0.1.0's worst defect specific to it: retrieval statuses were dropped, so a retrieval that failed was recorded as a successful span. A space whose embedder was unavailable produced
success: true, totalResults: 0— in HoneyHive that reads as "the index is empty", not "the search broke". See Changes in 0.2.0.
Security. 0.1.0's test file carried a live GoodMem API key as a default value, on the public default branch and in the
v0.1.0tag. It is removed here and the environment variable is now required with no fallback — but removing it from the tree does not un-leak it. That key needs rotating.
Install
pip install honeyhive-goodmem
Use
from honeyhive import HoneyHiveTracer
from honeyhive_goodmem import GoodMemClient, GoodMemConfig
HoneyHiveTracer.init(api_key="<your-honeyhive-key>", project="my-project")
client = GoodMemClient(
GoodMemConfig(base_url="https://your-goodmem-server", api_key="<your-goodmem-key>")
)
Both GoodMem settings fall back to GOODMEM_BASE_URL and GOODMEM_API_KEY.
Without a tracer the methods still run; HoneyHive logs that no tracer is
active and no span is emitted.
What a retrieval span records
client.retrieve_memories("what did I store?", space_ids=["<space-uuid>"], max_results=5)
{
"success": True,
"query": "...",
"results": [
{
"chunk_id": "...", "chunk_text": "...", "memory_id": "...", "space_id": "...",
"score": 0.64, # higher is better
"raw_score": -0.64, # exactly what the server sent
"score_kind": "vector", # or "reranker" -- not the same scale
"content_type": "text/plain",
"metadata": {...}, # the memory's metadata, joined by UUID
}
],
"total_results": 1,
"partial": False, # True when the server reported a problem
"statuses": [], # what it reported
"result_set_id": "...",
}
partial means exactly one thing: the server reported a real problem during
this retrieval. It is independent of whether hits came back. A degraded
search still returns whatever arrived, with partial set and a warning key;
when nothing usable arrives the result is empty and still flagged. The span
therefore shows a failed retrieval as failed.
For structured use, client.retrieve(...) returns the same data as a
RetrievalOutcome object instead of a traced dictionary.
Scores
GoodMem produces two kinds of score and they are not comparable. Vector
scores are negative distances, so score is the flipped value with
raw_score kept beside it. Reranker scores are already higher-is-better,
on a provider-dependent scale — measured live on the same five documents,
Voyage rerank-2.5 returned 0.27..0.93 and Jina jina-reranker-v3 returned
-0.14..0.43. There is therefore no default threshold anywhere in this
package.
Metadata filters
Filters are expressions evaluated server-side, not SQL:
from honeyhive_goodmem import filters
client.retrieve_memories("q", ["<space-uuid>"], metadata_filter={"tenant": "acme"})
expression = filters.all_of(
filters.equals("tenant", "acme"),
filters.compare("year", ">=", 2026),
)
The helper applies the escaping the server accepts (' → \', \ → \\;
SQL-style '' doubling is rejected with HTTP 400), refuses control
characters, restricts field names, and casts each value to the type GoodMem
stored — a boolean compared as TEXT is accepted with HTTP 200 and matches
nothing.
Operations
| Method | Event |
|---|---|
create_space, list_spaces, get_space, update_space, delete_space |
tool |
list_embedders |
tool |
create_memory, get_memory, list_memories, delete_memory |
tool |
retrieve_memories |
retrieval |
update_space takes name and labels. It no longer offers public_read:
the server removed that field and answers 400 Unrecognized field "publicRead".
Changes in 0.2.0
Reproduced against the published 0.1.0 wheel, live against GoodMem v1.0.320.
| Was | Now |
|---|---|
A live GoodMem API key was the default value of GOODMEM_API_KEY in the test file, on the public default branch |
Removed; the variable is required with no fallback. The key still needs rotating |
A failing embedder produced success: true, totalResults: 0 — the server's EMBEDDER_FAILED was dropped, so the span said success |
partial + statuses + warning in the traced payload |
A broken reranker produced success: true with three statuses discarded |
Same contract; hits are still returned, flagged |
Hand-written httpx client |
Official goodmem SDK |
public_read was a parameter; the server answers HTTP 400 |
Gone |
Empty search took 11.65 s — wait_for_indexing on by default |
0.31 s; the read path never polls |
| Reusing a space name reported the embedder you asked for while the space ran another | Reuse requires a match; a mismatch names both |
Chunks and memories were two arrays joined by positional memory_index |
Joined by UUID, de-duplicated by chunk id |
| Raw negative scores in the span | score / raw_score / score_kind |
nextToken appeared nowhere — listings returned one page |
Paginated, bounded by max_list_items |
| No metadata filtering | filters, escaped and type-correct |
| The API key was a public attribute | Private; absent from repr and from every traced payload |
| 13 live-only tests that fell back to a committed key; no CI | 33 offline + 16 live; CI on 3.11–3.13 |
Already correct in 0.1.0 and unchanged: request timeouts (30 s by default), and the error path — the server's own message reaches the caller.
Tests
| Suite | Count | Needs |
|---|---|---|
tests/test_honeyhive_goodmem.py |
33 | nothing — the real SDK over a mock transport, fed NDJSON captured from a live server |
tests/test_honeyhive_goodmem_live.py |
16 | GOODMEM_API_KEY + GOODMEM_BASE_URL; skips entirely without them |
pip install -e . pytest httpx "ruff==0.7.4" mypy
pytest tests/test_honeyhive_goodmem.py
GOODMEM_API_KEY=... GOODMEM_BASE_URL=... \
GOODMEM_TEST_EMBEDDER_ID=... \
pytest tests/test_honeyhive_goodmem_live.py
ruff check honeyhive_goodmem tests && mypy honeyhive_goodmem
One offline test scans the tree for a credential-shaped string, so the defect that shipped in 0.1.0 cannot come back unnoticed. The live suite creates one space per run and asserts, against a fresh listing, that it is gone.
License
Apache-2.0.
Release files for honeyhive-goodmem 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| honeyhive_goodmem-0.2.0.tar.gz | 20.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| honeyhive_goodmem-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 41.0 kB
Release files / honeyhive_goodmem-0.2.0.tar.gz
| Download URL | honeyhive_goodmem-0.2.0.tar.gz |
|---|---|
| Size | 20.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
172091a989352f25a6de8e64d7c22778a976495fc7179cdf5b3b8de379da8047
|
|
BLAKE2b-256 checksum How to use checksums |
e7f43f91f29b8879a4a7711c7824c3d7acec8f9858210d4ba41b676303225cf9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / honeyhive_goodmem-0.2.0-py3-none-any.whl
| Download URL | honeyhive_goodmem-0.2.0-py3-none-any.whl |
|---|---|
| Size | 20.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
608671829e1cf7c857a6cda5ccc62d753e329522f53d0952bac4f9dcc7fd37ec
|
|
BLAKE2b-256 checksum How to use checksums |
22eb0cc28dc55dbcbc61d446d365127a31379e44290d3c59298292ffb3a95ec9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log