Agent Execution Flow
Overview
flowchart TD
A[Issue labeled agent-ready] -->|GitHub webhook| B[rig-conductor]
B -->|Reads .rig-agent.yaml| C{Stack?}
C -->|ios + escalate| D[iBuild-E Mac Mini]
C -->|node| E[dev-e-node]
C -->|dotnet| F[dev-e-dotnet]
C -->|python| G[dev-e-python]
E & F & G -->|XADD stream + LPUSH signal| H[Valkey]
H -->|LLEN > 0| I[KEDA scales 0→1]
I -->|Pod starts ~25s| J[Stream Consumer]
J -->|Creates| K[Execution Log in Marten]
J -->|Refreshes| L[GitHub App Token]
J -->|Spawns| M[Claude CLI]
M -->|Step 1| N[Clone repo]
N -->|Step 2| O[Create feature branch]
O -->|Step 3| P[Read issue on GitHub]
P -->|Step 4| Q[Implement changes]
Q -->|Step 5| R[Run tests]
R -->|Step 6| S[Commit + Push]
S -->|Step 7| T[Create PR with Closes #N]
T -->|GitHub webhook PR opened| U[rig-conductor]
U -->|Records PR_CREATED| V[Event Store]
U -->|Records REVIEW_ASSIGNED| V
U -->|Routes to Review-E| W[Valkey stream]
W -->|KEDA wakes| X[Review-E]
X -->|Reviews diff| Y{Approved?}
Y -->|Yes| Z[Webhook: review_passed]
Y -->|No| AA[Webhook: changes_requested]
Z -->|Sets review-approved| AB[MergeGate Valkey hash]
T -->|CI runs| AC[GitHub Actions]
AC -->|check_run.completed| AD[Webhook: CI passed]
AD -->|Sets ci-passed| AB
AB -->|Flags set, or review + 30 s CI wait: attempt| AG{Guard re-reads GitHub:<br/>open, checks passed,<br/>Review-E APPROVED at head?}
AG -->|Yes| AE[Squash merge pinned to that head]
AG -->|No: defer| AB
AE -->|Records MERGED + ISSUE_DONE| V
AE -->|KEDA cooldown 5 min| AF[Scale 1→0]
AA -->|Routes back to Dev-E| J
style A fill:#4ade80
style AE fill:#38bdf8
style AF fill:#a78bfa
style AA fill:#f87171
Detailed Steps
1. Issue Assignment (rig-conductor)
GitHub webhook: issues.labeled (agent-ready)
→ rig-conductor receives webhook
→ Fetches .rig-agent.yaml from repo (1 GitHub API call)
→ Determines stack: node/dotnet/python/ios
→ If escalate contains "requires-macos" → route to iBuild-E
→ Otherwise → route to dev-e-{stack}
→ Records ISSUE_APPROVED + ISSUE_ASSIGNED events
→ XADD to assignments:{agent} stream
→ LPUSH to signal:{agent} list (KEDA wake signal)
2. Agent Wake-Up (KEDA)
KEDA polls signal:{agent} every 15s
→ LLEN > 0 → scales deployment 0→1
→ Pod starts (~25s for image pull + startup)
→ Node.js process starts
→ GitHub App token minted from PEM (valid 1 hour)
→ Git credentials configured
→ Discord bot connected
→ MCP servers started (GitHub, Advisor)
→ Stream consumer connects to Valkey
→ XREADGROUP starts consuming
3. Task Execution (Claude CLI)
Stream consumer receives assignment
→ Clears KEDA signal (DEL signal:{agent})
→ Creates execution log in rig-conductor
→ Refreshes GitHub App token (ensures fresh for this run)
→ Spawns Claude CLI with assertive prompt:
MANDATORY steps:
1. git clone https://github.com/{repo}.git
2. git checkout -b feature/issue-{N}-description
3. Read the issue for full context
4. Implement the changes
5. Run tests (from .rig-agent.yaml testCommand)
6. Commit with conventional commits
7. git push -u origin HEAD
8. gh pr create --title "..." --body "Closes #{N}"
CRITICAL: NOT done until PR is created.
→ CLI runs autonomously (up to 100 turns, 10 min timeout)
→ stderr captured and published to Valkey pub/sub (live logs)
→ On completion: cost, turns, tokens captured
4. PR Review (Review-E)
GitHub webhook: pull_request.opened
→ rig-conductor records PR_CREATED + REVIEW_ASSIGNED
→ Routes to Review-E: XADD + LPUSH
→ KEDA wakes Review-E (0→1)
→ Review-E reads PR diff
→ Approves or requests changes
→ Stream consumer calls POST /api/merge (a trigger: sets review-approved; not evidence)
If changes_requested:
→ rig-conductor routes back to Dev-E with feedback
→ Dev-E iterates on same branch, pushes fix
→ Review-E re-reviews
5. Merge (MergeGate)
MergeGate: Valkey hash per PR (merge-gate:{repo}#{pr}, 24 h TTL) with two TRIGGER flags:
- review-approved: set by the review webhook or POST /api/merge
(unauthenticated, and the runtime calls it on a text-matched
"approve", so the flag is never evidence)
- ci-passed: set by the check_run.completed webhook
An attempt runs when both flags are set, or on review-approved alone: at once
if main has no required checks, else after a 30 s wait for ci-passed.
Every attempt runs Merge()'s guard, which re-reads GitHub (rig-conductor#1028 + #2350):
→ the PR is still open else defer (pr_not_open)
→ every non-skip check_run on the head passed else defer, clear ci-passed
→ review-e-bot[bot]'s latest APPROVED / CHANGES_REQUESTED / DISMISSED
review is APPROVED at exactly that head else defer, clear review-approved
(COMMENTED is not a verdict; an unreadable or paginated list defers and
clears nothing)
A deferred PR waits for the next check_run or review webhook (no polling).
Then:
→ Re-read the PR (title + head): head moved since the guard → defer
→ Set merge dedup key in Valkey (1hr TTL; deleted again if the PUT fails)
→ Squash merge via API, pinned to the verified head (a later push makes
GitHub refuse the PUT: merge_put_failed)
→ Record MERGED; the issue goes done (in-deploy for Flux repos) once main
CI passes, or at once when the repo has no main CI
GitHub API calls per attempt that reaches the PUT: 5 (PR, check-runs, reviews,
PR, merge PUT); a guard defer stops after 3. After a merge: GET actions/runs on
main, and the sibling-PR close lists open PRs. No polling.
6. Scale Down
After assignment processed:
→ Stream consumer ACKs message
→ No more messages in stream
→ KEDA cooldown (5 min)
→ Scales deployment 1→0
→ Zero cost when idle
Error Handling
| Error |
Behavior |
| Invalid API key |
Detected from CLI output, waits 60s, retries fresh |
| Stale session |
Clears session from Valkey, retries without --resume |
| Git push failure |
CLI retries (instructed in prompt) |
| PR creation failure |
CLI retries (instructed in prompt) |
| CI failure |
check_run webhook routes back to agent with failure details |
| Review changes |
rig-conductor routes back to agent with review feedback |
| Duplicate webhook |
Delivery ID dedup in Valkey (1hr TTL) |
| Duplicate merge |
Merge dedup in Valkey (1hr TTL) |
GitHub API Budget
| Operation |
Calls |
When |
| Fetch .rig-agent.yaml |
1 |
Per issue assignment |
| PR details for review routing |
1 |
Per PR opened |
| Merge attempt |
5 (3 if the guard defers) |
Per attempt: PR, check-runs, reviews (the guard), PR, merge PUT |
| ReviewScanService |
18 |
Every 4 hours (fallback) |
| Total per issue |
~7 |
From assignment to one successful merge attempt |