Guides architectural decisions for LangGraph applications. Use when deciding between LangGraph vs alternatives, choosing state management strategies, designing multi-agent systems, or selecting persistence and streaming approaches.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
langgraph-architecture
description
Guides architectural decisions for LangGraph applications. Use when deciding between LangGraph vs alternatives, choosing state management strategies, designing multi-agent systems, or selecting persistence and streaming approaches.
LangGraph Architecture Decisions
When to Use LangGraph
Use LangGraph When You Need:
Stateful conversations - Multi-turn interactions with memory
Recommendation: Use TypedDict for most cases. Use Pydantic when you need validation or complex nested structures.
Reducer Selection
Use Case
Reducer
Example
Chat messages
add_messages
Handles IDs, RemoveMessage
Simple append
operator.add
Annotated[list, operator.add]
Keep latest
None (LastValue)
field: str
Custom merge
Lambda
Annotated[list, lambda a, b: ...]
Overwrite list
Overwrite
Bypass reducer
State Size Considerations
# SMALL STATE (< 1MB) - Put in stateclassState(TypedDict):
messages: Annotated[list, add_messages]
context: str# LARGE DATA - Use StoreclassState(TypedDict):
messages: Annotated[list, add_messages]
document_ref: str# Reference to storedefnode(state, *, store: BaseStore):
doc = store.get(namespace, state["document_ref"])
# Process without bloating checkpoints
Graph Structure Decisions
Single Graph vs Subgraphs
Single Graph when:
All nodes share the same state schema
Simple linear or branching flow
< 10 nodes
Subgraphs when:
Different state schemas needed
Reusable components across graphs
Team separation of concerns
Complex hierarchical workflows
Conditional Edges vs Command
Conditional Edges
Command
Routing based on state
Routing + state update
Separate router function
Decision in node
Clearer visualization
More flexible
Standard patterns
Dynamic destinations
# Conditional Edge - when routing is the focusdefrouter(state) -> Literal["a", "b"]:
return"a"if condition else"b"
builder.add_conditional_edges("node", router)
# Command - when combining routing with updatesdefnode(state) -> Command:
return Command(goto="next", update={"step": state["step"] + 1})
# Stream from subgraphsasyncfor chunk in graph.astream(
input,
stream_mode="updates",
subgraphs=True# Include subgraph events
):
namespace, data = chunk # namespace indicates depth
Human-in-the-Loop Design
Interrupt Placement
Strategy
Use Case
interrupt_before
Approval before action
interrupt_after
Review after completion
interrupt() in node
Dynamic, contextual pauses
Resume Patterns
# Simple resume (same thread)
graph.invoke(None, config)
# Resume with value
graph.invoke(Command(resume="approved"), config)
# Resume specific interrupt
graph.invoke(Command(resume={interrupt_id: value}), config)
# Modify state and resume
graph.update_state(config, {"field": "new_value"})
graph.invoke(None, config)
Gates (sequenced)
Complete in order before treating a LangGraph design as locked in. Each step has an objective pass condition (artifact or explicit “none”), not an honor-system “we considered it.”
Alternatives — Pass: For the workload, either (a) at least one row from Consider Alternatives When was evaluated and rejected with a one-line reason, or (b) the use case clearly matches Use LangGraph When You Need and does not fit a “consider alternative” row.
State contract — Pass: Every state field has an assigned reducer (or default/LastValue) documented in the same place as the schema; large payloads are references or Store-backed, not inlined blobs (see State Size Considerations).
Checkpointer — Pass: The saver type is chosen for the target environment per Checkpointer Selection (e.g. production is not InMemorySaver unless explicitly test-only).
Loops and flaky nodes — Pass:recursion_limit (or equivalent) is set for any graph that can cycle; per-node RetryPolicy or a documented “no retries” choice exists for external calls (see Retry Configuration).