Skip to content

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