← All blueprints

Reflection Loop LangGraph

blueprint · 3 agents · 1 MCP server
1305★ stars
176forks
4.7rating

What it does

A generator produces a first draft toward the goal. A critic, given a distinct and adversarial role, reviews it and returns concrete problems rather than vague praise. The generator revises to address each, and the two loop until the critic approves or the round limit is reached. A finalizer saves the approved version. The separation of generator and critic is the point: a single agent asked to self-check tends to rubber-stamp; a dedicated critic actually catches things.

The cast · 3 agents

Criticcriticreasoning

Review the draft against the task as a demanding reviewer. List concrete, specific problems and what would fix each. Return an object with an 'approved' boolean and the issues. Approve only when you genuinely cannot find a meaningful problem.

no tools · reasoning only
Finalizerfinalizerfast

Save the approved draft to a file. If the loop ended without approval, save the best draft and note the critic's remaining concerns at the top.

fs.write_file
Generatorgeneratorreasoning

Produce a draft that meets the task. If you received a critique, revise to address every point it raised. Do not defend the previous draft; improve it.

no tools · reasoning only

Flow

↻ loop until reflection.approved == true · max 3
Generatordraft
Criticreflection
Finalizeroutput

Interface

Inputs
taskstring
What to produce, and the standard it should meet.
Outputs
outputstring
The approved final version, saved to a file.

Depends on · 1 MCP server

io.github.modelcontextprotocol/filesystemnot in the registry yetfs
⤓ Export runnable code
# Generated by @socketcat/compiler for target: langgraph
# blueprint: com.socketcat/reflection-loop v1.0.0   schema: socketcat.dev/blueprint/v0
# This code is yours. Edit it freely. The socketcat_runtime helper is optional and can be vendored.

from typing import TypedDict
from langgraph.graph import StateGraph, START, END
import socketcat_runtime as _rt

class State(TypedDict, total=False):
    task: object
    output: object
    __loop_0: object
    draft: object
    reflection: object

def node_LoopHeader_0(state):
    return {}

def node_LoopTick_1(state):
    return {"__loop_0": state.get("__loop_0", 0) + 1}

def node_Nop_2(state):
    return {}

def node_AgentInvoke_3(state):
    return _rt.run_agent("generator", state, {"task":"task","reflection":"reflection"}, "draft")

def node_AgentInvoke_4(state):
    return _rt.run_agent("critic", state, {"task":"task","draft":"draft"}, "reflection")

def node_AgentInvoke_5(state):
    return _rt.run_agent("finalizer", state, {"draft":"draft"}, "output")

def route_LoopHeader_0(state):
    count = state.get("__loop_0", 0)
    return "exit" if (_rt.cond("reflection.approved == true", state) or count >= 3) else "loop"

def build():
    b = StateGraph(State)
    b.add_node("LoopHeader_0", node_LoopHeader_0)
    b.add_node("LoopTick_1", node_LoopTick_1)
    b.add_node("Nop_2", node_Nop_2)
    b.add_node("AgentInvoke_3", node_AgentInvoke_3)
    b.add_node("AgentInvoke_4", node_AgentInvoke_4)
    b.add_node("AgentInvoke_5", node_AgentInvoke_5)
    b.add_edge(START, "AgentInvoke_3")
    b.add_conditional_edges("LoopHeader_0", route_LoopHeader_0, {"loop": "AgentInvoke_3", "exit": "Nop_2"})
    b.add_edge("LoopTick_1", "LoopHeader_0")
    b.add_edge("Nop_2", "AgentInvoke_5")
    b.add_edge("AgentInvoke_3", "AgentInvoke_4")
    b.add_edge("AgentInvoke_4", "LoopTick_1")
    b.add_edge("AgentInvoke_5", END)
    return b.compile()

INPUTS = ["task"]
OUTPUTS = ["output"]

if __name__ == "__main__":
    _rt.main(build, INPUTS, OUTPUTS)
blueprint.json (the portable format)
{
  "id": "com.socketcat/reflection-loop",
  "flow": {
    "type": "sequence",
    "blocks": [
      {
        "max": 3,
        "type": "loop",
        "until": "reflection.approved == true",
        "blocks": [
          {
            "in": {
              "task": "task",
              "reflection": "reflection"
            },
            "out": "draft",
            "use": "generator",
            "type": "agent"
          },
          {
            "in": {
              "task": "task",
              "draft": "draft"
            },
            "out": "reflection",
            "use": "critic",
            "type": "agent"
          }
        ]
      },
      {
        "in": {
          "draft": "draft"
        },
        "out": "output",
        "use": "finalizer",
        "type": "agent"
      }
    ]
  },
  "tags": [
    "reflection",
    "self-critique",
    "quality",
    "generator-critic"
  ],
  "title": "Reflection Loop",
  "agents": {
    "critic": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Critic",
      "output": {
        "type": "object",
        "required": [
          "approved"
        ],
        "properties": {
          "issues": {
            "type": "string"
          },
          "approved": {
            "type": "boolean"
          }
        }
      },
      "instructions": "Review the draft against the task as a demanding reviewer. List concrete, specific problems and what would fix each. Return an object with an 'approved' boolean and the issues. Approve only when you genuinely cannot find a meaningful problem."
    },
    "finalizer": {
      "model": {
        "hint": "fast"
      },
      "title": "Finalizer",
      "tools": [
        "fs.write_file"
      ],
      "instructions": "Save the approved draft to a file. If the loop ended without approval, save the best draft and note the critic's remaining concerns at the top."
    },
    "generator": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Generator",
      "instructions": "Produce a draft that meets the task. If you received a critique, revise to address every point it raised. Do not defend the previous draft; improve it."
    }
  },
  "estate": {
    "draft": {
      "type": "object",
      "description": "The generator's current draft."
    },
    "reflection": {
      "type": "object",
      "description": "The critic's review, including an 'approved' flag."
    }
  },
  "$schema": "socketcat.dev/blueprint/v0",
  "authors": [
    {
      "url": "https://socketcat.com",
      "name": "SocketCat"
    }
  ],
  "license": "MIT",
  "servers": [
    {
      "ref": "io.github.modelcontextprotocol/filesystem",
      "alias": "fs"
    }
  ],
  "summary": "A generator and a separate critic loop — draft, critique, revise — until the critic approves, then the result is saved.",
  "targets": [
    "langgraph",
    "crewai",
    "*"
  ],
  "version": "1.0.0",
  "interface": {
    "inputs": {
      "task": {
        "type": "string",
        "description": "What to produce, and the standard it should meet."
      }
    },
    "outputs": {
      "output": {
        "type": "string",
        "description": "The approved final version, saved to a file."
      }
    }
  },
  "extensions": {
    "dev.langgraph": {
      "checkpointer": "memory"
    }
  },
  "description": "A generator produces a first draft toward the goal. A critic, given a distinct and adversarial role, reviews it and returns concrete problems rather than vague praise. The generator revises to address each, and the two loop until the critic approves or the round limit is reached. A finalizer saves the approved version. The separation of generator and critic is the point: a single agent asked to self-check tends to rubber-stamp; a dedicated critic actually catches things."
}

More in Core patterns

Browse all →

Supervisor Team

com.socketcat/supervisor-team
LangGraph

A supervisor decides who works next — a researcher who searches or a coder who edits the repo — and assembles the result when the work is done.

21402 servers
312

Deep Research

com.socketcat/deep-research
LangGraph

Splits a hard question into sub-questions, researches them in parallel to keep the wall-clock low, then synthesizes one brief with citations.

17551 server
254

Agentic RAG

com.socketcat/agentic-rag
LangGraph

Retrieval that doesn't trust its first search: it grades the results, rewrites the query when they're weak, and only answers once the context is good.

16801 server
241