LiticaLitica
Docs/Inspection

Python SDK

Inspection

Four windows into what your memory is doing: the graph, the audit feed, the write queue, and the ranking maths.

The memory graph

viz_graph returns the memories in one scope and the links between them — the same data behind the playground's graph view:

graph = client.viz_graph(limit=300)

len(graph.nodes)   # memories
len(graph.links)   # connections between them
graph.truncated    # True if limit cut the result short

Nodes and links stay plain dicts: they are large, UI-shaped payloads that evolve with the retrieval internals.

The audit feed

viz_add_events is a cursor-paged feed over every write: who wrote what, into which scope, and when. Poll it in ascending order, feeding cursor back as since_id:

# Bootstrap the cursor at the newest event:
page = client.viz_add_events(order="desc", limit=1)
cursor = page.cursor

# Then poll forward:
while True:
    page = client.viz_add_events(since_id=cursor, order="asc")
    for event in page.events:
        handle(event)
    cursor = page.cursor
    time.sleep(5)

Unlike every other scoped method, viz_add_events does not inherit the client's agent_id/namespace_id defaults — its filters default to all scopes. Silently narrowing an audit feed to one agent would defeat its purpose; narrow it explicitly if you want to.

Queue depth

viz_pending reports how many writes are still waiting in an agent's queue — useful for knowing when the write pipeline has drained after a bulk ingest:

client.add_memories_batch(fifty_facts)

while client.viz_pending() > 0:
    time.sleep(2)
# queue drained — new memories should now be searchable

Explain a search

search_explain is search_memories with the ranking maths attached: every candidate considered, its component scores, and the final order.

By default, search_explain is a real search

With the default rehearse=True it strengthens the memories it returns and logs the query, exactly like search_memories. Calling it in a loop to poke at rankings will distort the very rankings you are poking at. Pass rehearse=False for the side-effect-free what-if.

explained = client.search_explain(
    "who owns pricing?",
    rehearse=False,       # inspect without strengthening or logging
    max_candidates=25,
)

for r in explained.results:
    print(r.rank, r.final_score, r.text)   # rank is 1-based here

explained.rehearsed    # False — confirms this was a what-if
explained.candidates   # every candidate considered, not just the returned head
explained.trace        # domain weights, scoring constants, per-candidate maths

With rehearse=False you can also pass query_rf, a pre-decomposed query dict, to skip the server's LLM decomposition step; it is ignored when rehearse=True. And note the rank convention: 1-based here, 0-based in get_memory_trace — mirrored as the server sends them.

Next steps