Skip to main content

goodmem-autogen

GoodMem memory and tools for the AutoGen agent framework.

Two ways in:

  1. GoodMemContextProvider — an autogen_core.memory.Memory backed by a GoodMem space, so relevant passages are injected into the model context on every turn.
  2. create_goodmem_search_tool / create_goodmem_admin_tools — function tools an agent can call directly.

Built on the official goodmem SDK's async client, so nothing blocks the event loop.

Install

pip install goodmem-autogen

Requires Python 3.10+, autogen-core 0.7.5+ and the goodmem SDK 0.1.34+ (installed with it). Version 0.2 is a break from 0.1 — see CHANGELOG for the mapping.

As an AutoGen Memory

from autogen_core.memory import MemoryContent, MemoryMimeType
from goodmem_autogen import GoodMemContextProvider, GoodMemMemoryConfig

provider = GoodMemContextProvider(
    config=GoodMemMemoryConfig(
        base_url="https://goodmem.example.com",
        api_key="gm_...",              # stored as SecretStr, never serialized
        space_name="handbook",         # or space_id="..." to skip the lookup
        embedder_id="<embedder-uuid>",
    )
)

await provider.add(MemoryContent(
    content="Refunds above $500 need a manager's approval.",
    mime_type=MemoryMimeType.TEXT,
    metadata={"title": "handbook", "category": "policy"},
))

results = await provider.query("who approves a large refund?")
await provider.close()

add() waits for the memory to finish indexing by default, so a query right after it finds the result. Searching is never used as a way to wait.

Attach it to an agent and update_context injects retrieved passages as a system message each turn — the same pattern AutoGen's own ListMemory uses.

What a result carries

MemoryContent has no score field, so provenance lives in metadata:

{
  "title": "handbook", "category": "policy",   # the memory's own metadata
  "chunk_id": "...", "memory_id": "...", "space_id": "...", "source": "...",
  "score": -0.53, "score_kind": "vector",
  "partial": False, "statuses": [],
}
  • partial is True when part of the search did not complete — a reranker was unavailable, one space was unreachable. The passages are usable but may be incomplete, and statuses says why. A search that produced nothing usable returns an empty result and emits a warning carrying the statuses, so it is distinguishable from "no matches" without being raised. The search tool returns partial: true with statuses in its JSON for the same case.
  • score is passed through exactly as GoodMem reports it. Vector scores are opaque similarities that may be negative; reranker scores are on a scale that depends on the reranker model (Voyage rerank-2.5 ~0.27..0.93, Jina jina-reranker-v3 ~-0.14..0.43 on the same documents). score_kind says which you have — which is why relevance_threshold requires a reranker_id, and why it must be calibrated for the reranker in use rather than assumed to be 0–1. The threshold is applied by the server; if it removes every result the provider warns, since an empty result would otherwise read as "no matches".
  • score_kind is read from the response, not the configuration. If the reranker fails (RERANKING_FAILED, or NOT_FOUND for the reranker) the server still returns the vector-search hits; they are kept, labelled vector, and marked partial with those statuses.

As tools

The tools take a goodmem.AsyncGoodmem client, which you create and close.

from autogen_core import CancellationToken
from goodmem_autogen import create_goodmem_admin_tools, create_goodmem_search_tool
from goodmem import AsyncGoodmem

client = AsyncGoodmem(
    base_url="https://goodmem.example.com",
    api_key="gm_...",
    # verify="/path/to/ca.pem",   # a server with a self-signed certificate
)

search = create_goodmem_search_tool(
    client, space_ids=["<space-uuid>"], limit=5,
    reranker_id="<reranker-uuid>",            # optional
    metadata_filter={"category": "policy"},   # optional, escaped for you
)
admin_tools = create_goodmem_admin_tools(client)  # only for agents that need them

# What an agent's tool call does:
print(await search.run_json({"query": "who approves a large refund?"}, CancellationToken()))

await client.close()

The model supplies only the query; spaces, reranking and filters are yours, so an agent cannot redirect a search or widen it mid-run. The search tool returns JSON: results (each with chunk_text, score, score_kind, metadata and IDs), total_results, partial, and statuses when the server reported any.

create_goodmem_admin_tools(client) adds space and memory management (goodmem_list_embedders, goodmem_list_rerankers, goodmem_list_spaces, goodmem_get_space, goodmem_create_space, goodmem_update_space, goodmem_delete_space, goodmem_create_memory, goodmem_list_memories, goodmem_get_memory, goodmem_delete_memory, and goodmem_upload_file when upload_dir is given). A listing returns at most max_items (default 100) and sets truncated when that cap may have cut it short. These carry the authority of the configured API key — give them only to agents that need them. File upload is only created when you pass upload_dir, and paths resolving outside that directory are refused before the file is opened.

Every ID — a tool argument, space_ids, reranker_id, or an ID field of the config — must be a UUID (it is lowercased); anything else raises ValueError before a request is made. The SDK puts IDs into request paths unescaped, so "../spaces/<id>" given as a memory ID would otherwise address a whole space.

Cancellation

add, add_file and query honour an autogen_core.CancellationToken: an already-cancelled token prevents the request, and cancelling mid-flight aborts it.

Clearing a space

clear() deletes every memory in the space and requires allow_clear=True on the config, so a reflexive clear() cannot empty a space by accident.

Filters

A filter is a GoodMem expression applied to every configured space, e.g. CAST(val('$.category') AS TEXT) = 'policy'. Pass metadata_filter={...} and it is built and escaped for you. Writing one by hand: inside a quoted value escape ' as \' and \ as \\ — SQL-style '' doubling is rejected by the server.

Development

uv venv && uv pip install -e ".[dev]"
uv run ruff check goodmem_autogen tests
uv run mypy goodmem_autogen
uv run pytest -m "not integration"   # offline: the real SDK over a mock transport or a local server
GOODMEM_BASE_URL=... GOODMEM_API_KEY=... GOODMEM_EMBEDDER_ID=... \
  GOODMEM_VERIFY_SSL=false uv run pytest -m integration

CI runs the first four on Python 3.10–3.13, then uv build and an import of the wheel in a clean environment. It does not run the live suite, which needs a server: GOODMEM_EMBEDDER_ID is the embedder its spaces are created with, and GOODMEM_VERIFY_SSL=false is for a local server with a self-signed certificate. The offline suite also executes every Python snippet in this README against a local server.

Offline tests use event shapes captured from a live server. There is no default API key — live tests skip unless the environment provides one.

MIT.

Metadata

Release files for goodmem-autogen 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for goodmem-autogen 0.3.0
File Size Uploaded
goodmem_autogen-0.3.0.tar.gz 23.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for goodmem-autogen 0.3.0
File Interpreter ABI Platform
goodmem_autogen-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 48.7 kB

Release files / goodmem_autogen-0.3.0.tar.gz

Download URL goodmem_autogen-0.3.0.tar.gz
Size 23.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c1480d3c11ff9f2e598a840b590ec38b0eedcac2b7143edadf36feae536eefd3
BLAKE2b-256 checksum
How to use checksums
52d1bbf879e8232e1d5cb2027e0fa5eab0f9e685866c5e98fe85b0444f8aeb7c
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 29, 2026.

Transparency log

Release files / goodmem_autogen-0.3.0-py3-none-any.whl

Download URL goodmem_autogen-0.3.0-py3-none-any.whl
Size 25.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f7ccd3ad6412b5922f17461a403f1a5efaa3a62421d489a1c1e1157e6dbf46b2
BLAKE2b-256 checksum
How to use checksums
b640394397482b1fee7d1a2f8c08e9ad2a30b2a6e2254509ac9109d605abfd95
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 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page