Decisions Lifecycle
This walkthrough drives a Decision through its lifecycle with the local Python API:
- Create a decision with evidence, rejected alternatives, constraints, and rationale
- Reinforce it as new evidence arrives
- Contradict it when counter-evidence appears
- Supersede it when reality changes
- Search and retrieve the current decision
- Inspect provenance and causal chains
- Retract it when it is no longer valid
Decisions are first-class memory items in SmartMemory. See concepts/decision-memory for the model. This guide focuses on the runnable local API surface.
Source: smart-memory-core/smartmemory/smart_memory.py, smart-memory-core/smartmemory/decisions/manager.py.
End-to-end lifecycle
from smartmemory.models.decision import Decision
from smartmemory.models.memory_item import MemoryItem
from smartmemory.pipeline.config import PipelineConfig
from smartmemory.tools.factory import lite_context
lite = dict(pipeline_profile=PipelineConfig.lite(llm_enabled=False))
with lite_context(**lite) as memory:
evidence_id = memory.add(
MemoryItem(
content="Latency p95 measured at 850ms after switching to pgbouncer.",
memory_type="observation",
)
)
decision = memory.add_decision(
"Use pgbouncer transaction pooling for the billing service.",
decision_type="choice",
confidence=0.85,
evidence_ids=[evidence_id],
domain="billing",
tags=["infra", "pooling"],
rationale="Reduces connection churn and brings p95 under 200ms.",
rejected_alternatives=["session pooling", "client-side pooling"],
constraints=["max_client_conns <= 200"],
)
support_id = memory.add(
MemoryItem(
content="After 2 weeks in prod: p95 is about 140ms.",
memory_type="observation",
)
)
reinforced = memory.reinforce_decision(decision.decision_id, support_id)
contradiction_id = memory.add(
MemoryItem(
content="Spike day: transaction pooling broke prepared statements.",
memory_type="observation",
)
)
contradicted = memory.contradict_decision(
decision.decision_id,
contradiction_id,
)
replacement = Decision(
content="Use pgbouncer session pooling with a prepared-statement workaround.",
decision_type="choice",
confidence=0.8,
)
replacement = memory.supersede_decision(
decision.decision_id,
replacement,
reason="Transaction pooling broke ORM prepared statements.",
)
hits = memory.search("billing pooling decision", expertise=True)
retrieved = memory.get_decision(replacement.decision_id)
provenance = memory.get_decision_provenance(replacement.decision_id)
causal = memory.get_decision_causal_chain(
replacement.decision_id,
direction="both",
max_depth=3,
)
memory.retract_decision(
replacement.decision_id,
reason="Pooling no longer needed after load dropped.",
)
retracted = memory.get_decision(replacement.decision_id)
print(decision.decision_id)
print(reinforced.reinforcement_count, contradicted.contradiction_count)
print(memory.get_decision(decision.decision_id).status, retrieved.status)
print([d.content for d in hits["decision"]])
print(sorted(provenance.keys()), sorted(causal.keys()))
print(retracted.status)add_decision(...) returns a Decision object with .decision_id, .rejected_alternatives, .rationale, .constraints, .confidence, and .status. reinforce_decision(...), contradict_decision(...), supersede_decision(...), and retract_decision(...) are real lifecycle methods on SmartMemory.
search(expertise=True) returns a dictionary keyed by expertise type, not a flat list. Read decisions from hits["decision"].
Service and client notes
The authenticated service exposes the same lifecycle under /memory/decisions/*, and smartmemory-client exposes helpers such as create_decision(...), reinforce_decision(...), supersede_decision(...), retract_decision(...), get_decision(...), list_decisions(...), get_provenance_chain(...), and get_causal_chain(...).
For local examples and tests, prefer the core API above. It runs without a service, token, or workspace UUID.
Related
- Decision Memory concepts
- Reasoning Traces, pair with
source_trace_idon decision creation - Source:
smartmemory/decisions/manager.py