Skip to main content
Version: v0.9.0a2
Integrator

Python SDK Reference

5 min readPython integratorstigmem-py

What this page covers

stigmem-py is the official Python client for the Stigmem REST API. It covers facts, conflicts, federation, recall, memory cards, and subscriptions.

Audience: Python developers integrating with a Stigmem node.

Installationโ€‹

pip install stigmem-py
# or with uv:
uv add stigmem-py

Quick startโ€‹

from stigmem import StigmemClient
from stigmem.models import string_value

client = StigmemClient(url="http://localhost:8000", api_key="sk-...")

# Assert a fact
fact = client.assert_fact(
entity="stigmem://company.example/user/alice",
relation="memory:role",
value=string_value("engineer"),
source="agent:assistant",
)

# Recall relevant context
result = client.recall("what is Alice's current role?", token_budget=1000)
for sf in result.facts:
print(f"[{sf.score:.3f}] {sf.fact.relation}: {sf.fact.value.v}")

# Fetch entity summary card
card = client.get_card("stigmem://company.example/user/alice")
print(card.summary)

StigmemClientโ€‹

StigmemClient(url: str, api_key: str | None = None, timeout: float = 10.0)

Synchronous client. All methods raise StigmemHTTPError subclasses on non-2xx responses.

Supports use as a context manager: with StigmemClient(...) as client: ...

Factsโ€‹

assert_factโ€‹

client.assert_fact(
entity: str,
relation: str,
value: FactValue,
source: str,
*,
confidence: float = 1.0,
scope: FactScope = "company",
valid_until: str | None = None,
) -> Fact

Assert a new fact. Returns the stored Fact. Raises StigmemConflictError (409) if a contradicting fact exists and the node is in strict conflict mode.

retractโ€‹

client.retract(
entity: str,
relation: str,
scope: FactScope,
source: str,
*,
value: FactValue | None = None,
) -> Fact

Assert a retraction (confidence=0.0). Convenience wrapper around assert_fact.

get ยท queryโ€‹

client.get(fact_id: str) -> Fact

client.query(
*,
entity: str | None = None,
relation: str | None = None,
source: str | None = None,
scope: FactScope | None = None,
min_confidence: float | None = None,
include_contradicted: bool = False,
include_expired: bool = False,
cursor: str | None = None,
limit: int = 50,
after: str | None = None,
) -> FactPage

get fetches a single fact by ID. query is a paginated structured query.

Recallโ€‹

client.recall(
query: str,
*,
scope: FactScope = "local",
token_budget: int = 4000,
depth: int = 2,
weights: RecallWeights | None = None,
min_confidence: float = 0.1,
include_neighbors: bool = True,
limit: int = 100,
verify_full: bool = False,
) -> RecallResponse

Hybrid recall โ€” return the most salient facts for query within token_budget. Combines lexical (FTS5/BM25), dense-vector (ANN), and graph-traversal signals.

Set verify_full=True to send Stigmem-Verify: full.

Requests server-side integrity proof metadata, including the current fact-chain proof when the node can provide it.

RecallResponse fields:

Field
Type
Description
recall_id
str
UUID for this recall call.
query_hash
str
SHA-256 of the query string.
facts
list[ScoredFact]
Ranked, token-budget-packed facts.
total_scored
int
Candidates scored before packing.
token_budget / tokens_used
int
Requested vs actual budget.
truncated
bool
True when budget was exhausted.
chain_proof
FactChainProof | None
Full-verification fact-chain metadata when requested.

ScoredFact fields include fact, score, score_breakdown, hop_distance, token_estimate, and from_card.

Verification helpersโ€‹

The SDK exposes local integrity helpers for clients that need to fail closed on tampered responses:

from stigmem import (
StigmemVerificationError,
compute_fact_cid,
verify_fact_chain_proof,
verify_fact_cid,
)

result = client.recall("project status", verify_full=True)

try:
for scored in result.facts:
verify_fact_cid(scored.fact)
verify_fact_chain_proof(result.chain_proof, require_checkpoint=True)
except StigmemVerificationError as exc:
raise RuntimeError(f"Stigmem verification failed: {exc}") from exc

Rekor cryptographic inclusion verification remains a node/operator responsibility.

It requires live log trust roots that the SDK does not embed. verify_fact_chain_proof validates compact proof metadata and deterministic local transparency-log checkpoint payloads only.

Memory cardsโ€‹

client.get_card(
entity_uri: str,
*,
scope: FactScope = "local",
refresh: bool = False,
) -> MemoryCard

Fetch the synthesized memory card for entity_uri. The card is auto-refreshed when stale. Pass refresh=True to force a server-side recomputation. Raises StigmemNotFoundError when the entity has no live facts.

from stigmem import StigmemClient, MemoryCard
from stigmem.exceptions import StigmemNotFoundError

client = StigmemClient(url="http://localhost:8000", api_key="sk-...")

try:
card: MemoryCard = client.get_card("stigmem://company.example/user/alice", scope="local")
print(card.summary)
print(f"confidence={card.avg_confidence:.3f} stale={card.is_stale}")
print(f"contradictions={card.has_contradictions}")
except StigmemNotFoundError:
print("Entity has no live facts")

# Force refresh
card = client.get_card("stigmem://company.example/project/phase9", refresh=True)

MemoryCard fields:

Field
Type
Description
entity_uri
str
Entity the card describes.
scope
str
Scope the card was materialised from.
summary
str
Structured text summary of live facts.
fact_hashes
list[str]
SHA-256(fact_id) for each contributing fact.
avg_confidence
float
Source-trust-weighted mean confidence.
refreshed_at
str | None
ISO 8601 UTC timestamp of last refresh.
is_stale
bool
True when a new fact has been asserted since the last refresh.
has_contradictions
bool
True when any two live facts share the same relation.

Conflicts ยท Federation ยท Node infoโ€‹

client.list_conflicts(
*,
status: str | None = "unresolved",
cursor: str | None = None,
limit: int = 50,
) -> ConflictPage

client.resolve_conflict(
conflict_id: str,
*,
winning_fact_id: str | None = None,
resolution_note: str = "",
new_value: FactValue | None = None,
) -> ConflictResolution

client.federation_status() -> list[Peer]
client.node_info() -> NodeInfo # GET /.well-known/stigmem

AsyncStigmemClientโ€‹

Async version backed by httpx.AsyncClient. Supports async with AsyncStigmemClient(...) as client:.

All sync methods have async equivalents with the same signature โ€” prefix with await:

from stigmem import AsyncStigmemClient
from stigmem.models import string_value

async with AsyncStigmemClient(url="http://localhost:8000", api_key="sk-...") as client:
fact = await client.assert_fact(
entity="stigmem://company.example/user/alice",
relation="memory:role",
value=string_value("engineer"),
source="agent:assistant",
)
card = await client.get_card("stigmem://company.example/user/alice")
result = await client.recall("what is Alice's role?", token_budget=500)

Value constructorsโ€‹

from stigmem.models import (
string_value, # string_value("hello")
text_value, # text_value("long text...")
number_value, # number_value(3.14)
boolean_value, # boolean_value(True)
datetime_value, # datetime_value("2026-05-04T00:00:00Z")
ref_value, # ref_value("stigmem://...")
null_value, # null_value()
)

Exceptionsโ€‹

Exception
HTTP status
When raised
StigmemHTTPError
any non-2xx
Base class.
StigmemAuthError
401 / 403
Invalid or missing API key.
StigmemNotFoundError
404
Resource does not exist.
StigmemConflictError
409
Conflicting resource state.
from stigmem.exceptions import StigmemNotFoundError, StigmemAuthError

try:
card = client.get_card("stigmem://company.example/user/unknown")
except StigmemNotFoundError:
print("Entity not found")
except StigmemAuthError:
print("Check your API key")

See alsoโ€‹

Recall guide

Hybrid recall, weight tuning, fast-path.

Memory Cards guide

Card lifecycle and divergence policy.

Asserting facts

Detailed fact write patterns.

Querying facts

Structured predicate queries.