Skip to content

feat(engine): default checkpointer/session to in-memory when unset (LangGraph parity with ADK) #672

Description

@Freezaa9

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-874has_checkpointer = self._checkpointer is not None drives capabilities.history and capabilities.threadId. Both flip to False.
  • langgraph.py:1010list_sessions() returns [] immediately.
  • langgraph.py:1047get_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

  • LangGraph adapter wires an InMemorySaver when agent.config.checkpointer is unset, with an INFO log indicating the fallback.
  • GET /agent/capabilities returns history: true and threadId: true for a minimal LangGraph config with no checkpointer: block.
  • GET /agent/sessions returns sessions after a multi-turn conversation under the same config.
  • Multi-turn conversations preserve LangGraph state across /agent/run invocations on the same thread.
  • Unit test in libs/idun_agent_engine/tests/ covers the unset-checkpointer path, asserting both _checkpointer is not None and capabilities.history is True.
  • Docs updated:
    • 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

  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions