← 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
→ Tickets → tickets
→ Threads → threads
→ Synthesizer → themes
→ Filer → themes
→ Writer → digest

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 ↗