Standup Digest CrewAI
What it does
A scheduled crew. A collector pulls the issues that moved in the tracker and the pull requests merged in GitHub over the last day. A summarizer groups the activity by person or workstream and condenses it to what's worth saying. A poster drops the digest in the team channel before standup, so the meeting is about blockers, not status. Swap the tracker for your own and run it on a morning schedule.
The cast · 3 agents
Post the digest to the team channel as one message with a clear heading for the day. No commentary of your own.
Pull the issues that changed state in the tracker and the pull requests merged in GitHub within the window. Return each with who did it and a one-line what. Read-only.
Group the activity by person or workstream and condense it to what's worth reporting. Drop noise like dependency bumps and formatting. Keep it scannable.
Flow
Interface
Depends on · 3 MCP servers
Linearapp.linear/lineartrackerBPublisher
io.github.github/github-mcpnot in the registry yetcode
io.github.slack/slack-mcpnot in the registry yetchat# Generated by @socketcat/compiler for target: langgraph
# blueprint: com.socketcat/standup-digest 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
activity: object
grouped: object
def node_AgentInvoke_0(state):
return _rt.run_agent("collector", state, {"window":"window"}, "activity")
def node_AgentInvoke_1(state):
return _rt.run_agent("summarizer", state, {"activity":"activity"}, "grouped")
def node_AgentInvoke_2(state):
return _rt.run_agent("poster", state, {"grouped":"grouped"}, "digest")
def build():
b = StateGraph(State)
b.add_node("AgentInvoke_0", node_AgentInvoke_0)
b.add_node("AgentInvoke_1", node_AgentInvoke_1)
b.add_node("AgentInvoke_2", node_AgentInvoke_2)
b.add_edge(START, "AgentInvoke_0")
b.add_edge("AgentInvoke_0", "AgentInvoke_1")
b.add_edge("AgentInvoke_1", "AgentInvoke_2")
b.add_edge("AgentInvoke_2", END)
return b.compile()
INPUTS = ["window"]
OUTPUTS = ["digest"]
if __name__ == "__main__":
_rt.main(build, INPUTS, OUTPUTS)
▸blueprint.json (the portable format)
{
"id": "com.socketcat/standup-digest",
"flow": {
"type": "sequence",
"blocks": [
{
"in": {
"window": "window"
},
"out": "activity",
"use": "collector",
"type": "agent"
},
{
"in": {
"activity": "activity"
},
"out": "grouped",
"use": "summarizer",
"type": "agent"
},
{
"in": {
"grouped": "grouped"
},
"out": "digest",
"use": "poster",
"type": "agent"
}
]
},
"tags": [
"team",
"scheduled",
"reporting",
"sequential"
],
"title": "Standup Digest",
"agents": {
"poster": {
"model": {
"hint": "fast"
},
"title": "Poster",
"tools": [
"chat.post_message"
],
"instructions": "Post the digest to the team channel as one message with a clear heading for the day. No commentary of your own."
},
"collector": {
"model": {
"hint": "fast"
},
"title": "Collector",
"tools": [
"tracker.list_issues",
"code.list_commits"
],
"instructions": "Pull the issues that changed state in the tracker and the pull requests merged in GitHub within the window. Return each with who did it and a one-line what. Read-only."
},
"summarizer": {
"model": {
"hint": "reasoning"
},
"title": "Summarizer",
"instructions": "Group the activity by person or workstream and condense it to what's worth reporting. Drop noise like dependency bumps and formatting. Keep it scannable."
}
},
"estate": {
"grouped": {
"type": "object",
"description": "The activity grouped and condensed by person or workstream."
},
"activity": {
"type": "array",
"description": "The raw tracker and GitHub activity in the window."
}
},
"$schema": "socketcat.dev/blueprint/v0",
"authors": [
{
"url": "https://socketcat.com",
"name": "SocketCat"
}
],
"license": "MIT",
"servers": [
{
"ref": "app.linear/linear",
"alias": "tracker"
},
{
"ref": "io.github.github/github-mcp",
"alias": "code"
},
{
"ref": "io.github.slack/slack-mcp",
"alias": "chat"
}
],
"summary": "Pulls yesterday's tracker and GitHub activity each morning, groups it by person, and posts a standup digest to Slack.",
"targets": [
"crewai",
"langgraph",
"*"
],
"version": "1.0.0",
"interface": {
"inputs": {
"window": {
"type": "string",
"description": "How far back to look, e.g. 'since yesterday 9am'."
}
},
"outputs": {
"digest": {
"type": "string",
"description": "The standup digest, as posted to Slack."
}
}
},
"extensions": {
"com.crewai": {
"process": "sequential"
}
},
"description": "A scheduled crew. A collector pulls the issues that moved in the tracker and the pull requests merged in GitHub over the last day. A summarizer groups the activity by person or workstream and condenses it to what's worth saying. A poster drops the digest in the team channel before standup, so the meeting is about blockers, not status. Swap the tracker for your own and run it on a morning schedule."
}More in Productivity & HR
Browse all →Inbox Chief of Staff
Triages your inbox, then routes each thread to the right handler — draft a reply, propose meeting times, or file it — with your approval before anything sends.