SCM integrates through LangChain's middleware hooks. It runs in-process with the agent and requires no SCM server or SCM endpoint.
from langchain.agents import create_agent
from scm import SCM
memory = SCM(user_id="alice")
agent = create_agent(
model=model,
tools=[...],
middleware=[memory.langchain(max_memories=8, max_context_chars=4000)],
)
result = agent.invoke({
"messages": [{"role": "user", "content": "Keep my answers concise."}]
})from scm.langchain import create_scm_agent
agent = create_scm_agent(
model=model,
tools=[...],
user_id="alice",
system_prompt="You are a technical support agent.",
)The returned agent exposes its runtime as agent.scm for lifecycle and
administration calls.
from scm import SCM, SCMContext
from scm.langchain import create_scm_agent
memory = SCM(namespace="support")
agent = create_scm_agent(model=model, tools=[...], memory=memory)
config = {"configurable": {"thread_id": "langgraph-thread-19"}}
context = SCMContext(user_id="alice", thread_id="ticket-19")
agent.invoke(
{"messages": [{"role": "user", "content": "My account uses SSO."}]},
config=config,
context=context,
)Use the same SCMContext with invoke, ainvoke, and streaming methods. A
LangGraph checkpointer's thread identity and SCM's application user identity
serve different purposes; SCM records both without letting the model choose
either user.
Before the model call, SCM searches the current application user's memory and
adds a bounded <scm_memory> block to the system message. The block is labeled
as untrusted user data, so stored prompt-injection text is context rather than
instructions.
Human messages are persisted before model execution. Writes fail closed: a
durability error aborts the model call with SCMWriteError. Recall fails open:
the model can continue and scm_diagnostics records the recall failure class.
Retries and graph resumptions use a hash of user, thread, and message identity, so replaying the same message does not create duplicate memories.
Middleware contributes exactly five tools:
add_memorysearch_memorysleepwake_summaryforget
Their schemas never contain user_id. The tools resolve identity from the
LangChain runtime context.
SCM attempts to reuse the attached LangChain model for structured concept extraction. If that model does not support structured output or extraction fails, SCM falls back to offline heuristics. A second provider key is not required.
Long-running applications should close SCM during graceful shutdown:
agent.scm.close()This drains background work and commits the final lifecycle snapshot.