feat(sdk): Python REST client (agentmemory-py)#360
Conversation
Python users currently call the daemon's REST surface at :3111 by hand with
requests or curl. Ship a thin first-party client so notebooks, data-science
glue, and Python backends get the same shape as the TypeScript SDK without
hand-rolling auth, retries, or the plaintext-bearer guard.
New package at packages/python/:
- sync Client + async AsyncClient with identical surfaces
- methods: remember, smart_search, memories, memory(id), forget,
semantic, procedural, relations, health, plus request() escape hatch
- TypedDict response envelopes (no pydantic dep)
- only runtime dep is httpx
- plaintext-bearer guard ported from v0.9.12 byte-for-byte: warn once
on stderr when bearer would cross plaintext HTTP to a non-loopback
host; raise AuthError instead if AGENTMEMORY_REQUIRE_HTTPS=1
- hatchling build backend, Python >=3.10
- 31 tests via respx-mocked httpx + 1 opt-in live test gated by
AGENTMEMORY_LIVE=1
Plus .github/workflows/publish-python.yml: PyPI trusted-publisher release
on tag python-v* (mirrors the Node workflow). Apache-2.0 licensed to match
the root repo.
Closes #342
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR introduces Changesagentmemory-py Package
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/python/tests/test_client.py (1)
28-38: 💤 Low valueUnused parameter in helper function.
The
_mockparameter is not used within the function body. The docstring mentions it's kept for call-site readability, but this can be confusing.♻️ Optional: Remove unused parameter
-def _route(_mock, method: str, path: str, status: int, body, *, base: str = BASE): +def _route(method: str, path: str, status: int, body, *, base: str = BASE): """Register a respx route on the global mock router. - The ``@respx.mock`` decorator patches the module-level transport, so we - use ``respx.route`` (not the ``respx.router`` module) to register - expectations. The first arg is kept for call-site readability. + The ``@respx.mock`` decorator patches the module-level transport, so + we use ``respx.route`` to register expectations. """ return respx.route(method=method, url=f"{base}{path}").mock(Then update call sites (e.g., line 46, 53, etc.) to remove the
respx.routerargument.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/python/tests/test_client.py` around lines 28 - 38, The helper function _route has an unused first parameter `_mock`; remove that parameter from the signature and docstring and update all call sites that pass the respx.router/mock argument (e.g., tests around the places noted) to call _route(method, path, status, body, base=...) instead; ensure function name `_route` remains and no other references expect the removed parameter.packages/python/README.md (1)
90-94: 💤 Low valueClarify testing instructions are for repository contributors.
The test path
packages/python/testsassumes a repository checkout. Users who install viapip install agentmemorywon't have this directory.📝 Proposed clarification
## Testing +(For contributors working from the repository checkout:) + ```bash pip install -e ".[dev]" -pytest packages/python/tests +pytest testsAlternatively, add a note that testing is for development and users should refer to the test suite on GitHub. </details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@packages/python/README.mdaround lines 90 - 94, Update the Testing section
in the README to clarify these commands are for repository contributors and
adjust the pytest invocation so it runs from the package test directory when
using a repo checkout; specifically, change the example pytest path from
"packages/python/tests" to "tests" (or explain running from the repo root with
pytest packages/python/tests) and add a short note that users who installed via
pip should consult the repository's test suite on GitHub rather than expecting
tests to be present in the installed package.</details> </blockquote></details> <details> <summary>.github/workflows/publish-python.yml (1)</summary><blockquote> `33-36`: _⚡ Quick win_ **Prefer installing dev dependencies from the package specification.** The workflow manually lists test dependencies that duplicate `pyproject.toml`'s `[project.optional-dependencies.dev]` specification. If dev dependencies change, both locations must be updated. <details> <summary>♻️ Proposed refactor</summary> ```diff - name: Install build tooling run: | python -m pip install --upgrade pip - python -m pip install build hatchling pytest pytest-asyncio respx httpx + python -m pip install build + python -m pip install -e ".[dev]"This ensures the workflow uses the same dependency versions as
pyproject.toml.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/publish-python.yml around lines 33 - 36, The workflow step named "Install build tooling" currently hardcodes dev/test packages; change it to install the project's dev extras from pyproject.toml instead so CI stays in sync with [project.optional-dependencies.dev]. Replace the explicit pip install line (the one installing build hatchling pytest pytest-asyncio respx httpx) with a single installation of the package extras (e.g., install the project with the "dev" extras like ".[dev]" or the equivalent editable form) so the workflow derives dev dependencies from pyproject.toml rather than duplicating them.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/python/agentmemory/__init__.py`:
- Line 118: The parameter named type in the sync and async remember() methods
shadows Python's builtin; rename that parameter to memory_type in both function
signatures (sync remember and async remember) and update all internal references
and usages inside those functions (e.g., any code that reads the parameter,
builds dicts, or passes it onward) as well as any places within the same module
that call or reference the parameter name (including default handling and
docstrings) so all occurrences of type are replaced with memory_type to resolve
the Ruff A002 warning.
---
Nitpick comments:
In @.github/workflows/publish-python.yml:
- Around line 33-36: The workflow step named "Install build tooling" currently
hardcodes dev/test packages; change it to install the project's dev extras from
pyproject.toml instead so CI stays in sync with
[project.optional-dependencies.dev]. Replace the explicit pip install line (the
one installing build hatchling pytest pytest-asyncio respx httpx) with a single
installation of the package extras (e.g., install the project with the "dev"
extras like ".[dev]" or the equivalent editable form) so the workflow derives
dev dependencies from pyproject.toml rather than duplicating them.
In `@packages/python/README.md`:
- Around line 90-94: Update the Testing section in the README to clarify these
commands are for repository contributors and adjust the pytest invocation so it
runs from the package test directory when using a repo checkout; specifically,
change the example pytest path from "packages/python/tests" to "tests" (or
explain running from the repo root with pytest packages/python/tests) and add a
short note that users who installed via pip should consult the repository's test
suite on GitHub rather than expecting tests to be present in the installed
package.
In `@packages/python/tests/test_client.py`:
- Around line 28-38: The helper function _route has an unused first parameter
`_mock`; remove that parameter from the signature and docstring and update all
call sites that pass the respx.router/mock argument (e.g., tests around the
places noted) to call _route(method, path, status, body, base=...) instead;
ensure function name `_route` remains and no other references expect the removed
parameter.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 196e23ca-0c42-4cdb-9fe9-aea23c1f3ca5
📒 Files selected for processing (14)
.github/workflows/publish-python.yml.gitignoreCHANGELOG.mdpackages/python/LICENSEpackages/python/README.mdpackages/python/agentmemory/__init__.pypackages/python/agentmemory/_exceptions.pypackages/python/agentmemory/_http.pypackages/python/agentmemory/_types.pypackages/python/pyproject.tomlpackages/python/tests/__init__.pypackages/python/tests/conftest.pypackages/python/tests/test_bearer_guard.pypackages/python/tests/test_client.py
| project: Optional[str] = None, | ||
| title: Optional[str] = None, | ||
| concepts: Optional[List[str]] = None, | ||
| type: Optional[str] = None, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cd packages/python && find . -name "__init__.py" | grep agentmemoryRepository: rohitg00/agentmemory
Length of output: 90
🏁 Script executed:
wc -l packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 108
🏁 Script executed:
sed -n '110,130p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 773
🏁 Script executed:
sed -n '314,330p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 571
🏁 Script executed:
sed -n '100,150p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 1680
🏁 Script executed:
sed -n '300,360p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 1925
🏁 Script executed:
grep -n "type: Optional\[str\]" packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 144
🏁 Script executed:
grep -n '"type": type' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 132
🏁 Script executed:
sed -n '116,125p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 486
🏁 Script executed:
sed -n '320,329p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 424
🏁 Script executed:
sed -n '134,138p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 237
🏁 Script executed:
sed -n '331,335p' packages/python/agentmemory/__init__.pyRepository: rohitg00/agentmemory
Length of output: 237
Rename type parameter to avoid builtin shadowing.
Lines 118 and 322 use type as a parameter name in the sync and async remember() methods respectively. This shadows Python's builtin and is flagged by Ruff (A002). Renaming to memory_type requires updates at lines 118, 136 (sync method) and 322, 333 (async method).
Proposed fix
- type: Optional[str] = None,
+ memory_type: Optional[str] = None,
@@
- "type": type,
+ "type": memory_type,
@@
- type: Optional[str] = None,
+ memory_type: Optional[str] = None,
@@
- "type": type,
+ "type": memory_type,🧰 Tools
🪛 Ruff (0.15.12)
[error] 118-118: Function argument type is shadowing a Python builtin
(A002)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/python/agentmemory/__init__.py` at line 118, The parameter named
type in the sync and async remember() methods shadows Python's builtin; rename
that parameter to memory_type in both function signatures (sync remember and
async remember) and update all internal references and usages inside those
functions (e.g., any code that reads the parameter, builds dicts, or passes it
onward) as well as any places within the same module that call or reference the
parameter name (including default handling and docstrings) so all occurrences of
type are replaced with memory_type to resolve the Ruff A002 warning.
|
Closing — wrong abstraction. agentmemory functions register as Will replace with Issue #342 stays open and gets re-scoped to "Python usage via iii-sdk". |
Closes #342.
Adds
agentmemory-py— a thin Python REST client for the daemon at:3111. Native ecosystem reach for notebooks, Django backends, and any Python code that wants memory without writing its own retry/auth/JSON glue. No business logic — the daemon owns embedding, BM25, vector indexing, and lifecycle; this is a transport wrapper with typed responses.API surface
Sync
Clientand asyncAsyncClient, identical method sets:health()GET /agentmemory/livezremember(content=..., ...)POST /agentmemory/remembersmart_search(query=..., limit=...)POST /agentmemory/smart-searchmemories(project=..., latest=False)GET /agentmemory/memoriesmemory(memory_id)GET /agentmemory/memories/{id}forget(memory_id=...)POST /agentmemory/forgetsemantic()GET /agentmemory/semanticprocedural()GET /agentmemory/proceduralrelations()GET /agentmemory/relationsrequest(method, path, json=..., …)Responses are
TypedDict-shaped (Memory,SmartSearchResult,RememberResult, …) — nopydanticdep. The only runtime dependency ishttpx. Build backend ishatchling, Python>=3.10.Plaintext-bearer guard (parity with v0.9.12 / #315)
Ported byte-for-byte from the Node/Python integrations landed in #315:
localhost/127.0.0.1/::1) andhttps://targets stay silent.AGENTMEMORY_REQUIRE_HTTPS=1upgrades the warning to a hardAuthErrorraised atClientconstruction.AGENTMEMORY_URLandAGENTMEMORY_SECRETresolved as fallbacks when the constructor args areNone.PyPI publishing
New
.github/workflows/publish-python.ymlmirrors the existing Nodepublish.yml:python-v0.1.0(prefix keeps it separate from the Node release tag stream).pypa/gh-action-pypi-publish@release/v1— no API token in secrets.pytestthenpython -m buildthen publishes wheel + sdist.Verification
pytest packages/python/tests -q— 31 passed, 1 skipped (the skipped one is the live-daemon check gated byAGENTMEMORY_LIVE=1).python -m build packages/python/— producesagentmemory-0.1.0-py3-none-any.whl(15 KB) andagentmemory-0.1.0.tar.gz.pip install dist/*.whl && python -c "from agentmemory import Client; c = Client(); print(c.base_url)"— printshttp://localhost:3111, no error.Test breakdown
tests/test_client.py(18 tests): sync + async surface, header construction, env-var resolution, query-string + path params, escape hatch, error mapping (AuthErroron 401,ResponseErroron other non-2xx,NetworkErroron connection refused).tests/test_bearer_guard.py(13 tests): loopback exemptions (v4, v6, hostname), HTTPS exemption, no-token short-circuit, warn-once semantics,AGENTMEMORY_REQUIRE_HTTPS=1refusal,AsyncClientparity, post-warning bearer-still-sent assertion.Files
packages/python/agentmemory/{__init__.py,_http.py,_types.py,_exceptions.py}— package source.packages/python/tests/{conftest.py,test_client.py,test_bearer_guard.py}— pytest suite.packages/python/{pyproject.toml,README.md,LICENSE}— hatchling config, quickstart, Apache-2.0 (matches root repo)..github/workflows/publish-python.yml— trusted-publisher release..gitignore— adds Python build/cache patterns.CHANGELOG.md— entry under Unreleased.Summary by CodeRabbit
New Features
Documentation
Chores