← All blueprints

Feedback Synthesizer LangGraph

blueprint · 5 agents · 3 MCP servers
1043★ stars
137forks
4.7rating

What it does

Two collectors run in parallel: one pulls support tickets and product reviews from the warehouse, the other reads recent issue and discussion threads from GitHub. A synthesizer clusters the combined feedback into themes, each backed by representative quotes and a count so the weight of each is clear. A filer turns the highest-signal themes into well-formed feature issues, deduping against what is already open. A writer posts a digest to the product channel so the team sees the ranked voice of the customer. Point the collectors at your own stores.

The cast · 5 agents

Filerfilerfast

For the top themes, file a well-formed feature issue each: the problem in the user's words, the evidence, and the count. Before filing, check open issues and skip or link any duplicate rather than creating a second one.

code.create_issue
Writerwriterfast

Post a digest to the product channel: the ranked themes with their counts and the issues filed or linked. Keep it skimmable.

chat.post_message
Synthesizersynthesizerreasoning

Cluster the combined feedback into distinct themes. For each theme give a clear name, two or three representative real quotes, and how many items it covers. Rank by weight. Do not merge unrelated asks to inflate a count.

no tools · reasoning only
ThreadsthreadsAgentfast

List recent GitHub issues and discussions in the window that carry user feedback or requests. Return each with its title, a representative quote, and its reaction count.

code.list_issues
TicketsticketsAgentfast

Query the warehouse for support tickets and product reviews in the window. Return each with its text, source, and date. Read-only.

db.query_dsl

Flow

⇉ parallel
Ticketstickets
Threadsthreads
Synthesizerthemes
Filerthemes
Writerdigest

Interface

Inputs
windowstring
How far back to gather feedback, e.g. '30d'.
Outputs
digeststring
The ranked themes and the issues filed, as posted to the product channel.

Depends on · 3 MCP servers

io.github.supabase/postgres-mcpnot in the registry yetdb
io.github.github/github-mcpnot in the registry yetcode
io.github.slack/slack-mcpnot in the registry yetchat
⤓ Export runnable code
# Generated by @socketcat/compiler for target: langgraph
# blueprint: com.socketcat/feedback-synthesizer 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):
    window: object
    digest: object
    tickets: object
    threads: object
    themes: object

def node_Fork_0(state):
    return {}

def node_Join_1(state):
    return {}

def node_AgentInvoke_2(state):
    return _rt.run_agent("ticketsAgent", state, {"window":"window"}, "tickets")

def node_AgentInvoke_3(state):
    return _rt.run_agent("threadsAgent", state, {"window":"window"}, "threads")

def node_AgentInvoke_4(state):
    return _rt.run_agent("synthesizer", state, {"threads":"threads","tickets":"tickets"}, "themes")

def node_AgentInvoke_5(state):
    return _rt.run_agent("filer", state, {"themes":"themes"}, "themes")

def node_AgentInvoke_6(state):
    return _rt.run_agent("writer", state, {"themes":"themes"}, "digest")

def build():
    b = StateGraph(State)
    b.add_node("Fork_0", node_Fork_0)
    b.add_node("Join_1", node_Join_1)
    b.add_node("AgentInvoke_2", node_AgentInvoke_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_node("AgentInvoke_6", node_AgentInvoke_6)
    b.add_edge(START, "Fork_0")
    b.add_edge("Fork_0", "AgentInvoke_2")
    b.add_edge("Fork_0", "AgentInvoke_3")
    b.add_edge("Join_1", "AgentInvoke_4")
    b.add_edge("AgentInvoke_2", "Join_1")
    b.add_edge("AgentInvoke_3", "Join_1")
    b.add_edge("AgentInvoke_4", "AgentInvoke_5")
    b.add_edge("AgentInvoke_5", "AgentInvoke_6")
    b.add_edge("AgentInvoke_6", END)
    return b.compile()

INPUTS = ["window"]
OUTPUTS = ["digest"]

if __name__ == "__main__":
    _rt.main(build, INPUTS, OUTPUTS)
blueprint.json (the portable format)
{
  "id": "com.socketcat/feedback-synthesizer",
  "flow": {
    "type": "sequence",
    "blocks": [
      {
        "type": "parallel",
        "blocks": [
          {
            "in": {
              "window": "window"
            },
            "out": "tickets",
            "use": "ticketsAgent",
            "type": "agent"
          },
          {
            "in": {
              "window": "window"
            },
            "out": "threads",
            "use": "threadsAgent",
            "type": "agent"
          }
        ]
      },
      {
        "in": {
          "threads": "threads",
          "tickets": "tickets"
        },
        "out": "themes",
        "use": "synthesizer",
        "type": "agent"
      },
      {
        "in": {
          "themes": "themes"
        },
        "out": "themes",
        "use": "filer",
        "type": "agent"
      },
      {
        "in": {
          "themes": "themes"
        },
        "out": "digest",
        "use": "writer",
        "type": "agent"
      }
    ]
  },
  "tags": [
    "product",
    "voice-of-customer",
    "orchestrator-workers",
    "github"
  ],
  "title": "Feedback Synthesizer",
  "agents": {
    "filer": {
      "model": {
        "hint": "fast"
      },
      "title": "Filer",
      "tools": [
        "code.create_issue"
      ],
      "instructions": "For the top themes, file a well-formed feature issue each: the problem in the user's words, the evidence, and the count. Before filing, check open issues and skip or link any duplicate rather than creating a second one."
    },
    "writer": {
      "model": {
        "hint": "fast"
      },
      "title": "Writer",
      "tools": [
        "chat.post_message"
      ],
      "instructions": "Post a digest to the product channel: the ranked themes with their counts and the issues filed or linked. Keep it skimmable."
    },
    "synthesizer": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Synthesizer",
      "instructions": "Cluster the combined feedback into distinct themes. For each theme give a clear name, two or three representative real quotes, and how many items it covers. Rank by weight. Do not merge unrelated asks to inflate a count."
    },
    "threadsAgent": {
      "model": {
        "hint": "fast"
      },
      "title": "Threads",
      "tools": [
        "code.list_issues"
      ],
      "instructions": "List recent GitHub issues and discussions in the window that carry user feedback or requests. Return each with its title, a representative quote, and its reaction count."
    },
    "ticketsAgent": {
      "model": {
        "hint": "fast"
      },
      "title": "Tickets",
      "tools": [
        "db.query_dsl"
      ],
      "instructions": "Query the warehouse for support tickets and product reviews in the window. Return each with its text, source, and date. Read-only."
    }
  },
  "estate": {
    "themes": {
      "type": "array",
      "description": "The synthesizer's clustered themes with quotes and counts."
    },
    "threads": {
      "type": "array",
      "description": "Recent issue and discussion threads from GitHub."
    },
    "tickets": {
      "type": "array",
      "description": "Support tickets and reviews from the warehouse."
    }
  },
  "$schema": "socketcat.dev/blueprint/v0",
  "authors": [
    {
      "url": "https://socketcat.com",
      "name": "SocketCat"
    }
  ],
  "license": "MIT",
  "servers": [
    {
      "ref": "io.github.supabase/postgres-mcp",
      "alias": "db"
    },
    {
      "ref": "io.github.github/github-mcp",
      "alias": "code"
    },
    {
      "ref": "io.github.slack/slack-mcp",
      "alias": "chat"
    }
  ],
  "summary": "Aggregates scattered user feedback, clusters it into quote-backed themes, and files the top requests as deduped issues.",
  "targets": [
    "langgraph",
    "*"
  ],
  "version": "1.0.0",
  "interface": {
    "inputs": {
      "window": {
        "type": "string",
        "description": "How far back to gather feedback, e.g. '30d'."
      }
    },
    "outputs": {
      "digest": {
        "type": "string",
        "description": "The ranked themes and the issues filed, as posted to the product channel."
      }
    }
  },
  "extensions": {
    "dev.langgraph": {
      "checkpointer": "memory"
    }
  },
  "description": "Two collectors run in parallel: one pulls support tickets and product reviews from the warehouse, the other reads recent issue and discussion threads from GitHub. A synthesizer clusters the combined feedback into themes, each backed by representative quotes and a count so the weight of each is clear. A filer turns the highest-signal themes into well-formed feature issues, deduping against what is already open. A writer posts a digest to the product channel so the team sees the ranked voice of the customer. Point the collectors at your own stores."
}

More in Support & success

Browse all →

Support Triage

com.socketcat/support-triage
CrewAI

Classifies tickets, drafts replies, escalates edge cases with rationale.

4551 server
51

AI Mental Wellbeing Team

io.github.shubhamsaboo/ai-mental-wellbeing-agent
Autogen

An AG2 team offering structured wellbeing support: assessment, action, and follow-up roles — a support-app pattern, not a clinician.

50000
community ↗

AgentChat Swarm

io.github.microsoft/agentchat-swarm
Autogen

A flight-refund team using handoff-based swarm coordination, including a handoff to the human user when the agents need input.

50000
community ↗