CAMEL-AI
Expose GoodMem's RAG memory as a CAMEL BaseToolkit so a ChatAgent can store and recall documents.
Overview
GoodMem is a memory layer for AI agents that handles embedding, vector search, reranking, and
LLM-powered answering server-side. This integration packages the GoodMem API as a CAMEL
BaseToolkit: drop GoodMemToolkit into a CAMEL ChatAgent and the agent can store and
semantically retrieve documents from a GoodMem space alongside its other tools. By default the
model sees exactly two tools — goodmem_search and goodmem_remember — while listing, space
administration, deletion, and file upload are opt-in constructor settings the developer controls.
Installation
pip install goodmem-camelThe pip package is goodmem-camel; the import name is goodmem_camel. The optional example
runner needs OpenAI, installable with pip install goodmem-camel[examples].
Configuration
| Variable | Description |
|---|---|
GOODMEM_BASE_URL | Base URL of your GoodMem server (no /v1 suffix), e.g. https://your-goodmem-server.example.com. |
GOODMEM_API_KEY | API key sent as X-API-Key to authenticate requests. |
When both are set, the toolkit needs no connection arguments; the base_url and api_key
constructor arguments override them. Everything else is configured on the constructor, notably
space_ids (the spaces the toolkit reads from and writes to — the model never chooses a space)
and verify_ssl (default True; pass False only for a self-signed dev server).
Quick start
import os
os.environ["GOODMEM_BASE_URL"] = "https://your-goodmem-server.example.com"
os.environ["GOODMEM_API_KEY"] = "gm_xxxxxxxxxxxxxxxxxxxxxxxx"
from camel.agents import ChatAgent
from camel.models import ModelFactory
from camel.types import ModelPlatformType, ModelType
from goodmem_camel import GoodMemToolkit
# One-time setup: pick an embedder and create (or reuse) a space.
setup = GoodMemToolkit()
embedder_id = setup.list_embedders()[0]["embedderId"]
space_id = setup.create_space(name="quickstart", embedder_id=embedder_id)["spaceId"]
setup.close()
# The agent's toolkit is pinned to that space; the model sees only
# goodmem_search and goodmem_remember.
toolkit = GoodMemToolkit(space_ids=[space_id])
agent = ChatAgent(
system_message=(
"You are an assistant whose long-term memory lives in GoodMem. "
"Store facts the user shares, and answer their questions from memory."
),
model=ModelFactory.create(
model_platform=ModelPlatformType.DEFAULT,
model_type=ModelType.DEFAULT,
),
tools=toolkit.get_tools(),
)Local development. The example above uses a TLS-verified production URL. If you are running
GoodMem locally with a self-signed certificate, use https://localhost:8080 and disable TLS
verification by constructing each toolkit with verify_ssl=False. Keep TLS verification enabled
for any deployed server.
Retrieval post-processing
Retrieval post-processing is configured on the GoodMemToolkit constructor, so the developer —
never the model — decides what applies. goodmem_search itself takes only query and top_k.
| Argument | Type | Description |
|---|---|---|
reranker_id | UUID | Reranker model that reorders matched chunks by relevance. Pass None (not "") for no reranker. |
llm_id | UUID | GoodMem LLM that generates a grounded answer (abstractReply) alongside the chunks. Pass None (not "") for no LLM. It does not rerank or change scores. |
min_score | float | Drop hits scoring below this value. Applies only to reranker scores, whose scale is provider-dependent (not 0–1); off by default. |
metadata_filter | dict or expression | Server-side filter every retrieved memory must match: a mapping (an AND of equalities) or an expression built with goodmem_camel.filters. |
Every id must be a UUID; anything else — including an empty string — raises GoodMemIdError
before any request is made. Each search hit carries chunkId, text, memoryId, spaceId,
metadata, and a score oriented so higher is better, with rawScore (exactly what the server
sent) and scoreKind ("vector" or "reranker" — the two are not on a common scale) beside it.
When a requested reranker fails, the server returns the vector-stage hits (scoreKind: "vector"),
the result is marked partial, and statuses carries what the server reported.
Learn more
The full README, examples, and API reference are available on the PyPI package page.