Python SDK
Configuration
Everything the client needs is set once, at construction. Precedence is argument, then environment variable, then built-in default.
import litica
client = litica.Client(
api_key="lk_...", # or LITICA_API_KEY
agent_id="support-bot", # default agent for every call
namespace_id="ns_...", # default namespace for every call
timeout=30.0, # seconds, per request
)Settings
| 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 |
A client constructed with no API key at all raises LiticaConfigError immediately — not on the first request. timeout (default 30 seconds) and transport (an httpx.BaseTransport, useful for mocking in tests) are argument-only.
How scope works
Every memory in Litica lives in a scope: an agent_id plus an optional namespace_id. You set both once on the client, and every call that accepts them uses those defaults. 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 memoriesnamespace_id=None is a real scope, not an absence
A memory with no namespace is agent-private — that is its own scope in Litica. So passing namespace_id=None explicitly means “this agent's private memories” and overrides the client default. Omitting the argument means “use the client default.” The two are different, and the SDK keeps them different.
One deliberate exception: viz_add_events — the audit feed — does not inherit the client's scope defaults. An audit feed that silently narrowed itself to one agent would be the opposite of an audit feed. See Inspection.
Client lifecycle
The client holds an HTTP connection pool. Use it as a context manager, or call close() when you are done:
with litica.Client(api_key="lk_...") as client:
client.add_memory("...")
# pool closed automaticallyVerify your setup
health() checks the server is reachable (it returns False instead of raising), and get_tenant() confirms your key resolves:
>>> client.health()
True
>>> client.get_tenant()
'tn_9f2c...'Next steps
- Writing Memories — the write path, and why it is asynchronous.
- Namespaces — creating shared scopes and granting agents access.