Docs Drift Sync CrewAI
What it does
A detector reads a merged change and greps the docs tree for anything it made false: renamed flags, changed defaults, removed endpoints, moved config. A writer drafts the smallest edits that make the docs accurate again, matching the surrounding voice and leaving unrelated prose alone. A reviewer checks each edit against the real code, then opens a documentation pull request and links it in Slack. Classic sequential crew, one clean pass.
The cast · 3 agents
For each stale passage, draft the smallest edit that makes it accurate. Match the surrounding tone and formatting. Do not rewrite whole sections or touch prose that is still correct.
Read the change diff. Identify the public-facing surface it altered: flag names, defaults, endpoints, config keys, return shapes. Grep the docs tree for passages that describe those and are now wrong. Return each with its file and line. If nothing is stale, say so and stop.
Check every edit against the actual code to confirm it is now correct and complete. Open a documentation pull request with the edits and a short summary, and link it in the docs channel. Flag anything you could not verify for a human.
Flow
Interface
Depends on · 3 MCP servers
io.github.github/github-mcpnot in the registry yetcode
io.github.modelcontextprotocol/filesystemnot in the registry yetfs
io.github.slack/slack-mcpnot in the registry yetchat# Generated by @socketcat/compiler for target: langgraph
# blueprint: com.socketcat/docs-drift-sync 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):
changeRef: object
pr: object
stale: object
edits: object
def node_AgentInvoke_0(state):
return _rt.run_agent("detector", state, {"changeRef":"changeRef"}, "stale")
def node_AgentInvoke_1(state):
return _rt.run_agent("writer", state, {"stale":"stale"}, "edits")
def node_AgentInvoke_2(state):
return _rt.run_agent("reviewer", state, {"edits":"edits"}, "pr")
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 = ["changeRef"]
OUTPUTS = ["pr"]
if __name__ == "__main__":
_rt.main(build, INPUTS, OUTPUTS)
▸blueprint.json (the portable format)
{
"id": "com.socketcat/docs-drift-sync",
"flow": {
"type": "sequence",
"blocks": [
{
"in": {
"changeRef": "changeRef"
},
"out": "stale",
"use": "detector",
"type": "agent"
},
{
"in": {
"stale": "stale"
},
"out": "edits",
"use": "writer",
"type": "agent"
},
{
"in": {
"edits": "edits"
},
"out": "pr",
"use": "reviewer",
"type": "agent"
}
]
},
"tags": [
"documentation",
"devrel",
"sequential",
"github"
],
"title": "Docs Drift Sync",
"agents": {
"writer": {
"model": {
"hint": "coding"
},
"title": "Writer",
"tools": [
"fs.write_file"
],
"instructions": "For each stale passage, draft the smallest edit that makes it accurate. Match the surrounding tone and formatting. Do not rewrite whole sections or touch prose that is still correct."
},
"detector": {
"model": {
"hint": "reasoning"
},
"title": "Detector",
"tools": [
"code.get_diff",
"fs.grep"
],
"instructions": "Read the change diff. Identify the public-facing surface it altered: flag names, defaults, endpoints, config keys, return shapes. Grep the docs tree for passages that describe those and are now wrong. Return each with its file and line. If nothing is stale, say so and stop."
},
"reviewer": {
"model": {
"hint": "reasoning"
},
"title": "Reviewer",
"tools": [
"code.open_pr",
"chat.post_message"
],
"instructions": "Check every edit against the actual code to confirm it is now correct and complete. Open a documentation pull request with the edits and a short summary, and link it in the docs channel. Flag anything you could not verify for a human."
}
},
"estate": {
"edits": {
"type": "object",
"description": "The writer's proposed documentation edits."
},
"stale": {
"type": "array",
"description": "The doc passages the change made inaccurate, with file and line."
}
},
"$schema": "socketcat.dev/blueprint/v0",
"authors": [
{
"url": "https://socketcat.com",
"name": "SocketCat"
}
],
"license": "MIT",
"servers": [
{
"ref": "io.github.github/github-mcp",
"alias": "code"
},
{
"ref": "io.github.modelcontextprotocol/filesystem",
"alias": "fs"
},
{
"ref": "io.github.slack/slack-mcp",
"alias": "chat"
}
],
"summary": "Turns a merged code change into the documentation edits it made necessary, then opens a reviewed docs PR.",
"targets": [
"crewai",
"langgraph",
"*"
],
"version": "1.0.0",
"interface": {
"inputs": {
"changeRef": {
"type": "string",
"description": "The merged change to check docs against, as a commit SHA or PR reference."
}
},
"outputs": {
"pr": {
"type": "string",
"description": "The documentation pull request that was opened, with the list of edits."
}
}
},
"extensions": {
"com.crewai": {
"process": "sequential"
}
},
"description": "A detector reads a merged change and greps the docs tree for anything it made false: renamed flags, changed defaults, removed endpoints, moved config. A writer drafts the smallest edits that make the docs accurate again, matching the surrounding voice and leaving unrelated prose alone. A reviewer checks each edit against the real code, then opens a documentation pull request and links it in Slack. Classic sequential crew, one clean pass."
}