Skip to main content
Archived

This project has been archived by its maintainers, and is no longer receiving any updates.

autogen-goodmem

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 autogen-goodmem

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 autogen_goodmem 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 autogen_goodmem 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 autogen_goodmem tests
uv run mypy autogen_goodmem
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 autogen-goodmem 0.2.1

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

Source distribution (sdist)

Source distribution for autogen-goodmem 0.2.1
File Size Uploaded
autogen_goodmem-0.2.1.tar.gz 23.3 kB Details

Built distribution (wheel)

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

Total release size: 48.7 kB

Release files / autogen_goodmem-0.2.1.tar.gz

Download URL autogen_goodmem-0.2.1.tar.gz
Size 23.3 kB
Tags Source
SHA-256 checksum
How to use checksums
61c416fa7d5005c61983715accbfaa3eed35466abdb68e916dcd43a417584dd8
BLAKE2b-256 checksum
How to use checksums
fb363b44644fa847e6f10b3a46ee0081edf92cefff082166c1fbb2b013a36555
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 28, 2026.

Transparency log

Release files / autogen_goodmem-0.2.1-py3-none-any.whl

Download URL autogen_goodmem-0.2.1-py3-none-any.whl
Size 25.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
247a4a5ca8039e66632d9e8c7fc5f914528cc50dd081cced6e5060d02575f867
BLAKE2b-256 checksum
How to use checksums
13d79c20072fd1a77e853ed1b65046c449b8584c52fc03ff7e65881c90988342
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 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 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