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 shortNodes 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 searchableExplain 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 mathsWith 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
- Error Handling — what the SDK raises and how to respond.
- API Reference — full signatures for all four inspection methods.