Claude Skills
CollectionsCompareWorkflowsNominate
Sign inSign up
© 2026 Curated Agent Skills·Learn more about Agent Skills
Back to repository

langgraph-code-review

verified

Reviews LangGraph code for bugs, anti-patterns, and improvements. Use when reviewing code that uses StateGraph, nodes, edges, checkpointing, or other LangGraph features. Catches common mistakes in state management, graph structure, and async patterns.

View on GitHub

Marketplace

existential-birds

existential-birds/beagle

Plugin

beagle

Repository

existential-birds/beagle
16stars

skills/langgraph-code-review/SKILL.md

Last Verified

February 1, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/existential-birds/beagle/blob/main/skills/langgraph-code-review/SKILL.md -a claude-code --skill langgraph-code-review

Installation paths:

Claude
.claude/skills/langgraph-code-review/
Powered by add-skill CLI

Instructions

# LangGraph Code Review

When reviewing LangGraph code, check for these categories of issues.

## Critical Issues

### 1. State Mutation Instead of Return

```python
# BAD - mutates state directly
def my_node(state: State) -> None:
    state["messages"].append(new_message)  # Mutation!

# GOOD - returns partial update
def my_node(state: State) -> dict:
    return {"messages": [new_message]}  # Let reducer handle it
```

### 2. Missing Reducer for List Fields

```python
# BAD - no reducer, each node overwrites
class State(TypedDict):
    messages: list  # Will be overwritten, not appended!

# GOOD - reducer appends
class State(TypedDict):
    messages: Annotated[list, operator.add]
    # Or use add_messages for chat:
    messages: Annotated[list, add_messages]
```

### 3. Wrong Return Type from Conditional Edge

```python
# BAD - returns invalid node name
def router(state) -> str:
    return "nonexistent_node"  # Runtime error!

# GOOD - use Literal type hint for safety
def router(state) -> Literal["agent", "tools", "__end__"]:
    if condition:
        return "agent"
    return END  # Use constant, not string
```

### 4. Missing Checkpointer for Interrupts

```python
# BAD - interrupt without checkpointer
def my_node(state):
    answer = interrupt("question")  # Will fail!
    return {"answer": answer}

graph = builder.compile()  # No checkpointer!

# GOOD - checkpointer required for interrupts
graph = builder.compile(checkpointer=InMemorySaver())
```

### 5. Forgetting Thread ID with Checkpointer

```python
# BAD - no thread_id
graph.invoke({"messages": [...]})  # Error with checkpointer!

# GOOD - always provide thread_id
config = {"configurable": {"thread_id": "user-123"}}
graph.invoke({"messages": [...]}, config)
```

## State Schema Issues

### 6. Using add_messages Without Message Types

```python
# BAD - add_messages expects message-like objects
class State(TypedDict):
    messages: Annotated[list, add_messages]

def node(state):
    return {"messages": ["pla

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
7876 chars