Skip to content

Feature: Multi-event triggers for a single route (OR logic for when filters) #130

@warren-t-c

Description

@warren-t-c

Problem

When building state-transition pipelines that use GitHub labels, a common pattern is:

  1. Route fires on issues.labeled with a specific payload.label.name
  2. Agent processes the issue, adds the next label
  3. Next route fires, and so on

However, when an issue is created with labels already attached (e.g. via gh issue create --label analyzed), GitHub fires issues.opened but may not reliably fire issues.labeled. This means the pipeline misses the event.

To cover both cases, you currently need to duplicate the entire route definition — one for issues.labeled and one for issues.opened — with the only difference being the filter criteria.

Current workaround: full route duplication

# Primary route — fires on label addition
- name: estimation
  description: "Issue labeled analyzed — run estimation"
  when:
    source: github
    events:
      - resource.changed
    filter:
      provenance.platform_event: issues.labeled
      payload.label.name: "analyzed"
  transforms:
    - ref: enrich
    - ref: dedup
  then:
    actor: my-agent
    config:
      session_key: "estimation:{{payload.issue.number}}"
  with:
    prompt_file: estimation.md

# Companion route — same logic, different trigger
- name: estimation-on-open
  description: "Issue opened with analyzed label — run estimation"
  when:
    source: github
    events:
      - resource.changed
    filter:
      provenance.platform_event: issues.opened
  transforms:
    - ref: enrich
    - ref: has-label-analyzed   # custom transform to check array
    - ref: dedup
  then:
    actor: my-agent
    config:
      session_key: "estimation:{{payload.issue.number}}"
  with:
    prompt_file: estimation.md

This duplication scales poorly. A pipeline with 5 label transitions needs 10 routes instead of 5, plus a custom transform per label to check payload.issue.labels[] (since the filter system only supports dot-path equality, not array matching).

Proposed solution

Allow when.filter to accept multiple filter conditions with OR semantics, or allow provenance.platform_event to accept an array of values.

Option A: Array of filter blocks (OR logic)

- name: estimation
  when:
    source: github
    events:
      - resource.changed
    filter:
      - provenance.platform_event: issues.labeled
        payload.label.name: "analyzed"
      - provenance.platform_event: issues.opened
        payload.issue.labels[].name: "analyzed"
  transforms:
    - ref: enrich
    - ref: dedup
  then:
    actor: my-agent
    config:
      session_key: "estimation:{{payload.issue.number}}"
  with:
    prompt_file: estimation.md

Option B: Multi-value platform event matching

- name: estimation
  when:
    source: github
    events:
      - resource.changed
    filter:
      provenance.platform_event:
        - issues.labeled
        - issues.opened
      payload.label.name: "analyzed"   # matches for labeled events
  # ... with some mechanism to also check payload.issue.labels for opened events

Option A is more general and composable. Option B is simpler but less flexible.

Additional context

  • This is a general pattern that affects any state-transition pipeline using labels (or similar resources where the attribute can be set at creation time vs. added later)
  • The same pattern applies to other platforms beyond GitHub — any webhook provider where a resource can be created with properties already set
  • Array matching in filters (payload.issue.labels[].name) would also help, but multi-event triggers solve the broader duplication problem
  • The current router does strict dot-path equality in matchesFilter, which makes array-of-objects fields unmatchable without custom transforms

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions