Python client for Litica — human memory for AI agents
Project description
litica
Python client for Litica — shared human memory for AI agents.
A thin, synchronous wrapper over the Litica HTTP API. Each method is one route in the API.
pip install litica
Requires Python 3.10+. The only dependency is httpx.
Quickstart
import time
import litica
client = litica.Client(api_key="lk_...")
client.add_memory("Sam owns the Atlas pricing page.")
# Writes are queued, so poll until it shows up (see below).
for _ in range(20):
hits = client.search_memories("who owns pricing?")
if hits:
break
time.sleep(3)
for hit in hits:
print(hit.id, hit.text)
The conventional shorthand is lit, which is why the class is Client rather
than LiticaClient:
import litica as lit
client = lit.Client(api_key="lk_...")
Configuration
Precedence is argument → environment variable → default.
| Argument | Environment variable | Default |
|---|---|---|
api_key |
LITICA_API_KEY |
required |
base_url |
LITICA_BASE_URL |
https://mcp.litica.org |
agent_id |
LITICA_AGENT_ID |
"default" |
namespace_id |
LITICA_NAMESPACE_ID |
None |
Scope
agent_id and namespace_id are connection-level defaults applied to every
call that takes them. Any call can override them.
client = litica.Client(
api_key="lk_...",
agent_id="support-bot",
namespace_id="team-shared",
)
client.search_memories("who owns pricing?") # support-bot / team-shared
client.search_memories("...", agent_id="research-bot") # override for one call
client.search_memories("...", namespace_id=None) # this agent's private memories
Passing namespace_id=None explicitly means agent-private scope and
overrides the client default — a namespace of NULL is a real scope in Litica,
not an absence.
Writes are queued, not instant
Due to the nature of human-inspired memory, there is a short-term memory queue that has a wait time for ingestion.
add_memory returns as soon as the server accepts the write (HTTP 202).
However, the memory is not searchable yet. It takes time for Litica to decompose, embed, and store it.
A naive write-then-read will not produce expected behavior:
client.add_memory("Sam owns pricing.")
client.search_memories("pricing") # probably []
There is no wait= flag at the moment.
So poll for what you actually care about:
import time
def wait_for(client, query, needle, timeout=90):
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
hits = client.search_memories(query, top_k=10)
if any(needle in h.text for h in hits):
return hits
time.sleep(3)
raise TimeoutError(f"{needle!r} never became searchable")
client.add_memory("Sam owns the Atlas pricing page.")
hits = wait_for(client, "who owns pricing?", "Sam")
Two practical notes:
- Documents take longest. One upload fans out into many memories, so allow
a generous timeout after
add_document. - Searching is not free of side effects. Each search strengthens the memories it returns and is recorded in your query log. That is by design.
Errors
Every exception inherits from litica.LiticaError and carries .status_code,
.detail (the server's message, verbatim), and .response.
try:
client.add_memory("...")
except litica.LiticaRateLimitError as e:
time.sleep(e.retry_after or 60)
except litica.LiticaError as e:
print(e.status_code, e.detail)
LiticaAuthError (401) · LiticaNotFoundError (404) · LiticaConflictError
(409) · LiticaUnsupportedMediaError (415) · LiticaValidationError (422) ·
LiticaRateLimitError (429) · LiticaServerError (5xx) · LiticaAPIError
(anything else) · LiticaTimeout · LiticaConnectionError ·
LiticaResponseError · LiticaConfigError
What you can call
Memories
client.add_memory(content, *, agent_id, namespace_id, session_id)
client.add_memories_batch(contents, *, ...) # several at once
client.add_document("report.pdf", *, ...) # PDF / DOCX / PPTX / text
client.search_memories(query, *, top_k, ...)
client.list_memories(*, top_k, include_archived, ...)
client.get_memory_trace(memory_id) # why this memory surfaced
client.delete_memory(memory_id)
client.clear_memories(*, agent_id) # no undo
client.list_queries(limit)
client.list_agents()
client.get_tenant()
client.health()
Namespaces (shared memory between agents)
ns = client.create_namespace("team-shared", agents=["support-bot"])
client.grant_namespace_agent(ns.namespace_id, "research-bot", can_write=False)
client.list_namespace_agents(ns.namespace_id)
client.remove_namespace_agent(ns.namespace_id, "research-bot")
client.list_namespaces()
client.delete_namespace(ns.namespace_id)
Inspection
client.viz_graph(limit=300) # memories and their links
client.viz_add_events(since_id=0) # write-side audit feed
client.viz_pending() # queue depth
client.search_explain("who owns pricing?") # search, with the score breakdown
search_explainis a real search by default. Withrehearse=Trueit strengthens the memories it returns and logs the query, exactly likesearch_memories. Poking at rankings in a loop will move the rankings you are poking at. Passrehearse=Falsefor a side-effect-free what-if.
Responses
Frozen dataclasses mirroring the JSON as the server sends it. Unknown fields
never break parsing. Every model keeps the untouched body on .raw:
hit = client.search_memories("pricing")[0]
hit.id, hit.text, hit.created_at, hit.source_agent_id
hit.raw # everything the server sent
Timestamps stay ISO-8601 strings rather than datetime objects, because the
server sends null for rows that have none.
Known gaps
- No provenance on writes. The MCP tools let you record where a fact came from; the HTTP route this SDK wraps does not accept it yet, so memories written through the SDK carry no source attribution. Tracked as a follow-up.
rankis inconsistent across routes — 0-based inget_memory_trace, 1-based insearch_explain. Both are mirrored as the server sends them rather than quietly renumbered.- No read-your-writes signal. See "Writes are queued" above — you poll.
- No async client, no retries. Deliberately out of scope for this version.
- No tenant provisioning. That route uses a separate admin credential and is intentionally absent from this client.
Contributing
Bug reports, typing improvements, and documentation fixes are welcome. New endpoints are not — this client mirrors the API one-to-one, so a method cannot exist before the route does. See CONTRIBUTING.md for the full picture, and SECURITY.md to report a vulnerability privately.
License
Apache License 2.0. © 2026 Litica, Inc.
This licence covers this client library only. It grants no right to access or use the Litica service, which is a separate proprietary hosted service with its own terms; an API key is issued separately. See NOTICE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file litica-0.1.0.tar.gz.
File metadata
- Download URL: litica-0.1.0.tar.gz
- Upload date:
- Size: 24.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8be35fdc67da0e8915dab2a9f3609dfa90d274c1f29080fde394e5e23df5cde
|
|
| MD5 |
7ab7c17c408a3aaa1e84be750f1198c8
|
|
| BLAKE2b-256 |
9815835e82b9e6979df74ef09eca77c0a21eada1df2508185a70f9ed65d0cd31
|
Provenance
The following attestation bundles were made for litica-0.1.0.tar.gz:
Publisher:
release.yml on Litica-AI/litica-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
litica-0.1.0.tar.gz -
Subject digest:
b8be35fdc67da0e8915dab2a9f3609dfa90d274c1f29080fde394e5e23df5cde - Sigstore transparency entry: 2313758820
- Sigstore integration time:
-
Permalink:
Litica-AI/litica-sdk@e26853b3f32230e2541fe087f010804513f4b111 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Litica-AI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e26853b3f32230e2541fe087f010804513f4b111 -
Trigger Event:
push
-
Statement type:
File details
Details for the file litica-0.1.0-py3-none-any.whl.
File metadata
- Download URL: litica-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
589234d0a60655332d7a92dd8ed96f79361d029021109c7e21a6e31d87607947
|
|
| MD5 |
5090ea1347609191a42cf2f6f2551d39
|
|
| BLAKE2b-256 |
ea8ceb3e7854d5099d9abe823ca9c657a17a109aeb3663fc87547a79a97e89eb
|
Provenance
The following attestation bundles were made for litica-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Litica-AI/litica-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
litica-0.1.0-py3-none-any.whl -
Subject digest:
589234d0a60655332d7a92dd8ed96f79361d029021109c7e21a6e31d87607947 - Sigstore transparency entry: 2313758886
- Sigstore integration time:
-
Permalink:
Litica-AI/litica-sdk@e26853b3f32230e2541fe087f010804513f4b111 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Litica-AI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e26853b3f32230e2541fe087f010804513f4b111 -
Trigger Event:
push
-
Statement type: