RFC: Agent-First Event Filtering

Summary

AgentInbox should move from today's flat matchRules map to an agent-first filtering model with:

The goal is not human-friendly syntax. The goal is to let agents write correct filters without memorizing a project- specific DSL.

Problem

Current Subscription.matchRules is too weak and too ambiguous.

Today it has these limitations:

This creates two problems:

  1. agents cannot easily express common filtering needs such as:
    • only completed workflow runs
    • completed failures only
    • filter out self-authored GitHub comments
    • match nested payload paths such as payload.sender.login
  2. agents cannot easily tell whether a field is:
    • a stable AgentInbox normalized field
    • or a source-native payload field

Goals

Non-Goals

Event Model

Every normalized event should continue to have:

Filtering should treat these as separate namespaces.

metadata

metadata is the stable, normalized, source-type-specific contract.

Examples for github_repo_ci:

Rules:

payload

payload is the source-native event body.

Examples:

Rules:

Proposed Subscription Filter Shape

Replace the current flat matchRules map with:

{
  "metadata": {
    "status": "completed",
    "conclusion": "failure"
  },
  "payload": {
    "event": "pull_request"
  },
  "expr": "metadata.status == 'completed' && metadata.conclusion == 'failure'"
}

Interpretation:

This keeps the simple path simple while giving agents an escape hatch for more complex logic.

Expression Language

Use a JS-like boolean expression syntax implemented via JEXL.

Why JEXL:

Expression Context

The filter expression should only receive these variables:

Example:

metadata.status == "completed" &&
metadata.conclusion == "failure" &&
payload.sender.login != "jolestar"

Allowed Operators

Allow the normal boolean and comparison operators supported by JEXL:

Also allow dotted path access such as:

Helper Functions

The helper-function set should be intentionally small.

The baseline should be inspired by GitHub Actions expression helpers and GitHub workflow filter patterns.

Functions To Support

Rationale

GitHub Actions already established a familiar mental model for:

AgentInbox should follow that familiarity where possible.

Two additions are worth making:

exists is useful for sparse source-native payloads.

Example Filters

Only completed GitHub CI failures:

metadata.status == "completed" &&
metadata.conclusion == "failure"

Filter out self-authored GitHub comments:

payload.sender.login != "jolestar"

Only CI workflows on release branches:

metadata.status == "completed" &&
glob(metadata.headBranch, "release/*")

Match workflow names using a GitHub-style helper:

contains(["CI", "Copilot Code Review"], metadata.name) &&
metadata.status == "completed"

Match nested payload content:

contains(payload.head_commit.message, "[notify-agent]")

Evaluation Rules

Filter evaluation should run in this order:

  1. exact match against metadata block, if present
  2. exact match against payload block, if present
  3. evaluate expr, if present

All present parts must pass for the event to match.

This keeps the common case cheap and deterministic.

Source Schema

This RFC assumes a future source schema command such as:

agentinbox source schema github_repo_ci

Expected output should be split explicitly:

This is important because the filter model only stays clear if agents can ask:

Security And Runtime Constraints

The expression engine must remain sandboxed.

Rules:

The context should be pure event data and helper functions only.

Migration

Compatibility is not a goal for this RFC.

Migration plan:

  1. replace flat matchRules with a structured filter object
  2. implement namespaced shortcut blocks:
    • metadata
    • payload
  3. add expr powered by JEXL
  4. add source schema
  5. update source adapters to make metadata contracts explicit

Open Questions

Recommendation

Adopt the following as the next filtering model:

This gives agents a filtering language they are already good at producing, while keeping AgentInbox's normalized metadata model explicit and stable.