Python SDK for the Gum Memory API. Use it to create conversation sessions, append messages, retrieve contextual memory, and write user action events from Python services.
- Synchronous and asynchronous clients.
- TypedDict-based request types that still accept normal Python dictionaries.
- Session object API aligned with the Node.js SDK.
- User action profile recall aligned with
gum.userActions.recall()in the Node.js SDK. - Automatic API key normalization, host normalization, path escaping, and datetime serialization.
- Typed API, connection, and timeout errors.
pip install steamory-agent-kit-gumfrom gum import GumClient
gum = GumClient(api_key="gum_api_key")
session = gum.sessions.init({
"user_id": "user_123",
"session_id": "session_123",
"title": "Team scheduling session",
})
session.add_messages([
{
"role": "user",
"content": "Use Berlin for Europe team scheduling.",
},
])
memory = session.get_memory({
"query": "which city should be used for Europe scheduling",
"details": True,
})
print(memory.get("data"))from gum import AsyncGumClient
async def main() -> None:
async with AsyncGumClient(api_key="gum_api_key") as gum:
session = await gum.sessions.init({
"user_id": "user_123",
"session_id": "session_123",
})
await session.add_message({"role": "user", "content": "hello"})
memory = await session.get_memory({"query": "hello"})
print(memory.get("data"))from gum import GumClient
gum = GumClient(
api_key="gum_api_key",
host="gum.asix.inc",
timeout_ms=30_000,
)| Option | Default | Description |
|---|---|---|
api_key |
Required | Gum API key. The SDK sends Authorization: Api-Key <api_key>. Values already starting with Api-Key are preserved. |
host |
gum.asix.inc |
Plain hosts are normalized to HTTPS and trailing slashes are removed. Explicit http:// or https:// values are preserved. |
timeout_ms |
30000 |
Request timeout in milliseconds. Use 0 to disable the SDK timeout. |
headers |
None |
Default headers merged into every request. |
client |
None |
Optional httpx.Client or httpx.AsyncClient for custom transports, proxies, or tests. |
GumClient exposes synchronous resources:
gum.health(options=None)gum.sessionsgum.user_actions
AsyncGumClient exposes the same resources with awaitable network methods.
Initialize a session:
session = gum.sessions.init({
"user_id": "user_123",
"session_id": "session_123",
"metadata": {"source": "assistant-api"},
})
print(session.id)
print(session.raw_response)Restore a local session helper from a stored id without a network request:
session = gum.sessions.init("session_123")Add messages:
session.add_message({"role": "user", "content": "hello"})
session.add_messages([
{"role": "user", "content": "hello"},
{"role": "assistant", "content": "hi"},
])
gum.sessions.add_messages("session_123", {
"messages": [{"role": "user", "content": "hello"}],
})Retrieve memory:
memory = session.get_memory({
"query": "which city should be used for Europe scheduling",
"details": True,
})Pass recall_config to use the POST context endpoint:
memory = session.get_memory({
"query": "which city should be used for the user request",
"details": True,
"recall_config": {
"message_recent_limit": 20,
"message_semantic_top_k": 8,
"query_router": "single_hop_parallel",
"enable_long_term_recall": False,
},
})from datetime import datetime, timezone
gum.user_actions.create({
"user_id": "user_123",
"timestamp": datetime(2026, 4, 22, 1, 2, 3, tzinfo=timezone.utc),
"content": "User opened the Europe team scheduling page",
"session_id": "session_123",
"event_type": "page_view",
"page": "team_scheduling",
"anchors": {"region": "Europe", "city": "Berlin"},
"metadata": {"source": "assistant-api"},
})Recall profile-ready memory from user action logs:
profile_memory = gum.user_actions.recall({
"user_id": "user_123",
"query": "which scheduling preferences should be remembered",
"recall_config": {
"topk": 10,
"metadata_filters": {
"source": "assistant-api",
"page": "team_scheduling",
},
},
})The Python SDK intentionally does not expose threads, get_context,
sessions.create, sessions.from_id, or user_actions.query. The public
business surface is kept aligned with the current Node.js SDK while preserving
Python-style snake_case method names.
from gum import GumApiError, GumConnectionError, GumTimeoutError
try:
gum.sessions.init({"user_id": "user_123", "session_id": "session_123"})
except GumApiError as error:
print(error.status_code, error.detail, error.body)
except GumTimeoutError as error:
print(f"Timed out after {error.timeout_ms}ms")
except GumConnectionError as error:
print("Network failure", error.cause)python -m pip install -e ".[dev]"
ruff check .
mypy src tests
pytest --cov=gum --cov-fail-under=95Live smoke tests are optional and require a real API key:
GUM_API_KEY=your_gum_api_key_here pytest tests/live -m liveThe GitLab pipeline verifies, builds, syncs to GitHub, and publishes the package:
verify: installs the package with dev dependencies, then runsruff,mypy, and coverage-gated tests.build: builds the source distribution and wheel, then runstwine check.sync_github: manual job onmain, mirroring this repository to GitHub withforce-with-lease.publish: automatic for tags and manual on the default branch; skips upload when the same package version already exists on PyPI.
Required GitLab CI/CD variables:
| Variable | Used by | Description |
|---|---|---|
GITHUB_TOKEN |
sync_github |
GitHub token with permission to push to the mirror repository. |
GITHUB_REPOSITORY_PYTHON_SDK |
sync_github |
GitHub repository path, for example steamory-agent-kit/gum-sdk-python. |
PYPI_API_TOKEN |
publish |
PyPI API token. The pipeline passes it to Twine as __token__. |
MIT