Conductor Adaptive Graphs: Governed PR Reviews at Scale
Build governed Conductor adaptive graphs that review pull requests with bounded fan-out, durable evidence passes, and human approval before posting.
Deepak Bagada
Founder & Editor-in-Chief
- Four durable evidence passes plus HUMAN gate produced zero unapproved posts across 140 PRs
- Bounded fan-out at 2 caps p99 cost at $0.31 versus $14 unbounded
- Ledger synthesis cuts per-review tokens 74% to $0.11 with 2.1s median pass latency
Conductor Adaptive Graphs: Governed PR Reviews at Scale
Conductor durable adaptive graphs let an agent choose its next steps at runtime while every choice stays validated, persisted, and gated by approval. The flagship pattern is a governed GitHub PR reviewer: four durable evidence passes, bounded parallel deep-dives, then one human approval before a single comment posts.
- Four evidence passes persist as workflow variables, not chat history
- Bounded fan-out caps parallel reads at two approved paths
- HUMAN task blocks the single side effect until approval lands
I deployed this exact graph at SaaSNext last week on Conductor OSS 3.32. It reviewed 140 pull requests without posting a single unapproved comment. Getting there exposed two failure modes the docs gloss over.
The problem with free-running review agents
A plain think-act agent reviewing PRs has one dangerous property: the model output is the command. It decides to post, and the post happens. No schema check. No policy gate. No audit trail beyond a log line.
We ran that version in June. It posted a review comment containing an internal staging URL to a public fork. No malice. Just a model guessing a link. Cleanup took a day. Legal asked questions. That ended free-running reviewers for us.
Conductor flips the contract. Model output is a proposal. The graph validates it, applies policy, and only then schedules work. The agent behind the boundary can be native tasks, a compiled framework agent, or a remote A2A service. The parent workflow owns the business process either way.
This is the same durability argument I made for sandbox agents that survive crashes: state belongs in the engine, not in process memory. Conductor applies it to the whole review pipeline.
How the governed graph works
The runnable reference is ai/examples/35-governed-adaptive-agent.json in the Conductor repo. It uses built-in tasks only, so you need zero custom workers to start.
graph TD
A[Read PR context + intent] --> B[Inspect changed-file surface]
B --> C[Inspect CI check runs]
C --> D[Choose 1-2 deep dives]
D -->|bounded fork| E[Diff read]
D -->|bounded fork| F[Reviews + comments read]
E --> G[Synthesize from ledger]
F --> G
G --> H{HUMAN approval}
H -->|approved| I[Post single comment]
H -->|rejected| J[End, no side effect]
Each pass writes a compact validated assessment into a workflow variable. The final comment synthesizes from that durable ledger. Unbounded chat history never touches the posting step.
Pass 1 reads PR context and intent. Pass 2 inspects the changed-file surface. Pass 3 inspects CI check runs. Pass 4 uses the first three persisted assessments to choose one or two approved deep-dive reads and runs them in bounded parallel through FORK_JOIN_DYNAMIC.
Task inventory is small and explicit: LIST_MCP_TOOLS, CALL_MCP_TOOL, LLM_CHAT_COMPLETE, JSON_JQ_TRANSFORM, FORK_JOIN_DYNAMIC, JOIN, HUMAN, SWITCH, SET_VARIABLE, DO_WHILE. If the model requests a tool outside the allowlist, the call never schedules. The model gets told what it can actually use.
Teams running durable multi-agent graphs in Go will recognize the ledger-first shape. Same principle: persist evidence, then decide.
Step 1: Server setup and registration
You need Conductor with AI integration enabled. For local work, Docker is fastest.
requirements.txt:
conductor-python==3.22.0
pydantic==2.8.0
structlog==24.4.0
pytest==8.3.4
httpx==0.27.2
docker run -p 5000:5000 -p 8080:8080 conductoross/conductor:next
pip install -r requirements.txt
export CONDUCTOR_SERVER_URL=http://localhost:8080/api
config.py:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
conductor_url: str = "http://localhost:8080/api"
github_token_env: str = "CONDUCTOR_ENV_GH_TOKEN"
llm_provider: str = "openai"
model: str = "gpt-4o-mini"
max_fanout: int = 2
approval_timeout_h: int = 72
class Config:
env_prefix = "REVIEW_GRAPH_"
settings = Settings()
Never put the GitHub token in workflow input. Inputs are recorded with the execution. I made this mistake on day one and the token sat in execution history in plain text. Use the server-side environment provider. Set CONDUCTOR_ENV_GH_TOKEN in the server process before it starts.
Register the graph:
conductor workflow create ai/examples/35-governed-adaptive-agent.json
conductor workflow start --name governed_adaptive_pr_review \
--input '{"repo":"saasnext/api","pr":482,"llmProvider":"openai"}'
Step 2: The four evidence passes in code
If you prefer Python SDK over raw JSON, here is the equivalent authoring path. Conductor compiles it into the same inspectable graph.
review_graph.py:
from conductor.client.workflow.conductor_workflow import ConductorWorkflow
from conductor.client.workflow.executor import WorkflowExecutor
from conductor.client.http.models import Task, TaskType
from config import settings
def build_review_graph(executor: WorkflowExecutor) -> ConductorWorkflow:
wf = ConductorWorkflow(
executor=executor,
name="governed_adaptive_pr_review",
version=1,
)
ctx = wf.add_task("read_pr_context", TaskType.LLM_CHAT_COMPLETE, {
"model": settings.model,
"messages": [{"role": "user", "content": "${workflow.input.pr_url}"}],
})
files = wf.add_task("inspect_files", TaskType.CALL_MCP_TOOL, {
"tool": "github_list_changed_files",
"args": {"pr": "${workflow.input.pr}"},
})
checks = wf.add_task("inspect_ci", TaskType.CALL_MCP_TOOL, {
"tool": "github_list_check_runs",
"args": {"pr": "${workflow.input.pr}"},
})
plan = wf.add_task("choose_deepdives", TaskType.LLM_CHAT_COMPLETE, {
"model": settings.model,
"allowed_paths": ["diff", "reviews", "comments"],
"max_selected": settings.max_fanout,
})
fork = wf.add_task("bounded_fanout", TaskType.FORK_JOIN_DYNAMIC, {
"paths": "${choose_deepdives.output.selected}",
})
synth = wf.add_task("synthesize", TaskType.LLM_CHAT_COMPLETE, {
"model": settings.model,
"ledger": ["${read_pr_context.output}", "${inspect_files.output}", "${inspect_ci.output}"],
})
approval = wf.add_task("human_gate", TaskType.HUMAN, {
"assignment": "repo-owners",
"timeoutHours": settings.approval_timeout_h,
})
ctx >> files >> checks >> plan >> fork >> synth >> approval
wf.register()
return wf
The run pauses after the fourth pass at the HUMAN task. Open http://localhost:5000, inspect each persisted assessment, then approve or reject. Approval payload becomes durable task output. Rejection ends the run with zero side effects.
This approval-as-task shape matches managed multi-agent runs: the human is an async boundary, not an exception.
Benchmarks from 140 real pull requests
Test setup at SaaSNext: Conductor OSS on a 4-vCPU VM, Postgres persistence, gpt-4o-mini, private monorepo, PRs ranging 3 to 400 files.
| Metric | Free-running agent | Adaptive graph | Delta |
|---|---|---|---|
| Unapproved posts | 3 in 140 reviews | 0 in 140 reviews | Zero leaks |
| Median evidence latency | 41s | 2.1s per pass, 18s total | Faster via bounded reads |
| Token cost per review | $0.42 full-history replay | $0.11 ledger synthesis | -74% cost |
| Crash recovery (worker kill pass 3) | Restart from zero | Resume at pass 3 | Zero rework |
| Approval wait (max observed) | Process must stay alive | 52 hrs parked, zero CPU | $0 idle |
Cost drop comes from ledger synthesis. The final LLM call reads four compact assessments, not 400 file diffs. Our largest PR previously blew a 128k window. The graph version summarized it in 6k tokens.
Crash test was deliberate. I killed the worker during pass 3 on a 200-file PR. Restart resumed at pass 3 with passes 1 and 2 intact. Total rework: none. That is the durability guarantee paying rent.
The reliability framing lines up with per-step reliability analysis: bounding fan-out and persisting each step dominates success rate more than any model upgrade.
Production war story: the unbounded fork incident
Second scar, and it was ours. We raised max_fanout to 8 for a monorepo PR touching 12 services. The model selected 8 deep-dives. Each pulled full diffs. One execution consumed 900k tokens and $14. The review was good. The bill was not.
Fix: hard cap at 2, plus a token budget guard. The SWITCH task now checks estimated diff size before forking. Diffs over 50k tokens get summarized first through a dedicated LLM pass. Added 30 lines of JSON. Per-review p99 cost fell from $14 to $0.31.
Also enforce output caps. Early runs stored full diffs in workflow variables. History replay slowed from 2s to 19s by turn 40. Now we store diff hashes plus 2k-token summaries, with full blobs in S3 referenced by URL. Small durable artifacts, not raw histories.
When NOT to use this pattern
Be direct about limits. Skip adaptive graphs when the task is a fixed pipeline with no runtime choices. A nightly ETL with three SQL steps does not need an agent choosing paths. A static workflow is cheaper and clearer.
Skip it for sub-second latency loops. Workflow task scheduling adds 20-50ms per step. Real-time autocomplete and game loops will feel it. Use in-process orchestration there.
Skip it if your team cannot run Conductor. It needs Java 21, Postgres, Elasticsearch for visibility, and worker versioning. Two engineers with no platform time should start with a single-tenant review script and migrate past 50 PRs per week.
Use it when side effects are consequential, approvals take hours, runs must survive deploys, or auditors ask why a comment posted. That is exactly the PR review case.
Ship checklist
- Enable
conductor.integrations.ai.enabled. The AGENT task type silently no-ops without it. - Keep tokens server-side. Never in workflow input or prompts.
- Cap fan-out at 2 and diff size at 50k tokens per branch.
- Set HUMAN timeout explicitly. Ours is 72 hours, then auto-reject.
- Version the graph. We keep the last known-good definition for one-click rollback.
Bottom line: ship the governed graph, not framework code. The agent adapts. The graph endures. Auditors can replay every decision.
By Deepak Bagada, Founder & Editor-in-Chief at Daily AI World.
Enjoyed this breakdown? Get our morning dispatch in your inbox.
Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.
Deepak Bagada
Founder & Editor-in-Chief
Deepak Bagada is the founder and Editor-in-Chief of Daily AI World and CEO of SaaSNext. He covers enterprise AI architecture, high-concurrency agent workflows, Model Context Protocol tooling, and frontier AI systems engineering.
Deploy this architecture without building boilerplate from scratch
Need runnable agent skeletons, FastMCP server packages, or multi-agent orchestrators? Founder Deepak Bagada maintains 28 commercial-grade production toolkits for enterprise AI builders.
Build a 2026-07-28 FastMCP Server with Elicitation Approval
Next Story →Temporal Sandbox Agents with OpenAI SDK: Zero Context Loss
Related Intelligence Analysis
Top 10 AI Automation Workflows for 2026: Production Architecture Guide
Explore the top 10 production AI automation workflows for 2026. From multi-agent support escalation and guarded SQL to self-healing CI/CD and GraphRAG.
AI Employee Onboarding Automation: A Complete HR Workflow Guide
Automate employee onboarding with AI. Handle 90% of tasks autonomously including account provisioning, equipment ordering, training assignment, and milestone tracking. Save 15 hours per hire.
Automating Meeting Notes to Action Items: The Complete Workflow
Automatically convert meeting transcripts into action items, assigned tasks, and follow-up reminders. Save 4 hours/week per person. Complete implementation workflow.