LangGraph State Machine Designer — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited LangGraph State Machine Designer (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill takes a plain-language description of an agentic workflow and designs the corresponding LangGraph state machine: typed state schema, node functions, conditional edges, and checkpoint configuration. It handles the hard parts — state typing, routing logic, error recovery, and human-in-the-loop interrupts.
Copy this file to .agents/skills/langgraph-state-machine-designer/SKILL.md in your project root.
Then ask:
Provide:
Describe the workflow and paste these instructions. Ask for the full graph code.
When asked to design a LangGraph state machine, produce the following:
Every LangGraph graph has a single shared state object. Define it as a TypedDict with Annotated fields for lists (so they append rather than overwrite):
from typing import TypedDict, Annotated, Sequence
from langchain_core.messages import BaseMessage
import operator
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], operator.add]
# Add task-specific fields:
query: str
search_results: list[str]
draft: str
approved: bool
error: str | NoneRules for state design:
Annotated[list, operator.add] for any field that accumulates over time (messages, results)error field to every state — nodes should write errors here instead of raisingEach node is a function that takes state and returns a partial state update:
def call_model(state: AgentState) -> dict:
"""Main LLM reasoning node."""
response = llm.invoke(state["messages"])
return {"messages": [response]}
def run_tool(state: AgentState) -> dict:
"""Execute the tool the model requested."""
last_message = state["messages"][-1]
tool_result = execute_tool(last_message.tool_calls[0])
return {"messages": [ToolMessage(content=tool_result)]}
def handle_error(state: AgentState) -> dict:
"""Graceful error recovery node."""
return {"messages": [AIMessage(content="I encountered an error. Let me try a different approach.")], "error": None}Node design rules:
state["error"]from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode
builder = StateGraph(AgentState)
# Add nodes
builder.add_node("agent", call_model)
builder.add_node("tools", ToolNode(tools))
builder.add_node("error_handler", handle_error)
# Set entry point
builder.set_entry_point("agent")
# Conditional routing
def should_continue(state: AgentState) -> str:
last = state["messages"][-1]
if state.get("error"):
return "error_handler"
if hasattr(last, "tool_calls") and last.tool_calls:
return "tools"
return END
builder.add_conditional_edges("agent", should_continue, {
"tools": "tools",
"error_handler": "error_handler",
END: END
})
builder.add_edge("tools", "agent")
builder.add_edge("error_handler", "agent")For workflows requiring human approval before destructive actions:
from langgraph.checkpoint.memory import MemorySaver
# Compile with checkpointer
memory = MemorySaver()
graph = builder.compile(
checkpointer=memory,
interrupt_before=["execute_action"] # pause before this node
)
# Run until interrupt
config = {"configurable": {"thread_id": "thread_001"}}
result = graph.invoke({"messages": [HumanMessage(content=user_query)]}, config)
# Resume after human approval
graph.invoke(None, config) # continues from checkpointPattern: ReAct agent (reason → act → observe loop)
entry → agent → [tools | END]
↑_______|Pattern: Multi-step pipeline (sequential)
entry → step_1 → step_2 → step_3 → ENDPattern: Supervisor with sub-agents
entry → supervisor → [researcher | writer | reviewer | END]
↑___________________________|Pattern: Retry with fallback
entry → primary_agent → [success: END | failure: fallback_agent → END]Always produce:
AgentState TypedDictInput:
"Design a LangGraph agent that takes a user question, searches the web, then writes a summarized answer. No human approval needed."
Output:
from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage, HumanMessage
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode
class ResearchState(TypedDict):
messages: Annotated[Sequence[BaseMessage], operator.add]
query: str
def research_agent(state: ResearchState) -> dict:
response = llm_with_tools.invoke(state["messages"])
return {"messages": [response]}
def should_continue(state: ResearchState) -> str:
last = state["messages"][-1]
if hasattr(last, "tool_calls") and last.tool_calls:
return "search"
return END
builder = StateGraph(ResearchState)
builder.add_node("agent", research_agent)
builder.add_node("search", ToolNode([web_search_tool]))
builder.set_entry_point("agent")
builder.add_conditional_edges("agent", should_continue, {"search": "search", END: END})
builder.add_edge("search", "agent")
graph = builder.compile()~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.