Skip to content

Event-Driven Agent Routing

Event-driven agent routing reacts to status-change events — label additions, board transitions, PR changes — to advance work between handlers, with no central coordinator.

Overview

In an orchestrator-worker pipeline, a parent agent holds the full plan and dispatches each step explicitly. Event-driven routing inverts this: each step is a stateless handler triggered by a state transition. The handler fires, does its work, and emits the next state. No agent owns the full sequence.

GitHub's accessibility feedback pipeline is a documented production deployment of this pattern: each stage in a multi-team pipeline (AI intake → human review → service team resolution) is a GitHub Actions workflow triggered by label additions and project board status changes — not by a central coordinator calling each step in turn. Source

How It Works

GitHub Issues and Projects already provide the state machine primitives. Labels, project field values, and PR states are all observable events that Actions can subscribe to.

Trigger events:

Event Activity types Use for
issues labeled, unlabeled, opened, closed Route on label additions/removals
pull_request labeled, opened, review_requested, closed Route on PR state transitions
projects_v2_item edited (with changes payload) Route on project board status field changes

Source: GitHub Actions events docs

Handler design: Each workflow is stateless — it reads current issue/PR state, applies its logic, and writes the next state. Because state is stored in GitHub, re-running a handler is safe: re-adding a label re-fires it from a clean starting point.

Human-agent handoffs: Humans and agents are interchangeable at each stage. A human reviewer marks an issue as reviewed by applying a label; an agent responds identically. Neither side needs to know what comes next — sequencing lives in the trigger configuration.

Diagram

graph LR
    A[Issue created] -->|issues.opened| B[AI intake handler<br>enriches metadata]
    B -->|adds label: reviewed| C[Human review stage]
    C -->|adds label: validated| D[AI implementation handler]
    D -->|opens PR| E[PR review stage]
    E -->|PR merged| F[Closure handler<br>notifies submitter]

Each node is a separate, stateless GitHub Actions workflow. No node knows about the others.

Versus Orchestrator-Worker

Dimension Orchestrator-Worker Event-Driven Routing
Coordination Central agent holds full plan Distributed — each handler knows only its stage
Human handoff Explicit callback to orchestrator Human applies a label; event fires next handler
Re-run semantics Orchestrator must track progress Re-add label → handler re-runs from clean state
Ownership boundaries One owner (the orchestrator) Each team owns the handlers for their stage
Failure mode Orchestrator error stalls all stages Missing handler stalls silently

Google ADK and Anthropic's multi-agent research system use synchronous orchestrator-worker patterns. Anthropic notes that async event-driven execution would improve parallelism but "adds challenges in result coordination, state consistency, and error propagation." Source

Failure Modes

Silent stall: A state transition that fires no handler produces no error — the issue just stops advancing. Design for this explicitly:

  • Every status must have a designated handler
  • Add a fallback handler for issues.labeled that posts a comment when an unrecognized label is applied
  • Include status timestamps so delayed advancement is detectable in reports

Ambiguous ownership: If two teams both have handlers for the same label, both fire. Define exclusive ownership per label/status: each status has exactly one handler.

GitHub's implementation mitigates silent stalls with automated weekly reports and manual re-run capability — any Action can be re-triggered by re-applying the label. Source

Example

GitHub's accessibility pipeline uses issues: [opened, labeled] to route between three tiers. The AI intake workflow fires on issues.opened, calls the GitHub Models API with prompts stored in .github/copilot-instructions.md, populates ~80% of metadata (severity, WCAG mapping, affected groups), then applies the next label. Source A separate workflow fires when a human applies validated, routing to the service team.

# .github/workflows/ai-intake.yml
on:
  issues:
    types: [opened]

jobs:
  enrich:
    runs-on: ubuntu-latest
    steps:
      - name: Analyze with Copilot
        # calls GitHub Models API, applies labels based on response

Prompts live in .github/copilot-instructions.md and are modified via pull requests — no ML expertise needed to update AI behavior. Source

Key Takeaways

  • Use event-driven routing when team ownership boundaries map cleanly to status transitions — each team owns the handlers for their stage
  • Each handler must be stateless: read current state, do work, emit next state
  • Silent stalls are the primary failure mode — design observability (timestamps, fallback handlers) before deploying
  • Humans and agents are interchangeable handlers; the routing logic only sees the label, not who applied it
  • projects_v2_item webhook events are in public preview — test before building production pipelines on them

Sources

Feedback