AI agents that help you manage and document your architecture with EventCatalog.
EventCatalog Agents understand EventCatalog conventions — services, events, commands, queries, domains, channels, containers, specifications, and more — and use that understanding to keep your architecture documented and safe to change. They are powered by Flue and guided by bundled Agent Skills.
Today the agents run in your CI/CD pipeline as a GitHub Action: each time you open a pull request, the agents you've enabled review the change and report back. CI is the first place we run them; it is a delivery surface, not the limit of what the agents are.
| Agent | What it does |
|---|---|
| Code-to-Docs | Keeps your EventCatalog documentation in sync with your code by proposing catalog updates on each PR. |
| Breaking Changes | Detects breaking schema changes in a PR and shows which catalog consumers could be affected. |
| ADR Compliance | Checks that the code in a PR follows the architecture decisions (ADRs) documented in your catalog. |
Each Action step runs one agent, selected with the agent input (default:
code-to-docs). To run more than one, add another step (or workflow file) with a different agent.
The Code-to-Docs agent keeps your EventCatalog documentation in sync with your code. When you open a pull request, it reviews the diff, works out which documentation should change, updates it in your catalog repository, and opens (or updates) a documentation pull request — then comments back on your source PR with a summary and a link.
flowchart LR
PR[Source pull request] --> Agent[Code-to-Docs agent]
Agent --> Plan{Docs need<br/>updating?}
Plan -- No --> Comment[Comment on source PR]
Plan -- Yes --> Docs[Update catalog docs]
Docs --> CatalogPR[Open catalog pull request]
CatalogPR --> Comment
When a pull request is opened, the Code-to-Docs agent:
- Checks out your catalog repository into
eventcatalog/. - Collects the changed source files from the pull request (ignoring noise like
node_modules, build output, etc.). - Plans the impact — a read-only pass where the agent decides whether the diff requires any documentation changes, and if so, exactly which catalog resources should change. If nothing is needed, the run stops here and says so.
- Applies the plan — the agent updates the catalog documentation, using the bundled EventCatalog skill for correct frontmatter and folder structure. It checks its changes with the EventCatalog linter (the version your catalog pins) and with your catalog's fitness functions, and fixes problems its changes caused. It is only allowed to touch the resources approved in the plan; edits outside that plan are rejected.
- Handles version bumps — when the agent bumps a message's version (for a breaking change), the
services and agents that pin the old version are approved for editing automatically, and the
previous version is archived to
versioned/<version>/so it stays documented. - Opens a catalog PR — commits the changes to an
eventcatalog-actions/...branch in your catalog repository and opens or updates a pull request againstcatalog-ref. Its description links the source PR, lists the resources that changed, and flags anything worth checking. - Comments on the source PR with the catalog PR link and a table of the catalog resources it added, updated, or removed. If it couldn't update the docs, the comment says why and what to do.
Deterministic work (diff parsing, path resolution, git writes, token preflight, change detection) stays in TypeScript. The agent is responsible only for reasoning about documentation.
The Breaking Changes agent watches your message schemas. When a pull request changes a schema, it decides whether the change is breaking for existing consumers and, if so, traces it through your EventCatalog to the resources that could be affected — then comments back on your source PR with the breaking lines highlighted and the affected consumers listed. It is read-only: it never edits your catalog.
flowchart LR
PR[Source pull request] --> Agent[Breaking Changes agent]
Agent --> Schema{Schema<br/>changed?}
Schema -- No --> Skip[Nothing to report]
Schema -- Yes --> Breaking{Breaking<br/>change?}
Breaking -- No --> Skip
Breaking -- Yes --> Consumers[Find catalog consumers]
Consumers --> Comment[Comment on source PR]
When a pull request is opened, the Breaking Changes agent:
- Checks out your catalog repository into
eventcatalog/. - Finds changed schema files in the pull request (
.json,.yml, Avro, Protobuf, GraphQL, and similar). If the PR touches no schemas, the run stops here. - Scores each schema change — a read-only pass that decides whether the change is breaking (a removed/renamed field, a type change, a new required field, a narrowed enum, and so on). Additive changes are not breaking and are skipped.
- Finds affected consumers — for each breaking change, the agent traces the schema to the resource it belongs to and finds the services and flows that consume it (the producer that sends the message is not counted).
- Comments on the source PR with each breaking change, its highlighted lines, and the consumers
that could be affected. If
catalog-urlis configured, affected consumers and owner teams link to your hosted catalog. If no consumers are found, it logs that and skips the comment.
The ADR Compliance agent checks that the code a pull request changes follows the Architecture Decision Records in your EventCatalog. You point it at the ADRs that apply to the repository, and it comments on the source PR only when the code clearly conflicts with one. It is read-only and advisory: it never edits your catalog or blocks a merge.
flowchart LR
PR[Source pull request] --> Select[Select accepted ADRs<br/>from the adrs input]
Select --> Triage{Any on the<br/>same topic?}
Triage -- No --> Skip[Nothing to report]
Triage -- Yes --> Review{Clear<br/>conflict?}
Review -- No --> Skip
Review -- Yes --> Verify[Verify the citations]
Verify --> Comment[Comment on source PR]
The adrs input is required. It takes comma-separated globs relative to your catalog root, so a
repository can check against org-wide decisions and those of its own domain. Add this step to the
workflow from Get started:
- uses: event-catalog/agents@v2
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
agent: adr-compliance
adrs: adrs/**, domains/Orders/**
catalog-repo: your-org/your-catalog
catalog-url: https://catalog.example.com
catalog-token: ${{ secrets.EVENTCATALOG_TOKEN }}| To check against | Use |
|---|---|
ADRs in the top-level adrs/ folder |
adrs/** |
| A domain, and everything nested in it | domains/Orders/** |
| One service | domains/Orders/services/OrdersAPI/** |
| ADRs that share a naming convention | adrs/adr-orders-*/** |
| One ADR | adrs/adr-012-use-outbox |
| Every ADR in the catalog, as a deliberate choice | '**/adrs/**' (YAML needs the quotes) |
Only accepted ADRs are checked, at their latest version. If an accepted ADR amends one you selected,
it is included too, because the decision can't be judged correctly without it. If adrs is missing or
matches nothing, the run fails with an error, so a typo can't look like a clean pass.
ADRs can live under any adrs folder in your catalog, so point the globs at wherever yours are. The
catalog-token only needs read access, because this agent never writes to the catalog.
- Selects the ADRs matching
adrsfrom your catalog. - Triages their summaries against the diff, so only ADRs on the same topic are reviewed in full.
- Reviews the changed lines against those ADRs, reporting only clear conflicts.
- Verifies each citation: the line must be one this pull request changed, and the quoted sentence must really be in the ADR. A conflict that fails this check is dropped.
- Comments on the source PR with each conflict, the sentence from the ADR, and a suggestion. The comment updates on every push, and says so once the conflicts are gone. A pull request with no conflicts gets no comment.
If a conflict is intentional, add a line with the ADR's id and your reason to the pull request description. The conflict is then listed as an exception in the comment, so reviewers can still see it:
adr-exception: adr-003-offload-async-work-to-worker image resize takes under 5ms
The agent reads the description when it runs, so push a commit or re-run the workflow after adding the
line. To re-run automatically when the description changes, add edited to the workflow's
pull_request types.
If the decision itself has changed, propose a new ADR in your catalog instead.
Run an agent on your repository in three steps.
1. Add your model provider key as a secret in your repository (Settings → Secrets and variables →
Actions). Use the one that matches your chosen model — e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY, or
OPENROUTER_API_KEY.
2. Add a workflow at .github/workflows/eventcatalog.yml:
on:
pull_request:
jobs:
eventcatalog:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: event-catalog/agents@v2
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
agent: code-to-docs # or: breaking-changes, adr-compliance
catalog-repo: your-org/your-catalog
catalog-url: https://catalog.example.com
catalog-token: ${{ secrets.EVENTCATALOG_TOKEN }}3. Open a pull request. The selected agent runs and reports back on your source PR.
fetch-depth: 0is required so the agent can diff the pull request against its base. See Inputs for all configuration options, and When to run to run Code-to-Docs only once a pull request merges (recommended).
Each Action step runs a single agent. To run more than one, add another step in the same job (or a
second workflow file):
- uses: event-catalog/agents@v2
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
agent: code-to-docs
catalog-repo: your-org/your-catalog
catalog-url: https://catalog.example.com
catalog-token: ${{ secrets.EVENTCATALOG_TOKEN }}
- uses: event-catalog/agents@v2
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
agent: breaking-changes
catalog-repo: your-org/your-catalog
catalog-url: https://catalog.example.com
catalog-token: ${{ secrets.EVENTCATALOG_TOKEN }}Agents can run while a pull request is open, or once it is merged. We recommend running Code-to-Docs when a pull request merges, and Breaking Changes and ADR Compliance while it is open:
| Agent | Recommended trigger | Why |
|---|---|---|
| Code-to-Docs | When merged (types: [closed]) |
Documents what actually shipped, runs once per pull request, and never documents abandoned work. |
| Breaking Changes | While open (opened, synchronize, …) |
Its job is to warn before a breaking change merges. Run after merging, the warning comes too late to act on before it ships. |
| ADR Compliance | While open (opened, synchronize, …) |
Its job is to raise a conflict while the code can still change. |
Running Code-to-Docs on open pull requests also works: the catalog pull request is ready for review alongside the code, and is updated on every push. It runs more often, though, and most updates to a pull request don't change the documentation.
# .github/workflows/eventcatalog.yml
on:
pull_request:
types: [opened, synchronize, reopened, closed]
jobs:
code-to-docs:
# Only once the pull request is merged.
if: github.event.action == 'closed' && github.event.pull_request.merged == true
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- uses: event-catalog/agents@v2
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
agent: code-to-docs
catalog-repo: your-org/your-catalog
catalog-token: ${{ secrets.EVENTCATALOG_TOKEN }}
breaking-changes:
# While the pull request is open.
if: github.event.action != 'closed'
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- uses: event-catalog/agents@v2
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
agent: breaking-changes
catalog-repo: your-org/your-catalog
catalog-token: ${{ secrets.EVENTCATALOG_TOKEN }}Use pull_request with types: [closed] rather than push to your main branch: the agents need the
pull request to diff against and to comment on. If a pull request is closed without merging, the
agents skip it without commenting.
| Input | Required | Default | Description |
|---|---|---|---|
agent |
No | code-to-docs |
Which agent to run: code-to-docs, breaking-changes, or adr-compliance. |
adrs |
For ADR Compliance | Comma-separated globs, relative to the catalog root, selecting the ADRs to check against. See Choosing which ADRs to check. | |
catalog-repo |
Yes | EventCatalog repository to read/document, in owner/repo format. |
|
catalog-ref |
No | main |
Branch checked out from the catalog repository and targeted by documentation PRs. |
catalog-token |
No | github.token |
Token used to check out the catalog repository and open documentation pull requests. Not needed with a GitHub App. |
github-app-client-id |
No | Client ID of a GitHub App installed on the catalog repository. With github-app-private-key, the agent uses the App instead of catalog-token. |
|
github-app-private-key |
No | Private key of that GitHub App. Pass it from a secret. | |
catalog-url |
No | URL of your hosted EventCatalog. When set, Breaking Changes and ADR Compliance comments link to catalog pages. | |
model |
No | anthropic/claude-sonnet-4-6 |
Model specifier for the agent. See available models. |
ignore-paths |
No | see action.yml | Comma-separated paths or glob patterns to ignore in PR diffs. |
schema-extensions |
No | see action.yml | Comma-separated file extensions the Breaking Changes agent treats as message schemas. Add others (e.g. .js) to match where your contracts live. |
The agents run on Flue, which supports models from many providers — see the full list of model specifiers at pi.dev/models.
Breaking Changes only looks at schema files. By default that means
.json,.yml,.yaml,.avro,.avsc,.proto,.graphql, and.gql. If your message contracts live in source files (for example amessages.js), add that extension viaschema-extensionsso the agent inspects it.
The model provider's API key is passed as a normal workflow environment variable. Set the one that
matches your model:
| Provider | Env var |
|---|---|
| Anthropic | ANTHROPIC_API_KEY |
| OpenAI | OPENAI_API_KEY |
| OpenRouter | OPENROUTER_API_KEY |
The catalog is always checked out to eventcatalog/ under $GITHUB_WORKSPACE. When your catalog
lives in a different repository from your source code, provide a catalog-token with permission
to read it — and, for Code-to-Docs, to push branches and open pull requests in it (the default
github.token only has access to the current repository).
Instead of a personal access token, you can give the agent a GitHub App. Catalog pull requests are then opened by the App's bot account rather than a person, and the agent gets a token that is scoped to the catalog repository and expires after an hour.
- Create a GitHub App in your organization with these repository permissions: Contents: Read and write and Pull requests: Read and write. It doesn't need a webhook.
- Generate a private key for the App, and install the App on your catalog repository.
- Add the App's Client ID and private key to your source repository's secrets, and pass them to the
action instead of
catalog-token:
- uses: event-catalog/agents@v2
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
agent: code-to-docs
catalog-repo: your-org/your-catalog
github-app-client-id: ${{ vars.EVENTCATALOG_APP_CLIENT_ID }}
github-app-private-key: ${{ secrets.EVENTCATALOG_APP_PRIVATE_KEY }}Fitness functions are architecture rules you write for your
catalog, in fitness/*.fitness.ts files (for example "every event has a single producer"). When your
catalog has them, the Code-to-Docs agent runs them after making its changes and fixes any problems its
changes introduced. Problems that were already in your catalog are left alone.
Fitness functions are code from your catalog repository, so the agent runs them in a separate process that does not receive your model provider key or GitHub tokens. The agent can never create or edit fitness functions: a run that tries is rejected as off-plan.
We recommend also running the linter, your fitness functions and a build in your catalog repository's own CI, so every pull request — the agent's included — is checked before it is merged:
# .github/workflows/catalog-checks.yml in your catalog repository
on: pull_request
jobs:
checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
- run: npm ci
- run: npx eventcatalog-linter
- run: npx eventcatalog fitness check
- run: npx eventcatalog buildThe action sends one anonymous event per run so we can see how the agents are used. It contains the
run's outcome (and, for a failed run, the kind of error, such as an invalid model provider key), the
model, the run's duration, whether it ran on an open or a merged pull request, the repository name,
and for Code-to-Docs, how many of the agent's catalog
pull requests are open, merged, or closed without merging. It never contains anything from your
repositories: no code, file names, paths, diffs, or pull request content. Set POSTHOG_KEY: "" in
the step's env to turn it off.
This project uses pnpm and requires Node.js >=22.19.0 (Flue's minimum; CI uses
Node 24).
pnpm install
# Build + typecheck + run the eval suite
pnpm test
# Run only the evals (see evals/README.md)
pnpm run evals
# Run an agent locally against a checked-out workspace (code-to-docs, breaking-changes, or adr-compliance)
pnpm exec tsx src/run.ts code-to-docs --payload '{"workspace":"/tmp/example"}'See AGENTS.md for the project layout and contributor guidelines, and
evals/README.md for how the agents are evaluated.
This project is source-available under the Business Source License 1.1.
You are free to read the code, modify it, and contribute, and to use it for non-production purposes such as evaluation, development, and testing. Production use requires a commercial EventCatalog license — contact hello@eventcatalog.dev. Each release converts to the Apache License 2.0 four years after it is published.