[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C536XDPQZXJ8X3ECQJTRSV":3,"skill-same:01M6C536XDPQZXJ8X3ECQJTRSV":54},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":28,"linkOnly":29,"markdownContent":30,"markdownBody":31,"frontMatter":32,"refName":33,"commitSha":34,"skillDirectory":35,"forksCount":14,"repositoryHtmlUrl":36,"repositoryHomepageUrl":6,"ownerHtmlUrl":37,"ownerBlogUrl":38,"ownerDescription":6,"updatedAt":39,"install":40,"resources":53},"01M6C536XDPQZXJ8X3ECQJTRSV","langgraph-persistence",null,"INVOKE THIS SKILL when your LangGraph needs to persist state, remember conversations, travel through history, or configure subgraph checkpointer scoping. Covers checkpointers, thread_id, time travel, Store, and subgraph persistence modes.","CoralShades\u002Facm-ai","CoralShades","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F220297585?v=4","01M6C5211QSJHZ8HXSDDWCR507","Coral Shades AI Agency","01M6C52161FNQDRQ0FRR8DAA9D",0,"MIT","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.agent\u002Fskills\u002Flanggraph-persistence\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27],"persistence","langgraph","langgraph persistence","remember","state","configure","history","scoping","travel","2026-11-10 10:12:30",false,"---\nname: langgraph-persistence\ndescription: \"INVOKE THIS SKILL when your LangGraph needs to persist state, remember conversations, travel through history, or configure subgraph checkpointer scoping. Covers checkpointers, thread_id, time travel, Store, and subgraph persistence modes.\"\n---\n\n\u003Coverview>\nLangGraph's persistence layer enables durable execution by checkpointing graph state:\n\n- **Checkpointer**: Saves\u002Floads graph state at every super-step\n- **Thread ID**: Identifies separate checkpoint sequences (conversations)\n- **Store**: Cross-thread memory for user preferences, facts\n\n**Two memory types:**\n- **Short-term** (checkpointer): Thread-scoped conversation history\n- **Long-term** (store): Cross-thread user preferences, facts\n\u003C\u002Foverview>\n\n\u003Ccheckpointer-selection>\n\n| Checkpointer | Use Case | Production Ready |\n|--------------|----------|------------------|\n| `InMemorySaver` | Testing, development | No |\n| `SqliteSaver` | Local development | Partial |\n| `PostgresSaver` | Production | Yes |\n\n\u003C\u002Fcheckpointer-selection>\n\n---\n\n## Checkpointer Setup\n\n\u003Cex-basic-persistence>\n\u003Cpython>\nSet up a basic graph with in-memory checkpointing and thread-based state persistence.\n```python\nfrom langgraph.checkpoint.memory import InMemorySaver\nfrom langgraph.graph import StateGraph, START, END\nfrom typing_extensions import TypedDict, Annotated\nimport operator\n\nclass State(TypedDict):\n    messages: Annotated[list, operator.add]\n\ndef add_message(state: State) -> dict:\n    return {\"messages\": [\"Bot response\"]}\n\ncheckpointer = InMemorySaver()\n\ngraph = (\n    StateGraph(State)\n    .add_node(\"respond\", add_message)\n    .add_edge(START, \"respond\")\n    .add_edge(\"respond\", END)\n    .compile(checkpointer=checkpointer)  # Pass at compile time\n)\n\n# ALWAYS provide thread_id\nconfig = {\"configurable\": {\"thread_id\": \"conversation-1\"}}\n\nresult1 = graph.invoke({\"messages\": [\"Hello\"]}, config)\nprint(len(result1[\"messages\"]))  # 2\n\nresult2 = graph.invoke({\"messages\": [\"How are you?\"]}, config)\nprint(len(result2[\"messages\"]))  # 4 (previous + new)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nSet up a basic graph with in-memory checkpointing and thread-based state persistence.\n```typescript\nimport { MemorySaver, StateGraph, StateSchema, MessagesValue, START, END } from \"@langchain\u002Flanggraph\";\nimport { HumanMessage } from \"@langchain\u002Fcore\u002Fmessages\";\n\nconst State = new StateSchema({ messages: MessagesValue });\n\nconst addMessage = async (state: typeof State.State) => {\n  return { messages: [{ role: \"assistant\", content: \"Bot response\" }] };\n};\n\nconst checkpointer = new MemorySaver();\n\nconst graph = new StateGraph(State)\n  .addNode(\"respond\", addMessage)\n  .addEdge(START, \"respond\")\n  .addEdge(\"respond\", END)\n  .compile({ checkpointer });\n\n\u002F\u002F ALWAYS provide thread_id\nconst config = { configurable: { thread_id: \"conversation-1\" } };\n\nconst result1 = await graph.invoke({ messages: [new HumanMessage(\"Hello\")] }, config);\nconsole.log(result1.messages.length);  \u002F\u002F 2\n\nconst result2 = await graph.invoke({ messages: [new HumanMessage(\"How are you?\")] }, config);\nconsole.log(result2.messages.length);  \u002F\u002F 4 (previous + new)\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-basic-persistence>\n\n\u003Cex-production-postgres>\n\u003Cpython>\nConfigure PostgreSQL-backed checkpointing for production deployments.\n```python\nfrom langgraph.checkpoint.postgres import PostgresSaver\n\nwith PostgresSaver.from_conn_string(\n    \"postgresql:\u002F\u002Fuser:pass@localhost\u002Fdb\"\n) as checkpointer:\n    checkpointer.setup()  # only needed on first use to create tables\n    graph = builder.compile(checkpointer=checkpointer)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nConfigure PostgreSQL-backed checkpointing for production deployments.\n```typescript\nimport { PostgresSaver } from \"@langchain\u002Flanggraph-checkpoint-postgres\";\n\nconst checkpointer = PostgresSaver.fromConnString(\n  \"postgresql:\u002F\u002Fuser:pass@localhost\u002Fdb\"\n);\nawait checkpointer.setup(); \u002F\u002F only needed on first use to create tables\n\nconst graph = builder.compile({ checkpointer });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-production-postgres>\n\n---\n\n## Thread Management\n\n\u003Cex-separate-threads>\n\u003Cpython>\nDemonstrate isolated state between different thread IDs.\n```python\n# Different threads maintain separate state\nalice_config = {\"configurable\": {\"thread_id\": \"user-alice\"}}\nbob_config = {\"configurable\": {\"thread_id\": \"user-bob\"}}\n\ngraph.invoke({\"messages\": [\"Hi from Alice\"]}, alice_config)\ngraph.invoke({\"messages\": [\"Hi from Bob\"]}, bob_config)\n\n# Alice's state is isolated from Bob's\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nDemonstrate isolated state between different thread IDs.\n```typescript\n\u002F\u002F Different threads maintain separate state\nconst aliceConfig = { configurable: { thread_id: \"user-alice\" } };\nconst bobConfig = { configurable: { thread_id: \"user-bob\" } };\n\nawait graph.invoke({ messages: [new HumanMessage(\"Hi from Alice\")] }, aliceConfig);\nawait graph.invoke({ messages: [new HumanMessage(\"Hi from Bob\")] }, bobConfig);\n\n\u002F\u002F Alice's state is isolated from Bob's\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-separate-threads>\n\n---\n\n## State History & Time Travel\n\n\u003Cex-resume-from-checkpoint>\n\u003Cpython>\nTime travel: browse checkpoint history and replay or fork from a past state.\n```python\nconfig = {\"configurable\": {\"thread_id\": \"session-1\"}}\n\nresult = graph.invoke({\"messages\": [\"start\"]}, config)\n\n# Browse checkpoint history\nstates = list(graph.get_state_history(config))\n\n# Replay from a past checkpoint\npast = states[-2]\nresult = graph.invoke(None, past.config)  # None = resume from checkpoint\n\n# Or fork: update state at a past checkpoint, then resume\nfork_config = graph.update_state(past.config, {\"messages\": [\"edited\"]})\nresult = graph.invoke(None, fork_config)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nTime travel: browse checkpoint history and replay or fork from a past state.\n```typescript\nconst config = { configurable: { thread_id: \"session-1\" } };\n\nconst result = await graph.invoke({ messages: [\"start\"] }, config);\n\n\u002F\u002F Browse checkpoint history (async iterable, collect to array)\nconst states: Awaited\u003CReturnType\u003Ctypeof graph.getState>>[] = [];\nfor await (const state of graph.getStateHistory(config)) {\n  states.push(state);\n}\n\n\u002F\u002F Replay from a past checkpoint\nconst past = states[states.length - 2];\nconst replayed = await graph.invoke(null, past.config);  \u002F\u002F null = resume from checkpoint\n\n\u002F\u002F Or fork: update state at a past checkpoint, then resume\nconst forkConfig = await graph.updateState(past.config, { messages: [\"edited\"] });\nconst forked = await graph.invoke(null, forkConfig);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-resume-from-checkpoint>\n\n\u003Cex-update-state>\n\u003Cpython>\nManually update graph state before resuming execution.\n```python\nconfig = {\"configurable\": {\"thread_id\": \"session-1\"}}\n\n# Modify state before resuming\ngraph.update_state(config, {\"data\": \"manually_updated\"})\n\n# Resume with updated state\nresult = graph.invoke(None, config)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nManually update graph state before resuming execution.\n```typescript\nconst config = { configurable: { thread_id: \"session-1\" } };\n\n\u002F\u002F Modify state before resuming\nawait graph.updateState(config, { data: \"manually_updated\" });\n\n\u002F\u002F Resume with updated state\nconst result = await graph.invoke(null, config);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-update-state>\n\n---\n\n## Subgraph Checkpointer Scoping\n\nWhen compiling a subgraph, the `checkpointer` parameter controls persistence behavior. This is critical for subgraphs that use interrupts, need multi-turn memory, or run in parallel.\n\n\u003Csubgraph-checkpointer-scoping-table>\n\n| Feature | `checkpointer=False` | `None` (default) | `True` |\n|---|---|---|---|\n| Interrupts (HITL) | No | Yes | Yes |\n| Multi-turn memory | No | No | Yes |\n| Multiple calls (different subgraphs) | Yes | Yes | Warning (namespace conflicts possible) |\n| Multiple calls (same subgraph) | Yes | Yes | No |\n| State inspection | No | Warning (current invocation only) | Yes |\n\n\u003C\u002Fsubgraph-checkpointer-scoping-table>\n\n\u003Csubgraph-checkpointer-when-to-use>\n\n### When to use each mode\n\n- **`checkpointer=False`** — Subgraph doesn't need interrupts or persistence. Simplest option, no checkpoint overhead.\n- **`None` (default \u002F omit `checkpointer`)** — Subgraph needs `interrupt()` but not multi-turn memory. Each invocation starts fresh but can pause\u002Fresume. Parallel execution works because each invocation gets a unique namespace.\n- **`checkpointer=True`** — Subgraph needs to remember state across invocations (multi-turn conversations). Each call picks up where the last left off.\n\n\u003C\u002Fsubgraph-checkpointer-when-to-use>\n\n\u003Cwarning-stateful-subgraphs-parallel>\n\n**Warning**: Stateful subgraphs (`checkpointer=True`) do NOT support calling the same subgraph instance multiple times within a single node — the calls write to the same checkpoint namespace and conflict.\n\n\u003C\u002Fwarning-stateful-subgraphs-parallel>\n\n\u003Cex-subgraph-checkpointer-modes>\n\u003Cpython>\nChoose the right checkpointer mode for your subgraph.\n```python\n# No interrupts needed — opt out of checkpointing\nsubgraph = subgraph_builder.compile(checkpointer=False)\n\n# Need interrupts but not cross-invocation persistence (default)\nsubgraph = subgraph_builder.compile()\n\n# Need cross-invocation persistence (stateful)\nsubgraph = subgraph_builder.compile(checkpointer=True)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nChoose the right checkpointer mode for your subgraph.\n```typescript\n\u002F\u002F No interrupts needed — opt out of checkpointing\nconst subgraph = subgraphBuilder.compile({ checkpointer: false });\n\n\u002F\u002F Need interrupts but not cross-invocation persistence (default)\nconst subgraph = subgraphBuilder.compile();\n\n\u002F\u002F Need cross-invocation persistence (stateful)\nconst subgraph = subgraphBuilder.compile({ checkpointer: true });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-subgraph-checkpointer-modes>\n\n\u003Cparallel-subgraph-namespacing>\n\n### Parallel subgraph namespacing\n\nWhen multiple **different** stateful subgraphs run in parallel, wrap each in its own `StateGraph` with a unique node name for stable namespace isolation:\n\n\u003Cpython>\n```python\nfrom langgraph.graph import MessagesState, StateGraph\n\ndef create_sub_agent(model, *, name, **kwargs):\n    \"\"\"Wrap an agent with a unique node name for namespace isolation.\"\"\"\n    agent = create_agent(model=model, name=name, **kwargs)\n    return (\n        StateGraph(MessagesState)\n        .add_node(name, agent)  # unique name -> stable namespace\n        .add_edge(\"__start__\", name)\n        .compile()\n    )\n\nfruit_agent = create_sub_agent(\n    \"gpt-4.1-mini\", name=\"fruit_agent\",\n    tools=[fruit_info], prompt=\"...\", checkpointer=True,\n)\nveggie_agent = create_sub_agent(\n    \"gpt-4.1-mini\", name=\"veggie_agent\",\n    tools=[veggie_info], prompt=\"...\", checkpointer=True,\n)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\n```typescript\nimport { StateGraph, StateSchema, MessagesValue, START } from \"@langchain\u002Flanggraph\";\n\nfunction createSubAgent(model: string, { name, ...kwargs }: { name: string; [key: string]: any }) {\n  const agent = createAgent({ model, name, ...kwargs });\n  return new StateGraph(new StateSchema({ messages: MessagesValue }))\n    .addNode(name, agent)  \u002F\u002F unique name -> stable namespace\n    .addEdge(START, name)\n    .compile();\n}\n\nconst fruitAgent = createSubAgent(\"gpt-4.1-mini\", {\n  name: \"fruit_agent\", tools: [fruitInfo], prompt: \"...\", checkpointer: true,\n});\nconst veggieAgent = createSubAgent(\"gpt-4.1-mini\", {\n  name: \"veggie_agent\", tools: [veggieInfo], prompt: \"...\", checkpointer: true,\n});\n```\n\u003C\u002Ftypescript>\n\nNote: Subgraphs added as nodes (via `add_node`) already get name-based namespaces automatically and don't need this wrapper.\n\n\u003C\u002Fparallel-subgraph-namespacing>\n\n---\n\n## Long-Term Memory (Store)\n\n\u003Cex-long-term-memory-store>\n\u003Cpython>\nUse a Store for cross-thread memory to share user preferences across conversations.\n```python\nfrom langgraph.store.memory import InMemoryStore\n\nstore = InMemoryStore()\n\n# Save user preference (available across ALL threads)\nstore.put((\"alice\", \"preferences\"), \"language\", {\"preference\": \"short responses\"})\n\n# Node with store — access via runtime\nfrom langgraph.runtime import Runtime\n\ndef respond(state, runtime: Runtime):\n    prefs = runtime.store.get((state[\"user_id\"], \"preferences\"), \"language\")\n    return {\"response\": f\"Using preference: {prefs.value}\"}\n\n# Compile with BOTH checkpointer and store\ngraph = builder.compile(checkpointer=checkpointer, store=store)\n\n# Both threads access same long-term memory\ngraph.invoke({\"user_id\": \"alice\"}, {\"configurable\": {\"thread_id\": \"thread-1\"}})\ngraph.invoke({\"user_id\": \"alice\"}, {\"configurable\": {\"thread_id\": \"thread-2\"}})  # Same preferences!\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse a Store for cross-thread memory to share user preferences across conversations.\n```typescript\nimport { MemoryStore } from \"@langchain\u002Flanggraph\";\n\nconst store = new MemoryStore();\n\n\u002F\u002F Save user preference (available across ALL threads)\nawait store.put([\"alice\", \"preferences\"], \"language\", { preference: \"short responses\" });\n\n\u002F\u002F Node with store — access via runtime\nconst respond = async (state: typeof State.State, runtime: any) => {\n  const item = await runtime.store?.get([\"alice\", \"preferences\"], \"language\");\n  return { response: `Using preference: ${item?.value?.preference}` };\n};\n\n\u002F\u002F Compile with BOTH checkpointer and store\nconst graph = builder.compile({ checkpointer, store });\n\n\u002F\u002F Both threads access same long-term memory\nawait graph.invoke({ userId: \"alice\" }, { configurable: { thread_id: \"thread-1\" } });\nawait graph.invoke({ userId: \"alice\" }, { configurable: { thread_id: \"thread-2\" } });  \u002F\u002F Same preferences!\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-long-term-memory-store>\n\n\u003Cex-store-operations>\n\u003Cpython>\nBasic store operations: put, get, search, and delete.\n```python\nfrom langgraph.store.memory import InMemoryStore\n\nstore = InMemoryStore()\n\nstore.put((\"user-123\", \"facts\"), \"location\", {\"city\": \"San Francisco\"})  # Put\nitem = store.get((\"user-123\", \"facts\"), \"location\")  # Get\nresults = store.search((\"user-123\", \"facts\"), filter={\"city\": \"San Francisco\"})  # Search\nstore.delete((\"user-123\", \"facts\"), \"location\")  # Delete\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-store-operations>\n\n---\n\n## Fixes\n\n\u003Cfix-thread-id-required>\n\u003Cpython>\nAlways provide thread_id in config to enable state persistence.\n```python\n# WRONG: No thread_id - state NOT persisted!\ngraph.invoke({\"messages\": [\"Hello\"]})\ngraph.invoke({\"messages\": [\"What did I say?\"]})  # Doesn't remember!\n\n# CORRECT: Always provide thread_id\nconfig = {\"configurable\": {\"thread_id\": \"session-1\"}}\ngraph.invoke({\"messages\": [\"Hello\"]}, config)\ngraph.invoke({\"messages\": [\"What did I say?\"]}, config)  # Remembers!\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nAlways provide thread_id in config to enable state persistence.\n```typescript\n\u002F\u002F WRONG: No thread_id - state NOT persisted!\nawait graph.invoke({ messages: [new HumanMessage(\"Hello\")] });\nawait graph.invoke({ messages: [new HumanMessage(\"What did I say?\")] });  \u002F\u002F Doesn't remember!\n\n\u002F\u002F CORRECT: Always provide thread_id\nconst config = { configurable: { thread_id: \"session-1\" } };\nawait graph.invoke({ messages: [new HumanMessage(\"Hello\")] }, config);\nawait graph.invoke({ messages: [new HumanMessage(\"What did I say?\")] }, config);  \u002F\u002F Remembers!\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-thread-id-required>\n\n\n\u003Cfix-inmemory-not-for-production>\n\u003Cpython>\nUse PostgresSaver instead of InMemorySaver for production persistence.\n```python\n# WRONG: Data lost on process restart\ncheckpointer = InMemorySaver()  # In-memory only!\n\n# CORRECT: Use persistent storage for production\nfrom langgraph.checkpoint.postgres import PostgresSaver\nwith PostgresSaver.from_conn_string(\"postgresql:\u002F\u002F...\") as checkpointer:\n    checkpointer.setup()  # only needed on first use to create tables\n    graph = builder.compile(checkpointer=checkpointer)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse PostgresSaver instead of MemorySaver for production persistence.\n```typescript\n\u002F\u002F WRONG: Data lost on process restart\nconst checkpointer = new MemorySaver();  \u002F\u002F In-memory only!\n\n\u002F\u002F CORRECT: Use persistent storage for production\nimport { PostgresSaver } from \"@langchain\u002Flanggraph-checkpoint-postgres\";\nconst checkpointer = PostgresSaver.fromConnString(\"postgresql:\u002F\u002F...\");\nawait checkpointer.setup(); \u002F\u002F only needed on first use to create tables\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-inmemory-not-for-production>\n\n\n\u003Cfix-update-state-with-reducers>\n\u003Cpython>\nUse Overwrite to replace state values instead of passing through reducers.\n```python\nfrom langgraph.types import Overwrite\n\n# State with reducer: items: Annotated[list, operator.add]\n# Current state: {\"items\": [\"A\", \"B\"]}\n\n# update_state PASSES THROUGH reducers\ngraph.update_state(config, {\"items\": [\"C\"]})  # Result: [\"A\", \"B\", \"C\"] - Appended!\n\n# To REPLACE instead, use Overwrite\ngraph.update_state(config, {\"items\": Overwrite([\"C\"])})  # Result: [\"C\"] - Replaced\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse Overwrite to replace state values instead of passing through reducers.\n```typescript\nimport { Overwrite } from \"@langchain\u002Flanggraph\";\n\n\u002F\u002F State with reducer: items uses concat reducer\n\u002F\u002F Current state: { items: [\"A\", \"B\"] }\n\n\u002F\u002F updateState PASSES THROUGH reducers\nawait graph.updateState(config, { items: [\"C\"] });  \u002F\u002F Result: [\"A\", \"B\", \"C\"] - Appended!\n\n\u002F\u002F To REPLACE instead, use Overwrite\nawait graph.updateState(config, { items: new Overwrite([\"C\"]) });  \u002F\u002F Result: [\"C\"] - Replaced\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-update-state-with-reducers>\n\n\u003Cfix-store-injection>\n\u003Cpython>\nAccess store via the Runtime object in graph nodes.\n```python\n# WRONG: Store not available in node\ndef my_node(state):\n    store.put(...)  # NameError! store not defined\n\n# CORRECT: Access store via runtime\nfrom langgraph.runtime import Runtime\n\ndef my_node(state, runtime: Runtime):\n    runtime.store.put(...)  # Correct store instance\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nAccess store via runtime parameter in graph nodes.\n```typescript\n\u002F\u002F WRONG: Store not available in node\nconst myNode = async (state) => {\n  store.put(...);  \u002F\u002F ReferenceError!\n};\n\n\u002F\u002F CORRECT: Access store via runtime\nconst myNode = async (state, runtime) => {\n  await runtime.store?.put(...);  \u002F\u002F Correct store instance\n};\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-store-injection>\n\n\u003Cboundaries>\n### What You Should NOT Do\n\n- Use `InMemorySaver` in production — data lost on restart; use `PostgresSaver`\n- Forget `thread_id` — state won't persist without it\n- Expect `update_state` to bypass reducers — it passes through them; use `Overwrite` to replace\n- Run the same stateful subgraph (`checkpointer=True`) in parallel within one node — namespace conflict\n- Access store directly in a node — use `runtime.store` via the `Runtime` param\n\u003C\u002Fboundaries>\n","\u003Coverview>\nLangGraph's persistence layer enables durable execution by checkpointing graph state:\n\n- **Checkpointer**: Saves\u002Floads graph state at every super-step\n- **Thread ID**: Identifies separate checkpoint sequences (conversations)\n- **Store**: Cross-thread memory for user preferences, facts\n\n**Two memory types:**\n- **Short-term** (checkpointer): Thread-scoped conversation history\n- **Long-term** (store): Cross-thread user preferences, facts\n\u003C\u002Foverview>\n\n\u003Ccheckpointer-selection>\n\n| Checkpointer | Use Case | Production Ready |\n|--------------|----------|------------------|\n| `InMemorySaver` | Testing, development | No |\n| `SqliteSaver` | Local development | Partial |\n| `PostgresSaver` | Production | Yes |\n\n\u003C\u002Fcheckpointer-selection>\n\n---\n\n## Checkpointer Setup\n\n\u003Cex-basic-persistence>\n\u003Cpython>\nSet up a basic graph with in-memory checkpointing and thread-based state persistence.\n```python\nfrom langgraph.checkpoint.memory import InMemorySaver\nfrom langgraph.graph import StateGraph, START, END\nfrom typing_extensions import TypedDict, Annotated\nimport operator\n\nclass State(TypedDict):\n    messages: Annotated[list, operator.add]\n\ndef add_message(state: State) -> dict:\n    return {\"messages\": [\"Bot response\"]}\n\ncheckpointer = InMemorySaver()\n\ngraph = (\n    StateGraph(State)\n    .add_node(\"respond\", add_message)\n    .add_edge(START, \"respond\")\n    .add_edge(\"respond\", END)\n    .compile(checkpointer=checkpointer)  # Pass at compile time\n)\n\n# ALWAYS provide thread_id\nconfig = {\"configurable\": {\"thread_id\": \"conversation-1\"}}\n\nresult1 = graph.invoke({\"messages\": [\"Hello\"]}, config)\nprint(len(result1[\"messages\"]))  # 2\n\nresult2 = graph.invoke({\"messages\": [\"How are you?\"]}, config)\nprint(len(result2[\"messages\"]))  # 4 (previous + new)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nSet up a basic graph with in-memory checkpointing and thread-based state persistence.\n```typescript\nimport { MemorySaver, StateGraph, StateSchema, MessagesValue, START, END } from \"@langchain\u002Flanggraph\";\nimport { HumanMessage } from \"@langchain\u002Fcore\u002Fmessages\";\n\nconst State = new StateSchema({ messages: MessagesValue });\n\nconst addMessage = async (state: typeof State.State) => {\n  return { messages: [{ role: \"assistant\", content: \"Bot response\" }] };\n};\n\nconst checkpointer = new MemorySaver();\n\nconst graph = new StateGraph(State)\n  .addNode(\"respond\", addMessage)\n  .addEdge(START, \"respond\")\n  .addEdge(\"respond\", END)\n  .compile({ checkpointer });\n\n\u002F\u002F ALWAYS provide thread_id\nconst config = { configurable: { thread_id: \"conversation-1\" } };\n\nconst result1 = await graph.invoke({ messages: [new HumanMessage(\"Hello\")] }, config);\nconsole.log(result1.messages.length);  \u002F\u002F 2\n\nconst result2 = await graph.invoke({ messages: [new HumanMessage(\"How are you?\")] }, config);\nconsole.log(result2.messages.length);  \u002F\u002F 4 (previous + new)\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-basic-persistence>\n\n\u003Cex-production-postgres>\n\u003Cpython>\nConfigure PostgreSQL-backed checkpointing for production deployments.\n```python\nfrom langgraph.checkpoint.postgres import PostgresSaver\n\nwith PostgresSaver.from_conn_string(\n    \"postgresql:\u002F\u002Fuser:pass@localhost\u002Fdb\"\n) as checkpointer:\n    checkpointer.setup()  # only needed on first use to create tables\n    graph = builder.compile(checkpointer=checkpointer)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nConfigure PostgreSQL-backed checkpointing for production deployments.\n```typescript\nimport { PostgresSaver } from \"@langchain\u002Flanggraph-checkpoint-postgres\";\n\nconst checkpointer = PostgresSaver.fromConnString(\n  \"postgresql:\u002F\u002Fuser:pass@localhost\u002Fdb\"\n);\nawait checkpointer.setup(); \u002F\u002F only needed on first use to create tables\n\nconst graph = builder.compile({ checkpointer });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-production-postgres>\n\n---\n\n## Thread Management\n\n\u003Cex-separate-threads>\n\u003Cpython>\nDemonstrate isolated state between different thread IDs.\n```python\n# Different threads maintain separate state\nalice_config = {\"configurable\": {\"thread_id\": \"user-alice\"}}\nbob_config = {\"configurable\": {\"thread_id\": \"user-bob\"}}\n\ngraph.invoke({\"messages\": [\"Hi from Alice\"]}, alice_config)\ngraph.invoke({\"messages\": [\"Hi from Bob\"]}, bob_config)\n\n# Alice's state is isolated from Bob's\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nDemonstrate isolated state between different thread IDs.\n```typescript\n\u002F\u002F Different threads maintain separate state\nconst aliceConfig = { configurable: { thread_id: \"user-alice\" } };\nconst bobConfig = { configurable: { thread_id: \"user-bob\" } };\n\nawait graph.invoke({ messages: [new HumanMessage(\"Hi from Alice\")] }, aliceConfig);\nawait graph.invoke({ messages: [new HumanMessage(\"Hi from Bob\")] }, bobConfig);\n\n\u002F\u002F Alice's state is isolated from Bob's\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-separate-threads>\n\n---\n\n## State History & Time Travel\n\n\u003Cex-resume-from-checkpoint>\n\u003Cpython>\nTime travel: browse checkpoint history and replay or fork from a past state.\n```python\nconfig = {\"configurable\": {\"thread_id\": \"session-1\"}}\n\nresult = graph.invoke({\"messages\": [\"start\"]}, config)\n\n# Browse checkpoint history\nstates = list(graph.get_state_history(config))\n\n# Replay from a past checkpoint\npast = states[-2]\nresult = graph.invoke(None, past.config)  # None = resume from checkpoint\n\n# Or fork: update state at a past checkpoint, then resume\nfork_config = graph.update_state(past.config, {\"messages\": [\"edited\"]})\nresult = graph.invoke(None, fork_config)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nTime travel: browse checkpoint history and replay or fork from a past state.\n```typescript\nconst config = { configurable: { thread_id: \"session-1\" } };\n\nconst result = await graph.invoke({ messages: [\"start\"] }, config);\n\n\u002F\u002F Browse checkpoint history (async iterable, collect to array)\nconst states: Awaited\u003CReturnType\u003Ctypeof graph.getState>>[] = [];\nfor await (const state of graph.getStateHistory(config)) {\n  states.push(state);\n}\n\n\u002F\u002F Replay from a past checkpoint\nconst past = states[states.length - 2];\nconst replayed = await graph.invoke(null, past.config);  \u002F\u002F null = resume from checkpoint\n\n\u002F\u002F Or fork: update state at a past checkpoint, then resume\nconst forkConfig = await graph.updateState(past.config, { messages: [\"edited\"] });\nconst forked = await graph.invoke(null, forkConfig);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-resume-from-checkpoint>\n\n\u003Cex-update-state>\n\u003Cpython>\nManually update graph state before resuming execution.\n```python\nconfig = {\"configurable\": {\"thread_id\": \"session-1\"}}\n\n# Modify state before resuming\ngraph.update_state(config, {\"data\": \"manually_updated\"})\n\n# Resume with updated state\nresult = graph.invoke(None, config)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nManually update graph state before resuming execution.\n```typescript\nconst config = { configurable: { thread_id: \"session-1\" } };\n\n\u002F\u002F Modify state before resuming\nawait graph.updateState(config, { data: \"manually_updated\" });\n\n\u002F\u002F Resume with updated state\nconst result = await graph.invoke(null, config);\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-update-state>\n\n---\n\n## Subgraph Checkpointer Scoping\n\nWhen compiling a subgraph, the `checkpointer` parameter controls persistence behavior. This is critical for subgraphs that use interrupts, need multi-turn memory, or run in parallel.\n\n\u003Csubgraph-checkpointer-scoping-table>\n\n| Feature | `checkpointer=False` | `None` (default) | `True` |\n|---|---|---|---|\n| Interrupts (HITL) | No | Yes | Yes |\n| Multi-turn memory | No | No | Yes |\n| Multiple calls (different subgraphs) | Yes | Yes | Warning (namespace conflicts possible) |\n| Multiple calls (same subgraph) | Yes | Yes | No |\n| State inspection | No | Warning (current invocation only) | Yes |\n\n\u003C\u002Fsubgraph-checkpointer-scoping-table>\n\n\u003Csubgraph-checkpointer-when-to-use>\n\n### When to use each mode\n\n- **`checkpointer=False`** — Subgraph doesn't need interrupts or persistence. Simplest option, no checkpoint overhead.\n- **`None` (default \u002F omit `checkpointer`)** — Subgraph needs `interrupt()` but not multi-turn memory. Each invocation starts fresh but can pause\u002Fresume. Parallel execution works because each invocation gets a unique namespace.\n- **`checkpointer=True`** — Subgraph needs to remember state across invocations (multi-turn conversations). Each call picks up where the last left off.\n\n\u003C\u002Fsubgraph-checkpointer-when-to-use>\n\n\u003Cwarning-stateful-subgraphs-parallel>\n\n**Warning**: Stateful subgraphs (`checkpointer=True`) do NOT support calling the same subgraph instance multiple times within a single node — the calls write to the same checkpoint namespace and conflict.\n\n\u003C\u002Fwarning-stateful-subgraphs-parallel>\n\n\u003Cex-subgraph-checkpointer-modes>\n\u003Cpython>\nChoose the right checkpointer mode for your subgraph.\n```python\n# No interrupts needed — opt out of checkpointing\nsubgraph = subgraph_builder.compile(checkpointer=False)\n\n# Need interrupts but not cross-invocation persistence (default)\nsubgraph = subgraph_builder.compile()\n\n# Need cross-invocation persistence (stateful)\nsubgraph = subgraph_builder.compile(checkpointer=True)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nChoose the right checkpointer mode for your subgraph.\n```typescript\n\u002F\u002F No interrupts needed — opt out of checkpointing\nconst subgraph = subgraphBuilder.compile({ checkpointer: false });\n\n\u002F\u002F Need interrupts but not cross-invocation persistence (default)\nconst subgraph = subgraphBuilder.compile();\n\n\u002F\u002F Need cross-invocation persistence (stateful)\nconst subgraph = subgraphBuilder.compile({ checkpointer: true });\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-subgraph-checkpointer-modes>\n\n\u003Cparallel-subgraph-namespacing>\n\n### Parallel subgraph namespacing\n\nWhen multiple **different** stateful subgraphs run in parallel, wrap each in its own `StateGraph` with a unique node name for stable namespace isolation:\n\n\u003Cpython>\n```python\nfrom langgraph.graph import MessagesState, StateGraph\n\ndef create_sub_agent(model, *, name, **kwargs):\n    \"\"\"Wrap an agent with a unique node name for namespace isolation.\"\"\"\n    agent = create_agent(model=model, name=name, **kwargs)\n    return (\n        StateGraph(MessagesState)\n        .add_node(name, agent)  # unique name -> stable namespace\n        .add_edge(\"__start__\", name)\n        .compile()\n    )\n\nfruit_agent = create_sub_agent(\n    \"gpt-4.1-mini\", name=\"fruit_agent\",\n    tools=[fruit_info], prompt=\"...\", checkpointer=True,\n)\nveggie_agent = create_sub_agent(\n    \"gpt-4.1-mini\", name=\"veggie_agent\",\n    tools=[veggie_info], prompt=\"...\", checkpointer=True,\n)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\n```typescript\nimport { StateGraph, StateSchema, MessagesValue, START } from \"@langchain\u002Flanggraph\";\n\nfunction createSubAgent(model: string, { name, ...kwargs }: { name: string; [key: string]: any }) {\n  const agent = createAgent({ model, name, ...kwargs });\n  return new StateGraph(new StateSchema({ messages: MessagesValue }))\n    .addNode(name, agent)  \u002F\u002F unique name -> stable namespace\n    .addEdge(START, name)\n    .compile();\n}\n\nconst fruitAgent = createSubAgent(\"gpt-4.1-mini\", {\n  name: \"fruit_agent\", tools: [fruitInfo], prompt: \"...\", checkpointer: true,\n});\nconst veggieAgent = createSubAgent(\"gpt-4.1-mini\", {\n  name: \"veggie_agent\", tools: [veggieInfo], prompt: \"...\", checkpointer: true,\n});\n```\n\u003C\u002Ftypescript>\n\nNote: Subgraphs added as nodes (via `add_node`) already get name-based namespaces automatically and don't need this wrapper.\n\n\u003C\u002Fparallel-subgraph-namespacing>\n\n---\n\n## Long-Term Memory (Store)\n\n\u003Cex-long-term-memory-store>\n\u003Cpython>\nUse a Store for cross-thread memory to share user preferences across conversations.\n```python\nfrom langgraph.store.memory import InMemoryStore\n\nstore = InMemoryStore()\n\n# Save user preference (available across ALL threads)\nstore.put((\"alice\", \"preferences\"), \"language\", {\"preference\": \"short responses\"})\n\n# Node with store — access via runtime\nfrom langgraph.runtime import Runtime\n\ndef respond(state, runtime: Runtime):\n    prefs = runtime.store.get((state[\"user_id\"], \"preferences\"), \"language\")\n    return {\"response\": f\"Using preference: {prefs.value}\"}\n\n# Compile with BOTH checkpointer and store\ngraph = builder.compile(checkpointer=checkpointer, store=store)\n\n# Both threads access same long-term memory\ngraph.invoke({\"user_id\": \"alice\"}, {\"configurable\": {\"thread_id\": \"thread-1\"}})\ngraph.invoke({\"user_id\": \"alice\"}, {\"configurable\": {\"thread_id\": \"thread-2\"}})  # Same preferences!\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse a Store for cross-thread memory to share user preferences across conversations.\n```typescript\nimport { MemoryStore } from \"@langchain\u002Flanggraph\";\n\nconst store = new MemoryStore();\n\n\u002F\u002F Save user preference (available across ALL threads)\nawait store.put([\"alice\", \"preferences\"], \"language\", { preference: \"short responses\" });\n\n\u002F\u002F Node with store — access via runtime\nconst respond = async (state: typeof State.State, runtime: any) => {\n  const item = await runtime.store?.get([\"alice\", \"preferences\"], \"language\");\n  return { response: `Using preference: ${item?.value?.preference}` };\n};\n\n\u002F\u002F Compile with BOTH checkpointer and store\nconst graph = builder.compile({ checkpointer, store });\n\n\u002F\u002F Both threads access same long-term memory\nawait graph.invoke({ userId: \"alice\" }, { configurable: { thread_id: \"thread-1\" } });\nawait graph.invoke({ userId: \"alice\" }, { configurable: { thread_id: \"thread-2\" } });  \u002F\u002F Same preferences!\n```\n\u003C\u002Ftypescript>\n\u003C\u002Fex-long-term-memory-store>\n\n\u003Cex-store-operations>\n\u003Cpython>\nBasic store operations: put, get, search, and delete.\n```python\nfrom langgraph.store.memory import InMemoryStore\n\nstore = InMemoryStore()\n\nstore.put((\"user-123\", \"facts\"), \"location\", {\"city\": \"San Francisco\"})  # Put\nitem = store.get((\"user-123\", \"facts\"), \"location\")  # Get\nresults = store.search((\"user-123\", \"facts\"), filter={\"city\": \"San Francisco\"})  # Search\nstore.delete((\"user-123\", \"facts\"), \"location\")  # Delete\n```\n\u003C\u002Fpython>\n\u003C\u002Fex-store-operations>\n\n---\n\n## Fixes\n\n\u003Cfix-thread-id-required>\n\u003Cpython>\nAlways provide thread_id in config to enable state persistence.\n```python\n# WRONG: No thread_id - state NOT persisted!\ngraph.invoke({\"messages\": [\"Hello\"]})\ngraph.invoke({\"messages\": [\"What did I say?\"]})  # Doesn't remember!\n\n# CORRECT: Always provide thread_id\nconfig = {\"configurable\": {\"thread_id\": \"session-1\"}}\ngraph.invoke({\"messages\": [\"Hello\"]}, config)\ngraph.invoke({\"messages\": [\"What did I say?\"]}, config)  # Remembers!\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nAlways provide thread_id in config to enable state persistence.\n```typescript\n\u002F\u002F WRONG: No thread_id - state NOT persisted!\nawait graph.invoke({ messages: [new HumanMessage(\"Hello\")] });\nawait graph.invoke({ messages: [new HumanMessage(\"What did I say?\")] });  \u002F\u002F Doesn't remember!\n\n\u002F\u002F CORRECT: Always provide thread_id\nconst config = { configurable: { thread_id: \"session-1\" } };\nawait graph.invoke({ messages: [new HumanMessage(\"Hello\")] }, config);\nawait graph.invoke({ messages: [new HumanMessage(\"What did I say?\")] }, config);  \u002F\u002F Remembers!\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-thread-id-required>\n\n\n\u003Cfix-inmemory-not-for-production>\n\u003Cpython>\nUse PostgresSaver instead of InMemorySaver for production persistence.\n```python\n# WRONG: Data lost on process restart\ncheckpointer = InMemorySaver()  # In-memory only!\n\n# CORRECT: Use persistent storage for production\nfrom langgraph.checkpoint.postgres import PostgresSaver\nwith PostgresSaver.from_conn_string(\"postgresql:\u002F\u002F...\") as checkpointer:\n    checkpointer.setup()  # only needed on first use to create tables\n    graph = builder.compile(checkpointer=checkpointer)\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse PostgresSaver instead of MemorySaver for production persistence.\n```typescript\n\u002F\u002F WRONG: Data lost on process restart\nconst checkpointer = new MemorySaver();  \u002F\u002F In-memory only!\n\n\u002F\u002F CORRECT: Use persistent storage for production\nimport { PostgresSaver } from \"@langchain\u002Flanggraph-checkpoint-postgres\";\nconst checkpointer = PostgresSaver.fromConnString(\"postgresql:\u002F\u002F...\");\nawait checkpointer.setup(); \u002F\u002F only needed on first use to create tables\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-inmemory-not-for-production>\n\n\n\u003Cfix-update-state-with-reducers>\n\u003Cpython>\nUse Overwrite to replace state values instead of passing through reducers.\n```python\nfrom langgraph.types import Overwrite\n\n# State with reducer: items: Annotated[list, operator.add]\n# Current state: {\"items\": [\"A\", \"B\"]}\n\n# update_state PASSES THROUGH reducers\ngraph.update_state(config, {\"items\": [\"C\"]})  # Result: [\"A\", \"B\", \"C\"] - Appended!\n\n# To REPLACE instead, use Overwrite\ngraph.update_state(config, {\"items\": Overwrite([\"C\"])})  # Result: [\"C\"] - Replaced\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nUse Overwrite to replace state values instead of passing through reducers.\n```typescript\nimport { Overwrite } from \"@langchain\u002Flanggraph\";\n\n\u002F\u002F State with reducer: items uses concat reducer\n\u002F\u002F Current state: { items: [\"A\", \"B\"] }\n\n\u002F\u002F updateState PASSES THROUGH reducers\nawait graph.updateState(config, { items: [\"C\"] });  \u002F\u002F Result: [\"A\", \"B\", \"C\"] - Appended!\n\n\u002F\u002F To REPLACE instead, use Overwrite\nawait graph.updateState(config, { items: new Overwrite([\"C\"]) });  \u002F\u002F Result: [\"C\"] - Replaced\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-update-state-with-reducers>\n\n\u003Cfix-store-injection>\n\u003Cpython>\nAccess store via the Runtime object in graph nodes.\n```python\n# WRONG: Store not available in node\ndef my_node(state):\n    store.put(...)  # NameError! store not defined\n\n# CORRECT: Access store via runtime\nfrom langgraph.runtime import Runtime\n\ndef my_node(state, runtime: Runtime):\n    runtime.store.put(...)  # Correct store instance\n```\n\u003C\u002Fpython>\n\u003Ctypescript>\nAccess store via runtime parameter in graph nodes.\n```typescript\n\u002F\u002F WRONG: Store not available in node\nconst myNode = async (state) => {\n  store.put(...);  \u002F\u002F ReferenceError!\n};\n\n\u002F\u002F CORRECT: Access store via runtime\nconst myNode = async (state, runtime) => {\n  await runtime.store?.put(...);  \u002F\u002F Correct store instance\n};\n```\n\u003C\u002Ftypescript>\n\u003C\u002Ffix-store-injection>\n\n\u003Cboundaries>\n### What You Should NOT Do\n\n- Use `InMemorySaver` in production — data lost on restart; use `PostgresSaver`\n- Forget `thread_id` — state won't persist without it\n- Expect `update_state` to bypass reducers — it passes through them; use `Overwrite` to replace\n- Run the same stateful subgraph (`checkpointer=True`) in parallel within one node — namespace conflict\n- Access store directly in a node — use `runtime.store` via the `Runtime` param\n\u003C\u002Fboundaries>\n",{"name":5,"description":7},"main","1ca81b0a7de199942400f965edd4d7544077ac5d",".agent\u002Fskills\u002Flanggraph-persistence","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai","https:\u002F\u002Fgithub.com\u002FCoralShades","coralshades.com.au","2026-04-18 00:45:07",{"source":8,"skillName":5,"commands":41,"prompt":51,"zipAvailable":52},[42,45,48],{"tool":43,"command":44},"npx","npx skills add CoralShades\u002Facm-ai --skill langgraph-persistence",{"tool":46,"command":47},"bunx","bunx skills add CoralShades\u002Facm-ai --skill langgraph-persistence",{"tool":49,"command":50},"pnpm","pnpm dlx skills add CoralShades\u002Facm-ai --skill langgraph-persistence","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.agent\u002Fskills\u002Flanggraph-persistence\u002FSKILL.md",true,[],[55,79,92,97,119,129],{"skillNo":56,"name":57,"nameZh":6,"description":58,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":59,"categories":60,"keywords":66,"publishedAt":28},"01M6C63HKXA890HHV47WBAX0TB","uncodixfy","Prevents generic AI\u002FCodex UI patterns when generating frontend code. Use this skill whenever generating HTML, CSS, React, Vue, Svelte, or any frontend UI code to enforce clean, human-designed aesthetics inspired by Linear, Raycast, Stripe, and GitHub instead of typical AI-generated UI.","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Funcodixfy\u002FSKILL.md",[61],{"categoryNo":62,"categoryName":63,"taxonomyType":64,"taxonomyTypeDesc":65},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[57,67,68,69,70,71,72,73,74,75,76,77,78],"github","frontend","css","codex","react","code","linear","ui","vue","generated","use","html",{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":83,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":28},"01M6C63FJ2GEBBGZ5XSMV40KXB","runpodctl","Runpod CLI to manage your GPU workloads.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Frunpodctl\u002FSKILL.md",[],[81,87,88,89,90,91],"macos","cli","linux","gpu","Bash",{"skillNo":93,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":28},"01M6C63DPAV46TFVQ01SFYPJ7X","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flanggraph-persistence\u002FSKILL.md",[],[21,20,19,27,25,26,22,23,24],{"skillNo":98,"name":99,"nameZh":6,"description":100,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":108,"publishedAt":28},"01M6C63BNS9CQEBTB8RNSSBFPA","langgraph-human-in-the-loop","INVOKE THIS SKILL when implementing human-in-the-loop patterns, pausing for approval, or handling errors in LangGraph. Covers interrupt(), Command(resume=...), approval\u002Fvalidation workflows, and the 4-tier error handling strategy.","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flanggraph-human-in-the-loop\u002FSKILL.md",[103],{"categoryNo":104,"categoryName":105,"taxonomyType":106,"taxonomyTypeDesc":107},"01JBSEEDCAT000000000000038","人力资源","PROFESSION","适用职业",[109,110,20,111,112,113,114,115,116,117,118],"langgraph human in the loop","loop","workflows","error handling","validation","human-in-the-loop","command","strategy","approval","resume",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":125,"publishedAt":28},"01M6C639GVYZFX3NFPV5FBDR4F","langgraph-fundamentals","INVOKE THIS SKILL when writing ANY LangGraph code. Covers StateGraph, state schemas, nodes, edges, Command, Send, invoke, streaming, and error handling.","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flanggraph-fundamentals\u002FSKILL.md",[],[126,20,112,23,127,128,115,72],"langgraph fundamentals","streaming","writing",{"skillNo":130,"name":131,"nameZh":6,"description":132,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":133,"categories":134,"keywords":135,"publishedAt":28},"01M6C6375N34YX2GZ3SD3R7XR2","langchain-rag","INVOKE THIS SKILL when building ANY retrieval-augmented generation (RAG) system. Covers document loaders, RecursiveCharacterTextSplitter, embeddings (OpenAI), and vector stores (Chroma, FAISS, Pinecone).","https:\u002F\u002Fgithub.com\u002FCoralShades\u002Facm-ai\u002Fblob\u002Fmain\u002F.qwen\u002Fskills\u002Flangchain-rag\u002FSKILL.md",[],[136,137,138,139,140,141,142,143,144,145],"rag","langchain rag","langchain","embeddings","vector","openai","chroma","faiss","vector stores","system"]