Summary
The LangGraph adapter leaves self._checkpointer = None when the YAML omits the checkpointer: block, which silently disables conversation history, session listing, thread state, and the AG-UI threadId/history capability flags. ADK already defaults to InMemorySessionService / InMemoryMemoryService in the same situation. The engine should provide the same in-memory default for LangGraph so a minimal config "just works" — matching how a developer would expect a freshly-installed engine to behave.
Grounding in code
LangGraph — no default (current behavior)
libs/idun_agent_engine/src/idun_agent_engine/agent/langgraph/langgraph.py:419-453
async def _setup_persistence(self) -> None:
if not self._configuration:
return
if self._configuration.checkpointer: # ← if None, nothing happens
if isinstance(self._configuration.checkpointer, SqliteCheckpointConfig):
...
elif isinstance(self._configuration.checkpointer, InMemoryCheckpointConfig):
self._checkpointer = InMemorySaver()
...
elif isinstance(self._configuration.checkpointer, PostgresCheckpointConfig):
...
Downstream effects when self._checkpointer is None:
langgraph.py:866-874 — has_checkpointer = self._checkpointer is not None drives capabilities.history and capabilities.threadId. Both flip to False.
langgraph.py:1010 — list_sessions() returns [] immediately.
langgraph.py:1047 — get_session() short-circuits on not self._checkpointer.
- LangGraph itself cannot carry state between turns at all without a checkpointer; multi-turn chats lose context silently.
Schema: libs/idun_agent_schema/src/idun_agent_schema/engine/langgraph.py:76
checkpointer: CheckpointConfig | None = None
So a minimal config like:
agent:
type: LANGGRAPH
config:
name: My Agent
graph_definition: ./agent.py:graph
is valid and lands the user in the no-checkpointer state with no warning.
ADK — already defaults to in-memory
libs/idun_agent_engine/src/idun_agent_engine/agent/adk/adk.py:389-431
async def _initialize_session_service(self) -> None:
...
if not self._configuration.session_service:
# Default to InMemory if not specified
self._session_service = InMemorySessionService()
return
...
async def _initialize_memory_service(self) -> None:
...
if not self._configuration.memory_service:
# Default to InMemory if not specified
self._memory_service = InMemoryMemoryService()
return
Proposed change
In _setup_persistence() (LangGraph adapter), when self._configuration.checkpointer is None, default to InMemorySaver() and record an InMemoryCheckpointConfig-equivalent entry in self._infos[\"checkpointer\"]. Log an INFO line so operators know in-memory was chosen as a fallback and that state is process-local (not durable across restarts).
Sketch:
if self._configuration.checkpointer:
# existing branches unchanged
...
else:
self._checkpointer = InMemorySaver()
self._infos[\"checkpointer\"] = InMemoryCheckpointConfig(type=\"memory\").model_dump()
logger.info(
\"No checkpointer configured for LangGraph agent; defaulting to in-memory \"
\"(state is not persisted across process restarts).\"
)
Acceptance criteria
Notes / tradeoffs
- This is a behavioral change for users currently relying on "no checkpointer = no history". Risk is low because the prior behavior was almost always a foot-gun (silent loss of conversation state); however, the
INFO log makes the choice visible.
- Keeps parity with ADK, which already does the same.
- Does not change defaults for durable backends — users still opt into SQLite/Postgres explicitly.
Summary
The LangGraph adapter leaves
self._checkpointer = Nonewhen the YAML omits thecheckpointer:block, which silently disables conversation history, session listing, thread state, and the AG-UIthreadId/historycapability flags. ADK already defaults toInMemorySessionService/InMemoryMemoryServicein the same situation. The engine should provide the same in-memory default for LangGraph so a minimal config "just works" — matching how a developer would expect a freshly-installed engine to behave.Grounding in code
LangGraph — no default (current behavior)
libs/idun_agent_engine/src/idun_agent_engine/agent/langgraph/langgraph.py:419-453Downstream effects when
self._checkpointer is None:langgraph.py:866-874—has_checkpointer = self._checkpointer is not Nonedrivescapabilities.historyandcapabilities.threadId. Both flip toFalse.langgraph.py:1010—list_sessions()returns[]immediately.langgraph.py:1047—get_session()short-circuits onnot self._checkpointer.Schema:
libs/idun_agent_schema/src/idun_agent_schema/engine/langgraph.py:76So a minimal config like:
is valid and lands the user in the no-checkpointer state with no warning.
ADK — already defaults to in-memory
libs/idun_agent_engine/src/idun_agent_engine/agent/adk/adk.py:389-431Proposed change
In
_setup_persistence()(LangGraph adapter), whenself._configuration.checkpointerisNone, default toInMemorySaver()and record anInMemoryCheckpointConfig-equivalent entry inself._infos[\"checkpointer\"]. Log anINFOline so operators know in-memory was chosen as a fallback and that state is process-local (not durable across restarts).Sketch:
Acceptance criteria
InMemorySaverwhenagent.config.checkpointeris unset, with anINFOlog indicating the fallback.GET /agent/capabilitiesreturnshistory: trueandthreadId: truefor a minimal LangGraph config with nocheckpointer:block.GET /agent/sessionsreturns sessions after a multi-turn conversation under the same config./agent/runinvocations on the same thread.libs/idun_agent_engine/tests/covers the unset-checkpointer path, asserting both_checkpointer is not Noneandcapabilities.history is True.libs/idun_agent_engine/CLAUDE.md(Configuration Flow / LangGraph Key Details) — note the default.docs/(Mintlify config reference) — mention the default and that it is non-durable.Notes / tradeoffs
INFOlog makes the choice visible.