Install any skill in seconds. Free to start, no credit card required.
Get Started Free →LangGraph state-machine design and debugging for `StateGraph`, node/edge routing, checkpoints, `interrupt`, and HITL flows. Use when building or troubleshooting graph-based agents with conditional edges and thread state.
.claude/skills/majiayu000-langgraph/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 36% | 0% |
| case-07 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 52% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 26% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 4% | 0% |
pythonfrom typing import TypedDict from langgraph.graph import StateGraph, END class GraphState(TypedDict): """State passed between nodes.""" input: str output: str | None error: str | None australian_context: dict | None # Locale info def create_graph() -> StateGraph: workflow = StateGraph(GraphState) # Add nodes workflow.add_node("process", process_node) workflow.add_node("validate", validate_node) workflow.add_node("respond", respond_node) # Set entry point workflow.set_entry_point("process") # Add edges workflow.add_edge("process", "validate") workflow.add_conditional_edges( "validate", check_validation, { "valid": "respond", "invalid": END, } ) workflow.add_edge("respond", END) return workflow.compile()
pythonasync def process_node(state: GraphState) -> GraphState: """Process the input with Australian context.""" try: # Load Australian context if not present if not state.get("australian_context"): state["australian_context"] = { "locale": "en-AU", "currency": "AUD", "date_format": "DD/MM/YYYY", "timezone": "Australia/Brisbane" } result = await process_input(state["input"], state["australian_context"]) state["output"] = result except Exception as e: state["error"] = str(e) return state def check_validation(state: GraphState) -> str: """Determine next step based on state.""" if state.get("error"): return "invalid" return "valid"
pythonfrom langgraph.checkpoint.memory import MemorySaver memory = MemorySaver() graph = create_graph() app = graph.compile(checkpointer=memory) # Run with thread ID for persistence result = await app.ainvoke( { "input": "process this", "australian_context": {"locale": "en-AU"} }, config={"configurable": {"thread_id": "user-123"}} )
python# Partial state updates def update_node(state: GraphState) -> dict: return {"output": "updated value"} # Only updates 'output'
pythondef router(state: GraphState) -> str: """Route to different nodes based on state.""" input_type = classify_input(state["input"]) match input_type: case "question": return "answer_node" case "command": return "execute_node" case _: return "fallback_node" workflow.add_conditional_edges( "classify", router, { "answer_node": "answer", "execute_node": "execute", "fallback_node": "fallback", } )
pythonfrom langgraph.graph import StateGraph from typing import Annotated import operator class ParallelState(TypedDict): inputs: list[str] results: Annotated[list[str], operator.add] async def parallel_process(state: ParallelState) -> ParallelState: tasks = [process(inp) for inp in state["inputs"]] results = await asyncio.gather(*tasks) return {"results": results}
pythonclass MultiAgentState(TypedDict): """State for multi-agent coordination.""" task: str frontend_result: str | None backend_result: str | None database_result: str | None verification_result: str | None australian_context: dict def create_multi_agent_workflow() -> StateGraph: """Orchestrate multiple specialist agents.""" workflow = StateGraph(MultiAgentState) # Specialist agents as nodes workflow.add_node("frontend", frontend_agent_node) workflow.add_node("backend", backend_agent_node) workflow.add_node("database", database_agent_node) workflow.add_node("verification", verification_agent_node) # Parallel execution of specialists workflow.set_entry_point("frontend") workflow.add_edge("frontend", "backend") workflow.add_edge("backend", "database") workflow.add_edge("database", "verification") workflow.add_edge("verification", END) return workflow.compile()
pythonasync def safe_node(state: GraphState) -> GraphState: """Node with error handling.""" try: result = await risky_operation(state["input"]) return {"output": result} except ValidationError as e: return {"error": f"Validation: {e}"} except Exception as e: logger.error("Unexpected error", error=str(e), state=state) return {"error": "Internal error"}
pythonasync def australian_context_node(state: GraphState) -> GraphState: """Ensure Australian context is applied.""" if not state.get("australian_context"): state["australian_context"] = { "locale": "en-AU", "currency": "AUD", "date_format": "DD/MM/YYYY", "phone_format": "04XX XXX XXX", "regulations": ["Privacy Act 1988", "WCAG 2.1 AA"] } # Validate output against Australian standards if state.get("output"): state["output"] = apply_australian_formatting( state["output"], state["australian_context"] ) return state
python@pytest.mark.asyncio async def test_graph_happy_path(): graph = create_graph() result = await graph.ainvoke({ "input": "test", "australian_context": {"locale": "en-AU"} }) assert result["output"] is not None assert result["error"] is None assert result["australian_context"]["locale"] == "en-AU" @pytest.mark.asyncio async def test_graph_error_handling(): graph = create_graph() result = await graph.ainvoke({"input": "invalid"}) assert result["error"] is not None @pytest.mark.asyncio async def test_multi_agent_coordination(): """Test orchestrator coordinating multiple agents.""" workflow = create_multi_agent_workflow() result = await workflow.ainvoke({ "task": "Build new feature", "australian_context": {"locale": "en-AU"} }) assert result["frontend_result"] is not None assert result["backend_result"] is not None assert result["verification_result"] == "PASS"
This skill is used by:
.claude/agents/orchestrator/ - Multi-agent coordination.claude/agents/backend-specialist/ - Agent workflow implementationSee: backend/fastapi.skill.md, verification/verification-first.skill.md
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 25,423 | 21,831 | -14% | 1 | 1 | 0% | 3,448 | 4,685 | +36% | 0 | 0 | — |
case-07 | fail→pass | 21,915 | 9,593 | -56% | 1 | 1 | 0% | 3,052 | 2,784 | -9% | 0 | 0 | — |
case-08 | fail→pass | 16,555 | 12,895 | -22% | 1 | 1 | 0% | 2,806 | 4,263 | +52% | 0 | 0 | — |
case-02 | fail→pass | 22,378 | 18,639 | -17% | 1 | 1 | 0% | 4,709 | 5,936 | +26% | 0 | 0 | — |
case-03 | fail→fail | 26,041 | 20,551 | -21% | 1 | 1 | 0% | 4,155 | 6,196 | +49% | 0 | 0 | — |
case-04 | pass→pass | 12,412 | 15,952 | +29% | 1 | 1 | 0% | 2,583 | 4,152 | +61% | 0 | 0 | — |
case-05 | pass→pass | 14,039 | 14,124 | +1% | 1 | 1 | 0% | 2,954 | 4,795 | +62% | 0 | 0 | — |
case-06 | pass→pass | 14,374 | 7,109 | -51% | 1 | 1 | 0% | 1,845 | 3,334 | +81% | 0 | 0 | — |
case-09 | fail→fail | 17,880 | 11,793 | -34% | 1 | 1 | 0% | 2,332 | 3,669 | +57% | 0 | 0 | — |
case-10 | pass→pass | 10,595 | 14,170 | +34% | 1 | 1 | 0% | 2,162 | 3,671 | +70% | 0 | 0 | — |
case-11 | pass→pass | 8,933 | 10,915 | +22% | 1 | 1 | 0% | 1,584 | 2,983 | +88% | 0 | 0 | — |
case-12 | pass→pass | 11,693 | 9,570 | -18% | 1 | 1 | 0% | 2,277 | 3,732 | +64% | 0 | 0 | — |
case-13 | pass→pass | 16,009 | 11,753 | -27% | 1 | 1 | 0% | 1,982 | 4,111 | +107% | 0 | 0 | — |
case-14 | fail→fail | 48,766 | 9,938 | -80% | 1 | 1 | 0% | 2,865 | 3,818 | +33% | 0 | 0 | — |
case-15 | fail→fail | 20,566 | 15,319 | -26% | 1 | 1 | 0% | 2,762 | 3,835 | +39% | 0 | 0 | — |
case-16 | fail→pass | 19,403 | 16,162 | -17% | 1 | 1 | 0% | 3,814 | 3,976 | +4% | 0 | 0 | — |
case-17 | fail→pass | 12,458 | 5,597 | -55% | 1 | 1 | 0% | 2,447 | 2,943 | +20% | 0 | 0 | — |
case-18 | pass→pass | 11,594 | 7,836 | -32% | 1 | 1 | 0% | 2,299 | 3,259 | +42% | 0 | 0 | — |
case-19 | fail→pass | 22,262 | 11,539 | -48% | 1 | 1 | 0% | 3,180 | 4,188 | +32% | 0 | 0 | — |
case-20 | fail→pass | 11,473 | 10,417 | -9% | 1 | 1 | 0% | 2,217 | 3,875 | +75% | 0 | 0 | — |
case-21 | fail→pass | 15,655 | 9,008 | -42% | 1 | 1 | 0% | 2,713 | 3,436 | +27% | 0 | 0 | — |
case-22 | pass→pass | 14,387 | 13,116 | -9% | 1 | 1 | 0% | 1,828 | 3,496 | +91% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +41 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.