| name | kitaru-langgraph-migration |
| description | Migrate existing LangGraph and LangChain agent code to Kitaru's LangGraph adapter. Use when code mentions LangGraph, StateGraph, CompiledStateGraph, graph.invoke, graph.ainvoke, stream, astream, interrupt, Command, thread_id, checkpointer, InMemorySaver, MemorySaver, create_agent, KitaruGraphRunner, LangGraphRunRequest, LangGraphRunResult, KitaruLangGraphMiddleware, build_resume_request, wait_for_interrupt, checkpoint_strategy, graph_call, calls, callbacks, event streams, Deep Agents, or checkpointers. Helps classify direct, approximate, and absent mappings, choose graph_call vs middleware-backed calls boundaries, preserve LangGraph ownership of graph state, and produce a migration report.
|
Migrate LangGraph to Kitaru
What this skill does
Use this skill to inspect LangGraph, LangChain create_agent(...), or Deep
Agents code and move only the supportable durability boundary to Kitaru's
kitaru.adapters.langgraph surfaces.
The output should be conservative:
- A source pattern inventory.
- A migration plan that classifies each important pattern as
direct,
approximate, or absent.
- Migrated or proposed code using
KitaruGraphRunner, LangGraphRunRequest,
LangGraphRunResult, and, when safe, KitaruLangGraphMiddleware.
- A
MIGRATION_REPORT.md section or file that names replay, interrupt,
checkpointer, state, stream, and side-effect risks.
Do not promise that Kitaru replaces LangGraph persistence or checkpoints every
node inside the graph.
Mental model: LangGraph owns the graph; Kitaru records the doorway
LangGraph still owns graph state, checkpointers, stores, interrupts,
thread_id, graph-local replay, and any Deep Agents sandbox or filesystem
backend.
Kitaru can record either:
- one outer graph invocation with
checkpoint_strategy="graph_call"; or
- synchronous LangChain model/tool calls that physically pass through
KitaruLangGraphMiddleware while a KitaruGraphRunner is active with
checkpoint_strategy="calls".
A useful picture: LangGraph is the house. Kitaru can put a camera at the front
door and, if LangChain middleware is installed, at a few visible interior
doorways. It cannot see through walls into checkpointers, stores, hosted tools,
or async model/tool internals that do not pass through a true Kitaru checkpoint.
When to use this skill
Use it when the user asks to:
- replace raw
graph.invoke(...) / graph.ainvoke(...) entrypoints with
KitaruGraphRunner.invoke(...) / ainvoke(...);
- add Kitaru around a
StateGraph / CompiledStateGraph;
- choose between
checkpoint_strategy="graph_call" and "calls";
- migrate LangGraph interrupts and
Command(resume=...) handling;
- review LangGraph checkpointers, stores,
thread_id, InMemorySaver, or
MemorySaver assumptions;
- add
KitaruLangGraphMiddleware to a LangChain create_agent(...) agent;
- reason about callbacks, events,
stream, astream, stream_events, or Deep
Agents under Kitaru;
- produce a migration report for LangGraph code.
When not to use this skill
Do not use it to:
- replace LangGraph's checkpointer or store with Kitaru;
- promise Kitaru can replay every LangGraph node, edge, interrupt, event, or
Deep Agents filesystem operation;
- migrate PydanticAI, OpenAI Agents SDK, Claude Agent SDK, Gemini Interactions,
or raw provider SDK code;
- put Kitaru waits inside graph nodes or checkpoints without a flow-scope
redesign;
- invent unsupported Kitaru strategies beyond
graph_call and calls.
The three mapping types
Classify each source pattern before editing:
direct: Kitaru has a clear adapter surface for the same outer behavior.
Example: graph.invoke(input, config) becomes
runner.invoke(LangGraphRunRequest.start(input, thread_id=...)).
approximate: The migration is possible, but replay, observability,
interrupt, streaming, state, or persistence behavior differs. Example:
callbacks remain observability, not replay boundaries.
absent: There is no safe automatic migration until the source is redesigned.
Example: a claim that Kitaru will replace a production LangGraph checkpointer.
Unsupported patterns must not be silently approximated. Add a concrete
# TODO(migration): ... comment near proposed code, list it in the report, and
explain the redesign needed.
Migration workflow
- Inspect source first. Find graph construction, compile-time checkpointers
and stores,
thread_id handling, raw invoke/ainvoke/stream calls, interrupts,
Command(resume=...), callbacks, middleware, Deep Agents usage, and existing
Kitaru flows/checkpoints.
- Classify every pattern. Use
references/concept-map.md and
references/gaps-and-flags.md. Count direct, approximate, flagged, and
blocked items.
- Choose Kitaru boundaries. Prefer
checkpoint_strategy="graph_call" unless
the source clearly uses synchronous LangChain model/tool handlers that can be
wrapped by KitaruLangGraphMiddleware.
- Present the plan before generating code when the migration is more than a
tiny entrypoint replacement. Name high-risk seams before editing.
- Draft migrated code. Keep the source graph. Add
KitaruGraphRunner and
serializable LangGraphRunRequest objects. Add explicit result status
handling for completed vs interrupted.
- Produce
MIGRATION_REPORT.md. Include the pattern inventory,
classifications, chosen boundary, flags, behavior differences, and
verification plan.
- Verify behavior. Prefer static/import checks and a small local graph. If
provider keys or production checkpointers are unavailable, say so.
Pattern detection checklist
Look for:
StateGraph(...), .compile(...), CompiledStateGraph, graph.invoke(...),
graph.ainvoke(...), stream(...), astream(...), or stream_events(...).
config={"configurable": {"thread_id": ...}}, checkpoint_id, or
checkpoint_ns.
interrupt(...), Command(resume=...), wait_for_interrupt(...), and
result status branches.
InMemorySaver, MemorySaver, Postgres/Redis/custom checkpointers, stores,
or memory APIs.
create_agent(...), middleware=[...], and whether
KitaruLangGraphMiddleware() is installed.
- callbacks, LangSmith tracing, event streams, or stream handlers with external
side effects.
- Deep Agents middleware/backends, filesystem tools, subagents, sandboxes, or
state backends.
- Existing
@kitaru.flow or @kitaru.checkpoint wrappers.
- Non-serializable graph outputs, state snapshots, clients, file handles, or raw
framework objects returned from checkpoints.
Boundary decision rules
- Keep LangGraph as the graph runtime.
- Default to
KitaruGraphRunner(graph, checkpoint_strategy="graph_call") for a
clean outer checkpoint around one completed or interrupted invocation.
- Use
checkpoint_strategy="calls" only when synchronous LangChain model/tool
calls pass through KitaruLangGraphMiddleware while the runner is active.
- Treat async calls mode as metadata-only today; do not promise true async
granular checkpoints.
- Keep LangGraph checkpointers/stores in place. Kitaru records its own boundary;
it does not replace LangGraph's persistence layer.
- For replay planning,
graph_call gives one outer graph-call at target;
middleware-observed calls can add supported sync model/tool targets. LangGraph
state, thread_id, checkpoint IDs, and graph-local time travel are not Kitaru
override state; keep those decisions in the LangGraph request/config.
- Preserve stable
thread_id handling. If the source has no stable thread ID,
flag it before migration.
- If the source relies on graph-local time travel or checkpoint IDs, preserve and
flag it before migration.
- Treat callbacks, events, and streams as observability unless a concrete Kitaru
checkpoint boundary stores a final serializable value.
- Do not put Kitaru
wait() calls inside graph nodes or checkpoints. Bridge
LangGraph interrupts at flow scope when human input is needed.
LangGraph migration quick guide
Minimal outer graph call:
from typing import TypedDict
from langgraph.graph import END, START, StateGraph
from kitaru.adapters.langgraph import KitaruGraphRunner, LangGraphRunRequest
class State(TypedDict):
topic: str
summary: str
def summarize(state: State) -> dict[str, str]:
return {"summary": f"Summary for {state['topic']}"}
builder = StateGraph(State)
builder.add_node("summarize", summarize)
builder.add_edge(START, "summarize")
builder.add_edge("summarize", END)
graph = builder.compile()
runner = KitaruGraphRunner(graph, name="summary_graph")
request = LangGraphRunRequest.start(
{"topic": "durable agents", "summary": ""},
thread_id="thread-001",
)
result = runner.invoke(request)
if result.status != "completed":
raise RuntimeError(f"Expected completed graph, got {result.status!r}")
print(result.output)
For full examples, load references/code-patterns.md.
Gap handling rules
When a pattern is unsafe or unsupported:
- Do not silently approximate it.
- Add a concrete
# TODO(migration): ... comment near proposed code.
- Add a report entry with severity
LOW, MEDIUM, HIGH, or BLOCKER.
- Explain the bad outcome the flag prevents. Example: "the graph resumes from a
LangGraph interrupt, so code before
interrupt() in that node may run again."
- Propose the smallest safe redesign.
Report requirements
Every non-trivial migration must include or draft MIGRATION_REPORT.md with:
- source files reviewed and changed/proposed;
- classification totals;
- source pattern inventory with
file:line locations;
- chosen Kitaru graph boundary and checkpoint strategy;
- direct translations;
- approximate translations and caveats;
- flagged items with severity and required action;
- LangGraph-specific notes for
graph_call versus middleware-observed calls
replay targets, thread_id, checkpointers/stores, interrupts/resume,
streams/events, Deep Agents, capture policy, and side effects;
- verification plan and whether execution was actually run.
Use references/report-template.md when a full report is needed.
Anti-patterns
Avoid these:
- Replacing a LangGraph checkpointer/store with Kitaru.
- Claiming Kitaru replays every node, edge, stream event, or Deep Agents action.
- Using
calls without KitaruLangGraphMiddleware and calling it granular
Kitaru checkpointing.
- Treating async
awrap_model_call / awrap_tool_call metadata as true
checkpoints.
- Using
InMemorySaver as production restart-durable storage.
- Ignoring
result.status == "interrupted".
- Returning raw graph state snapshots or non-serializable framework objects from
checkpoints.
- Hiding durable side effects in stream/callback handlers without idempotency.
References
Load only the reference file needed for the current task:
references/concept-map.md — source-to-target mapping table and
classification guidance.
references/code-patterns.md — import-complete migration examples.
references/gaps-and-flags.md — severity definitions, upstream assumptions,
and must-flag patterns.
references/report-template.md — LangGraph-specific migration report template.
Kitaru source references:
- Kitaru LangGraph adapter docs:
kitaru/docs/content/docs/adapters/langgraph.mdx
- Adapter exports:
kitaru/src/kitaru/adapters/langgraph/__init__.py
- LangChain middleware:
kitaru/src/kitaru/adapters/langgraph/langchain.py
- Adapter example:
kitaru/examples/integrations/langgraph_agent/README.md