langchain-gnarl
LangChain and LangGraph integrations for Gnarl agent memory:
a LangGraph long-term memory store, a LangChain chat history and a LangChain
retriever. Thin wrappers over the published
gnarl-client; the node does the
embedding, so there is no embedding model to configure.
pip install langchain-gnarl
With no address configured, the client finds the node itself: $GNARL_URL,
else the endpoint the node on this machine recorded, else the Gnarly app's
http://127.0.0.1:43300. Pass a client to point anywhere else.
from langchain_gnarl import GnarlStore, GnarlChatMessageHistory, GnarlRetriever
store = GnarlStore() # LangGraph BaseStore
store.put(("memories", "alice"), "diet", {"text": "Alice is vegetarian"})
hits = store.search(("memories", "alice"), query="what does alice eat?", limit=3)
history = GnarlChatMessageHistory("thread-42", user="alice")
history.add_user_message("I moved to Lisbon last spring")
docs = GnarlRetriever(namespace="langchain-chat", user="alice").invoke("where does alice live?")
Use the store in a graph like any other: builder.compile(store=GnarlStore()),
or create_react_agent(model, tools, store=GnarlStore()).
GnarlStore (LangGraph BaseStore)
GnarlStore(client=None, *, async_client=None, namespace="langgraph-store", index_fields=None)
| LangGraph | Gnarl memory |
|---|---|
| the store | one memory namespace (default langgraph-store) |
| item namespace tuple | user — labels joined with . (LangGraph forbids . in labels) |
| item key | session |
| item value | stored verbatim (JSON); its text is embedded by the node |
search(query=...) |
memory.recall, scoped to user — semantic |
- Isolation between namespace tuples is enforced by the node: recall is scoped
to
userserver-side.("memories", "alice")never recalls Bob's items. searchwith a query over a namespace that has sub-namespaces recalls each one and merges by score. Without a query it lists items, newest first.filter=supports equality and$eq/$ne/$gt/$gte/$lt/$lte, applied to the recalled candidates.- Values are embedded by default from every string they contain;
index_fields=["text"](or a put's ownindex=[...]) narrows that.index=Falseis not supported: the node embeds every memory. - TTL is not supported (
supports_ttl = False). - A
putis visible as soon as it returns. A replaced or deleted item drops out of other processes' reads after the node's next refresh (about a second), and immediately in this process.putis not atomic; two concurrent puts of one key both land, and reads return the newer. list_namespacesand query-lesssearchread one row per item.
GnarlChatMessageHistory (LangChain BaseChatMessageHistory)
GnarlChatMessageHistory(session_id, *, client=None, async_client=None, namespace="langchain-chat", user=None)
One memory per turn (session = session_id, the full message kept
verbatim). Turns are therefore also recallable semantically across sessions.
clear() deletes the session's turns.
GnarlRetriever (LangChain BaseRetriever)
GnarlRetriever(client=None, async_client=None, namespace=None, space=None, user=None, session=None, k=4, require_complete=False)
Returns Documents whose metadata carries id, score, knn_score,
fact_type, session, agent, created, tags, namespace, and the
recall's partial and coverage. When part of the memory space did not
answer, partial is True — the documents are a subset, and a missing memory
may still exist. require_complete=True raises IncompleteRecall instead.
Clients
Every class takes an optional gnarl.Client and gnarl.AsyncClient. With
neither, one is built on first use and finds the node as described above
($GNARL_TOKEN supplies a token).
With only a sync client, async methods run it in a worker thread.
Development
pip install -e '.[dev]'
ruff check . && mypy && pyright
pytest tests/unit
GNARL_URL=http://127.0.0.1:<port> pytest tests/integration # a throwaway test node; skipped when unset
Licensed under Apache-2.0.
Metadata
Release files for langchain-gnarl 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| langchain_gnarl-0.1.0.tar.gz | 28.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| langchain_gnarl-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.3 kB
Release files / langchain_gnarl-0.1.0.tar.gz
| Download URL | langchain_gnarl-0.1.0.tar.gz |
|---|---|
| Size | 28.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c9bd25b8f34a19b817d914a48e30d5d89fe897a303651467767dbaf6ca396a2d
|
|
BLAKE2b-256 checksum How to use checksums |
c23a6152e6f59766fa977b251331b083ae7ec24992dba1361158822f9c64d114
|
| 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 Oct 11, 2026.
Transparency logRelease files / langchain_gnarl-0.1.0-py3-none-any.whl
| Download URL | langchain_gnarl-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
576290072e74c3a6932832fabf341ef1ab075491ce23a07a383444dccf4f05fb
|
|
BLAKE2b-256 checksum How to use checksums |
7e2f93f320dc75f1f1c1aab95e049c915d025f9401897681d87a8cce16061650
|
| 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 Oct 11, 2026.
Transparency log