← All blueprints

Incident Commander LangGraph

blueprint · 5 agents · 4 MCP servers
1180★ stars
164forks
4.8rating

What it does

Three investigators run in parallel the moment an alert lands: one reads the error's stack trace and frequency from Sentry, one pulls the relevant latency and error-rate series from Grafana, and one lists the recent commits that touched the failing path in GitHub. A commander synthesizes their reports into one hypothesis with a confidence level, and a scribe posts a formatted update to the on-call channel. Point the three servers at your own stack and the workflow is unchanged.

The cast · 5 agents

Scribescribefast

Post a short, scannable incident update to the on-call channel: what is failing, the leading hypothesis, the suspect change, and the confidence. No filler.

chat.post_message
Triagetriagefast

Read the Sentry issue named in the alert. Report the exception type, the top stack frame, when it was first seen, and how often it is firing now. Do not speculate about cause yet.

errors.get_issueerrors.list_events
Commandercommanderreasoning

Read the error, metric, and code reports. Write one root-cause hypothesis: what most likely broke, which change probably caused it, and how confident you are (low/medium/high). If the evidence conflicts, say so and pick the most likely explanation.

no tools · reasoning only
Historianhistorianfast

List the commits merged in the last 48 hours that touched the file or service in the stack trace. Report author, message, and time for each candidate.

code.list_commits
MetricsmetricsAgentfast

Pull the latency and error-rate series for the affected service around the alert time. Report what changed and when the change started, relative to the alert.

metrics.query_range

Flow

⇉ parallel
TriageerrorReport
MetricsmetricReport
HistoriancodeReport
Commanderhypothesis
Scribeupdate

Interface

Inputs
alertobject
The incoming alert: at least an error id or fingerprint and the service it fired on.
Outputs
updatestring
The incident update that was posted, including the root-cause hypothesis and its confidence.

Depends on · 4 MCP servers

Sentryio.github.getsentry/sentry-mcperrorsBVerified
io.github.grafana/grafana-mcpnot in the registry yetmetrics
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/incident-commander 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):
    alert: object
    update: object
    errorReport: object
    metricReport: object
    codeReport: object
    hypothesis: object

def node_Fork_0(state):
    return {}

def node_Join_1(state):
    return {}

def node_AgentInvoke_2(state):
    return _rt.run_agent("triage", state, {"alert":"alert"}, "errorReport")

def node_AgentInvoke_3(state):
    return _rt.run_agent("metricsAgent", state, {"alert":"alert"}, "metricReport")

def node_AgentInvoke_4(state):
    return _rt.run_agent("historian", state, {"alert":"alert"}, "codeReport")

def node_AgentInvoke_5(state):
    return _rt.run_agent("commander", state, {"codeReport":"codeReport","errorReport":"errorReport","metricReport":"metricReport"}, "hypothesis")

def node_AgentInvoke_6(state):
    return _rt.run_agent("scribe", state, {"hypothesis":"hypothesis"}, "update")

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("Fork_0", "AgentInvoke_4")
    b.add_edge("Join_1", "AgentInvoke_5")
    b.add_edge("AgentInvoke_2", "Join_1")
    b.add_edge("AgentInvoke_3", "Join_1")
    b.add_edge("AgentInvoke_4", "Join_1")
    b.add_edge("AgentInvoke_5", "AgentInvoke_6")
    b.add_edge("AgentInvoke_6", END)
    return b.compile()

INPUTS = ["alert"]
OUTPUTS = ["update"]

if __name__ == "__main__":
    _rt.main(build, INPUTS, OUTPUTS)
blueprint.json (the portable format)
{
  "id": "com.socketcat/incident-commander",
  "flow": {
    "type": "sequence",
    "blocks": [
      {
        "type": "parallel",
        "blocks": [
          {
            "in": {
              "alert": "alert"
            },
            "out": "errorReport",
            "use": "triage",
            "type": "agent"
          },
          {
            "in": {
              "alert": "alert"
            },
            "out": "metricReport",
            "use": "metricsAgent",
            "type": "agent"
          },
          {
            "in": {
              "alert": "alert"
            },
            "out": "codeReport",
            "use": "historian",
            "type": "agent"
          }
        ]
      },
      {
        "in": {
          "codeReport": "codeReport",
          "errorReport": "errorReport",
          "metricReport": "metricReport"
        },
        "out": "hypothesis",
        "use": "commander",
        "type": "agent"
      },
      {
        "in": {
          "hypothesis": "hypothesis"
        },
        "out": "update",
        "use": "scribe",
        "type": "agent"
      }
    ]
  },
  "tags": [
    "incident-response",
    "observability",
    "orchestrator-workers",
    "on-call"
  ],
  "title": "Incident Commander",
  "agents": {
    "scribe": {
      "model": {
        "hint": "fast"
      },
      "title": "Scribe",
      "tools": [
        "chat.post_message"
      ],
      "instructions": "Post a short, scannable incident update to the on-call channel: what is failing, the leading hypothesis, the suspect change, and the confidence. No filler."
    },
    "triage": {
      "model": {
        "hint": "fast"
      },
      "title": "Triage",
      "tools": [
        "errors.get_issue",
        "errors.list_events"
      ],
      "instructions": "Read the Sentry issue named in the alert. Report the exception type, the top stack frame, when it was first seen, and how often it is firing now. Do not speculate about cause yet."
    },
    "commander": {
      "model": {
        "hint": "reasoning"
      },
      "title": "Commander",
      "output": {
        "type": "object",
        "required": [
          "summary",
          "confidence"
        ],
        "properties": {
          "summary": {
            "type": "string"
          },
          "confidence": {
            "type": "string"
          },
          "suspectCommit": {
            "type": "string"
          }
        }
      },
      "instructions": "Read the error, metric, and code reports. Write one root-cause hypothesis: what most likely broke, which change probably caused it, and how confident you are (low/medium/high). If the evidence conflicts, say so and pick the most likely explanation."
    },
    "historian": {
      "model": {
        "hint": "fast"
      },
      "title": "Historian",
      "tools": [
        "code.list_commits"
      ],
      "instructions": "List the commits merged in the last 48 hours that touched the file or service in the stack trace. Report author, message, and time for each candidate."
    },
    "metricsAgent": {
      "model": {
        "hint": "fast"
      },
      "title": "Metrics",
      "tools": [
        "metrics.query_range"
      ],
      "instructions": "Pull the latency and error-rate series for the affected service around the alert time. Report what changed and when the change started, relative to the alert."
    }
  },
  "estate": {
    "codeReport": {
      "type": "object",
      "description": "The historian's list of recent commits touching the failing code."
    },
    "hypothesis": {
      "type": "object",
      "description": "The commander's root-cause hypothesis with a confidence level."
    },
    "errorReport": {
      "type": "object",
      "description": "The triage agent's summary of the Sentry issue: stack, first-seen, rate."
    },
    "metricReport": {
      "type": "object",
      "description": "The metrics agent's read of the relevant dashboards around the alert time."
    }
  },
  "$schema": "socketcat.dev/blueprint/v0",
  "authors": [
    {
      "url": "https://socketcat.com",
      "name": "SocketCat"
    }
  ],
  "license": "MIT",
  "servers": [
    {
      "ref": "io.github.getsentry/sentry-mcp",
      "alias": "errors"
    },
    {
      "ref": "io.github.grafana/grafana-mcp",
      "alias": "metrics"
    },
    {
      "ref": "io.github.github/github-mcp",
      "alias": "code"
    },
    {
      "ref": "io.github.slack/slack-mcp",
      "alias": "chat"
    }
  ],
  "summary": "Turns a single error alert into a root-cause hypothesis and a Slack incident update, gathering evidence from three sources at once.",
  "targets": [
    "langgraph",
    "*"
  ],
  "version": "1.0.0",
  "interface": {
    "inputs": {
      "alert": {
        "type": "object",
        "description": "The incoming alert: at least an error id or fingerprint and the service it fired on."
      }
    },
    "outputs": {
      "update": {
        "type": "string",
        "description": "The incident update that was posted, including the root-cause hypothesis and its confidence."
      }
    }
  },
  "extensions": {
    "dev.langgraph": {
      "checkpointer": "memory"
    }
  },
  "description": "Three investigators run in parallel the moment an alert lands: one reads the error's stack trace and frequency from Sentry, one pulls the relevant latency and error-rate series from Grafana, and one lists the recent commits that touched the failing path in GitHub. A commander synthesizes their reports into one hypothesis with a confidence level, and a scribe posts a formatted update to the on-call channel. Point the three servers at your own stack and the workflow is unchanged."
}