Package Exports
- @a5c-ai/events
Readme
@a5c-ai/events – Events SDK & CLI
Normalize and enrich GitHub (and other) events for agentic workflows. Use the CLI in CI or locally to turn raw webhook/Actions payloads into a compact, consistent schema that downstream agents and automations can trust.
- Quick install via npm
- Commands:
events mentions,events normalize,events enrich,events generate_context,events reactor,events emit,events validate(seedocs/cli/reference.mdfor options and examples) - Output: JSON to stdout or file
- Extensible via provider adapters and enrichers
Ownership & Routing
Semantics: enrichment computes owners_union as the sorted, de‑duplicated union of all CODEOWNERS across changed files. This differs from GitHub’s per‑file evaluation where the last matching rule wins. We use union semantics to enable broader, safer routing.
Learn more and see examples in docs/routing/ownership-and-routing.md (Semantics).
Quick Start
Prerequisites:
- Node.js 20.x LTS (see
.nvmrcfor CI parity).- If you use
nvm, runnvm usein the project root.
- If you use
Install:
npm install @a5c-ai/events
# or for CLI-only usage
npm install -g @a5c-ai/eventsTry it:
# Normalize a payload file
npx @a5c-ai/events normalize --in samples/workflow_run.completed.json --out out.json
# Inspect selected fields
jq '.type, .repo.full_name, .provenance.workflow?.name' out.json
# Validate against the NE schema (quiet on success)
cat out.json | npx @a5c-ai/events validate --quietProgrammatic SDK example:
- See SDK Quickstart:
docs/user/sdk-quickstart.md(minimal example usingmapToNEand optionalenrichGithub).
End-to-end CI example:
- End-to-end GitHub Actions recipe (normalize → enrich → reactor → emit):
docs/ci/actions-e2e-example.md
Ref note (important):
- The NE schema defines
ref.typeasbranch | tag | unknown. Pull request events use branch semantics and populateref.baseandref.headwith the base and head branch names respectively; there is noprenum inref.type. - Canonical references: see the NE Schema overview at
docs/cli/ne-schema.md#refand the JSON Schema atdocs/specs/ne.schema.json.
Normalized types (GitHub adapter): workflow_run, pull_request, push, issue, issue_comment, check_run, and now also release, deployment, job (from workflow_job), step (when granular), and alert (code/secret scanning).
CI Checks
For CI guidance and required checks, see docs/ci/ci-checks.md.
Validate locally: npm run -s validate:examples (details in docs/ci/ci-checks.md).
Triggers matrix (summary):
- Pull requests → Quick feedback:
Quick Checks(lint, typecheck, unit tests + coverage),Lint,Typecheck,Commit Hygiene, andTests(lightweight; mirrors Quick Checks but uploads coverage artifacts). - Push to protected branches (
a5c/main,main) → Heavier gates:Build,Tests(full install/build/test with coverage artifacts). - Branch semantics:
a5c/mainis development/staging;mainis production.
CLI Reference
Reactor: Apply rules to a normalized event and emit custom events — see docs/cli/reference.md#events-reactor for usage and examples.
Mentions config (Quick Start)
For the full, canonical list of Mentions flags and defaults, see the CLI reference. Quick examples:
# Disable scanning of changed files (code‑comment mentions)
events enrich --in ... --flag 'mentions.scan.changed_files=false'
# Restrict by language allowlist (accepts canonical IDs or common extensions; inputs normalize to IDs)
events enrich --in ... --flag 'mentions.languages=ts,js'Canonical reference and examples:
- docs/cli/reference.md#events-enrich
- docs/cli/reference.md#mentions-scanning
- End-to-end Actions example: docs/ci/actions-e2e-example.md
events mentions
- Purpose: Extract @mentions from text (stdin) or a file.
- Common flags:
--source <kind>:pr_body|pr_title|commit_message|issue_comment(default:pr_body)--file <path>: read from file instead of stdin--window <n>: context window size (default: 30)--known-agent <name...>: known agent names to boost confidence
events normalize
- Purpose: Convert a raw provider payload into the normalized Event schema.
- Common flags:
--in <file>: input JSON file (raw event)--out <file>: write result to file (default: stdout)--source <name>: provenance (action|webhook|cli) [default:cli]- Accepts
actionsas input alias and persistsprovenance.source: "action".
- Accepts
--select <paths>: comma-separated dot paths to include in output--filter <expr>: filter expressionpath[=value]; if not matching, exits with code 2 and no output (see CLI reference example: docs/cli/reference.md#events-normalize)--label <key=value...>: attach labels to top‑levellabels[](repeatable)
events enrich
- Purpose: Add metadata and correlations to a normalized event.
- Common flags:
--in <file>: normalized event JSON (or raw payload; NE shell will be created)--out <file>: write enriched result--rules <file>: rules file path (yaml/json)
--flag include_patch=<true|false>: include diff patches in files (default: false)--flag commit_limit=<n>: max commits to include (default: 50)- Mentions scanning flags are documented once in the CLI reference at
docs/cli/reference.md#events-enrichand are the canonical source of truth for wording and defaults. --use-github: enable GitHub API enrichment (requiresA5C_AGENT_GITHUB_TOKENorGITHUB_TOKEN;A5C_AGENT_GITHUB_TOKENtakes precedence when both are set). For CI convenience, you may setA5C_EVENTS_AUTO_USE_GITHUB=trueto auto-enable when a token is present; otherwise behavior remains offline by default.--select <paths>: comma-separated dot paths to include in output--filter <expr>: filter expressionpath[=value]; if not matching, exits with code 2 and no output (see CLI reference example: docs/cli/reference.md#events-enrich)
--label <key=value...>: attach labels to top‑levellabels[]
Mentions flags
Canonical source: Mentions scanning flags and defaults are documented in the CLI reference. To avoid drift, this README links to the canonical list instead of duplicating it.
- docs/cli/reference.md#events-enrich
- docs/cli/reference.md#mentions-scanning
Quick examples:
# Disable scanning changed files for code‑comment mentions
events enrich --in samples/pull_request.synchronize.json \
--flag mentions.scan.changed_files=false
# Restrict to specific languages and lower the size cap
events enrich --in samples/pull_request.synchronize.json \
--flag mentions.languages=ts,js \
--flag mentions.max_file_bytes=102400See also:
Specs:
docs/specs/README.md#42-mentions-schemaCLI reference:
docs/cli/reference.md#events-enrichBehavior:
Offline by default: without
--use-github, no network calls occur. Output includesenriched.githubwithpartial=trueandreason="flag:not_set". See example outputs:docs/examples/enrich.offline.jsonanddocs/examples/enrich.online.json.When
--use-githubis set but no token is configured, the CLI exits with code3(provider/network error) and prints an error; no JSON is emitted. For programmatic SDK usage and tests with an injected Octokit, a partial structure withreason: "token:missing"may be returned, but the CLI UX is exit3.
Exit codes: 0 success, non‑zero on errors (invalid input, etc.).
Offline GitHub enrichment
When you do not pass --use-github, enrichment runs without network calls. Two acceptable offline shapes exist:
- Minimal NE: omit
enriched.githubentirely (valid per schema; often used in minimal examples). - CLI default stub: include
enriched.githubwith{ provider: 'github', partial: true, reason: <implementation-defined> }.
The CLI currently uses the stub form; the exact reason string may evolve. See examples: docs/examples/enrich.offline.stub.json.
Example (excerpt):
{
"enriched": {
"github": {
"provider": "github",
"partial": true,
"reason": "flag:not_set",
},
},
}With --use-github and a valid token, fields are populated. For example:
events enrich --in samples/pull_request.synchronize.json --use-github | jq '.enriched.github.pr.mergeable_state'If you pass --use-github without a token, the CLI exits with code 3 and prints a clear error to stderr. The programmatic API may return a partial object with reason: "token:missing", but the CLI does not emit JSON on this error.
Notes:
- Minimal offline examples may omit
enriched.github. Both shapes validate against the NE schema. See also:docs/examples/enrich.offline.stub.json. For detailed command usage and examples, see docs/cli/reference.md.
Mentions scanning examples
Examples are centralized in the CLI Reference:
- docs/cli/reference.md#mentions-scanning
Rules quick-start (composed events)
Note: The CLI Reference is the single source of truth for flags/options.
Define a minimal rule in YAML and evaluate it with enrich --rules to emit composed events. This example matches the included PR sample (samples/pull_request.synchronize.json) which carries a documentation label.
# 1) Create a tiny rules file
cat > rules.sample.yml <<'YAML'
rules:
- name: pr_labeled_documentation
on: pull_request
when:
all:
- { path: "$.payload.pull_request.labels[*].name", contains: "documentation" }
emit:
key: pr_labeled_documentation
reason: "PR has documentation label"
targets: [developer-agent]
YAML
# 2) Enrich with rules and inspect composed outputs
events enrich --in samples/pull_request.synchronize.json \
--rules rules.sample.yml \
| jq '(.composed // []) | map({key, reason})'Notes:
events enrich --in samples/pull_request.synchronize.json \
--flag mentions.max_file_bytes=102400 \
--flag mentions.languages=ts,js// Learn more links
- Real‑world rules can combine predicates (
all/any/not,eq,in,contains,exists) and project fields intoemit.payload. See the richer sample atsamples/rules/conflicts.yml. - When no rules match,
.composedmay be absent ornull. Guard with(.composed // [])as shown. - Learn more:
- Specs §6.1: docs/specs/README.md#61-rule-engine-and-composed-events
- CLI Reference — Events Reactor: docs/cli/reference.md#events-reactor
Normalized Event Schema (MVP)
Normalized Event Schema (MVP)
Core fields returned by normalize:
id: provider-unique id (stubbed in CLI for local files)provider:github(default) or othertype: coarse event type (e.g.,workflow_run,pull_request,push)occurred_at: ISO timestamprepo: minimal repository inforef: branch/ref contextactor: event actorpayload: raw provider payload (object | array; verbatim). Note: payloads may be large; avoid printing the entire value in examples and prefer selecting specific fields with tools likejq.enriched:{ metadata, derived, correlations }labels: string array for routing (e.g.,env=staging)provenance:{ source: action|webhook|cli, workflow? }(no labels here). Note: CLI accepts--source actionsbut normalizes toactionin output.
See the detailed specs for full schema and roadmap.
Notes:
- Example outputs may omit or truncate large
payloadbodies to keep docs readable. - The optional
composed[].payloadallowsobject | array | null(from enrichment/rules). Seedocs/specs/ne.schema.json.
Examples
GitHub Actions (normalize current run):
- name: Normalize workflow_run
run: |
npx @a5c-ai/events normalize \
--source actions \
--in "$GITHUB_EVENT_PATH" \
--out event.json
jq '.type, .repo.full_name, .labels' event.json
### Enrichment examples
- Offline (includes minimal `enriched.github` stub): `docs/examples/enrich.offline.json`
- Online (includes minimal `enriched.github`): `docs/examples/enrich.online.json`
Both examples conform to the NE schema (`docs/specs/ne.schema.json`) and are validated in CI.Local payload file:
events normalize --in samples/pull_request.synchronize.json \
--out out.json
jq '.type, .labels' out.jsonEnrichment (offline vs online):
# Offline (default; no network calls)
events enrich --in samples/pull_request.synchronize.json --out enriched.offline.json
jq '.enriched.github // { partial: "offline" }' enriched.offline.json
# Online (GitHub enrichment; requires token)
export GITHUB_TOKEN=ghp_your_token_here
events enrich --in samples/pull_request.synchronize.json \
--flag include_patch=false --flag commit_limit=50 --flag file_limit=200 \
--use-github --out enriched.online.json
jq '.enriched.github.provider' enriched.online.jsonWith rules (composed events):
events enrich --in samples/pull_request.synchronize.json \
--rules samples/rules/conflicts.yml \
| jq '(.composed // []) | map({key, reason})'
# note: `reason` may be omitted depending on rule configurationSee also sample outputs:
- docs/examples/enrich.offline.json
- docs/examples/enrich.online.json
Coverage (Optional)
You can optionally upload coverage to Codecov. This repo does not enable uploads by default.
Opt-in steps (aligned with docs/ci/ci-checks.md):
- Define
CODECOV_TOKENvia repo/org Secret or Variable. - Use the guarded upload step after coverage is generated:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN || vars.CODECOV_TOKEN || '' }}
- name: Upload coverage to Codecov (optional)
if: ${{ env.CODECOV_TOKEN != '' }}
uses: codecov/codecov-action@v4
with:
token: ${{ env.CODECOV_TOKEN }}
files: coverage/lcov.info
flags: pr
fail_ci_if_error: falseAlternatively, use the repo script:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN || vars.CODECOV_TOKEN || '' }}
- name: Upload coverage to Codecov (optional)
if: ${{ env.CODECOV_TOKEN != '' }}
run: bash scripts/coverage-upload.shNote: The Codecov badge at the top links to the tree view for a5c/main: https://app.codecov.io/gh/a5c-ai/events/tree/a5c/main
Auth tokens: precedence & redaction
- Token precedence: runtime prefers
A5C_AGENT_GITHUB_TOKENoverGITHUB_TOKENwhen both are set (seesrc/config.ts). - Redaction: CLI redacts sensitive keys and common secret patterns in output by default (see
src/utils/redact.ts).- Sensitive keys include:
token,secret,password,passwd,pwd,api_key,apikey,key,client_secret,access_token,refresh_token,private_key,ssh_key,authorization,auth,session,cookie,webhook_secret. - Pattern masking includes (non‑exhaustive): GitHub PATs (
ghp_,gho_,ghu_,ghs_,ghe_), JWTs,Bearer ...headers, AWSAKIA.../ASIA...keys, Stripesk_live_/sk_test_, Slackxox...tokens, and URL basic auth (https://user:pass@host).
- Sensitive keys include:
Examples:
# Precedence: A5C_AGENT_GITHUB_TOKEN wins when both are set
export GITHUB_TOKEN=ghp_low_scope
export A5C_AGENT_GITHUB_TOKEN=ghs_org_or_repo_scope
events enrich --in samples/pull_request.synchronize.json --use-github | jq '.enriched.github.provider'
# Missing token with --use-github: exits 3
unset GITHUB_TOKEN A5C_AGENT_GITHUB_TOKEN
events enrich --in samples/pull_request.synchronize.json --use-github || echo $?
# stderr: GitHub enrichment failed: ...
# exit code: 3
# Mentions scanning controls for code comments
# Disable scanning of changed files
events enrich --in samples/pull_request.synchronize.json \
--flag mentions.scan.changed_files=false | jq '.enriched.mentions // [] | length'
# Restrict to selected languages and reduce size cap
events enrich --in samples/pull_request.synchronize.json \
--flag mentions.languages=ts,js \
--flag mentions.max_file_bytes=102400 \
| jq '.enriched.mentions // [] | map(select(.source=="code_comment")) | length'See also: CLI reference for flags and exit codes: docs/cli/reference.md. Cross‑link: docs/cli/code-comment-mentions.md and specs §4.2 in docs/specs/README.md.
Validate against schema
Use the NE JSON Schema at docs/specs/ne.schema.json to validate CLI output.
Note: outputs that include composed are enriched; composed is optional and defined in the NE schema (docs/specs/ne.schema.json), so it does not need to be removed for validation. If you want to validate the normalized-only subset, validate before enrichment or strip it with jq 'del(.composed)'. When present, composed[].payload is object | array | null.
# Normalize a sample workflow_run payload
events normalize --in samples/workflow_run.completed.json --out out.json
# Validate result using the built-in validator
events validate --in out.json --schema docs/specs/ne.schema.json --quiet
# Alternative (ajv-cli)
# npx ajv validate -s docs/specs/ne.schema.json -d out.json --spec=draft2020Extract mentions
Extract @agent/@user mentions from text or a file. From a file:
events mentions --source pr_body --file docs/specs/README.md | jq '.[].normalized_target'Or via stdin:
echo "Please route to @developer-agent and @validator-agent" | \
events mentions --source issue_comment | jq -r '.[].normalized_target'
# => developer-agent
# => validator-agentConfiguration
Environment variables:
GITHUB_TOKENorA5C_AGENT_GITHUB_TOKEN: enables GitHub API enrichmentDEBUG: set totrueto enable debug modeA5C_AGENT_GITHUB_TOKENorGITHUB_TOKEN: required when using--use-github- Logging toggles: see
docs/observability.md(CLI flags for log format/level are proposed; current support is env-only in select paths)
CLI behavior:
- Defaults are safe for local runs (no network calls unless
--use-githubis set). - Exit codes: 0 success; 1 generic error; 2 input/validation error (missing
--in, invalid JSON, filter mismatch); 3 provider/network error when--use-githubis requested and calls fail. - For CI, prefer explicit
--inand write--outartifacts for downstream steps.
Samples
See docs/specs/README.md for examples and behavior-driven test outlines. Add your own payloads under samples/ and reference them with --in.
Development
- Build:
npm run build - Dev CLI:
npm run dev(runssrc/cli.tsvia tsx) - Lint/Typecheck/Format:
npm run lint/npm run typecheck/npm run format- CI Observability: see
.github/actions/obs-summaryand.github/actions/obs-collectorcomposite actions which write a job summary and uploadobservability.json. Both composites set up Node viaactions/setup-node@v4with default Node 20; override withwith.node-versionif needed. Example usage lives in.github/workflows/tests.yml.- Node requirement: the composites under
.github/actions/obs-*execute Node inline scripts and ensure Node internally. You can optionally pre‑setup Node in your job if you want to control the toolchain:- uses: actions/setup-node@v4 with: node-version: 20
- Node requirement: the composites under
- CI runs lint and typecheck on PRs; see
.github/workflows/lint.ymland.github/workflows/typecheck.yml.
- CI Observability: see
- Local pre-commit enforces staged-file hygiene and runs lint-staged (ESLint + Prettier); see
docs/dev/precommit-hooks.md. Conventional commits are validated via Husky + commitlint; seedocs/contributing/git-commits.md. - Minimal Node types + commander; TypeScript configured in
tsconfig.json
Node.js Version Policy
This project targets Node 20 LTS by default:
- Engines:
"node": ">=20"inpackage.json - Local:
.nvmrcpins Node 20 - CI: workflows use
actions/setup-node@v4withnode-version-file: '.nvmrc'
Typecheck CI runs a matrix on Node 20 and 22 to catch version-specific type issues, but build/tests default to Node 20.
Commit conventions
We follow Conventional Commits. Local commit messages are validated with Husky + commitlint, and PRs run a commitlint check. See docs/contributing/git-commits.md.
For local hooks and skip flags, see docs/dev/precommit-hooks.md and the pre-commit section in CONTRIBUTING.md.
To use the commit message template locally:
git config commit.template .gitmessage.txtProject structure:
src/cli.ts– CLI entrypoint (mentions, normalize, enrich, emit, validate)src/normalize.ts/src/enrich.ts– command handlerssrc/providers/*– provider adapters (GitHub mapping underproviders/github)src/utils/redact.ts– redaction utilities
Background: a5c Platform Template
This repository initially used a generic a5c platform README. That content now lives in docs/producer/platform-template.md. The top‑level README focuses on the Events SDK/CLI. For the broader platform, visit https://a5c.ai and the docs.
Composed + Validate (Walkthrough)
You can enrich with rules to emit composed events and validate the enriched output against the NE schema. The composed field is part of the NE schema and optional; enriched documents validate as‑is. If you want to validate just the normalized subset, you may drop .composed before validation.
# Enrich with rules to produce `.composed[]`
events enrich --in samples/pull_request.synchronize.json --rules samples/rules/conflicts.yml --out enriched.json
# Inspect composed events (guard for absence; `reason` may be omitted)
jq '(.composed // []) | map({key, reason})' enriched.json
# Validate the enriched document against the NE schema (as‑is)
events validate --in enriched.json --schema docs/specs/ne.schema.json --quiet
# Option: validate the normalized‑only subset (drop `.composed`)
jq 'del(.composed)' enriched.json | events validate --schema docs/specs/ne.schema.json --quietNotes:
.composedmay be absent when no rules match. Use(.composed // [])injq.- NE schema:
docs/specs/ne.schema.jsonincludes optional top‑levelcomposed.payloadisobject | array;composed[].payloadmay beobject | array | null. reasonis optional depending on rule configuration.
Links
- Specs:
docs/specs/README.md - Issues: https://github.com/a5c-ai/events/issues
- Agent registry: https://github.com/a5c-ai/registry
See the CLI reference for canonical examples covering mentions.scan.changed_files, mentions.max_file_bytes, and mentions.languages:
- docs/cli/reference.md#events-enrich
See E2E coverage in tests/mentions.flags.e2e.test.ts for practical examples validating:
- default scanning on for changed files
- disabling scan via
mentions.scan.changed_files=false - size cap via
mentions.max_file_bytes - language restrictions via
mentions.languages
Normalized Event Schema (MVP)
Core fields returned by normalize:
id: provider-unique id (stubbed in CLI for local files)provider:github(default) or othertype: coarse event type (e.g.,workflow_run,pull_request,push)occurred_at: ISO timestamprepo: minimal repository inforef: branch/ref contextactor: event actorpayload: raw provider payload (object | array; verbatim). Note: payloads may be large; avoid printing the entire value in examples and prefer selecting specific fields with tools likejq.enriched:{ metadata, derived, correlations }labels: string array for routing (e.g.,env=staging)provenance:{ source: action|webhook|cli, workflow? }(no labels here)
See the detailed specs for full schema and roadmap.
Notes:
- Example outputs may omit or truncate large
payloadbodies to keep docs readable. - The optional
composed[].payloadallowsobject | array | null(from enrichment/rules). Seedocs/specs/ne.schema.json.
Examples
GitHub Actions (normalize current run):
- name: Normalize workflow_run
run: |
npx @a5c-ai/events normalize \
--source actions \
--in "$GITHUB_EVENT_PATH" \
--out event.json
# Note: --source actions is accepted as an alias; the stored value will be provenance.source: "action".
jq '.type, .repo.full_name, .labels' event.jsonLocal payload file:
events normalize --in samples/pull_request.synchronize.json \
--out out.json
jq '.type, .labels' out.jsonEnrichment (with GitHub lookups enabled):
export GITHUB_TOKEN=ghp_your_token_here
# Default include_patch is false; enable it explicitly only if you need diff bodies
events enrich --in samples/pull_request.synchronize.json \
--flag commit_limit=50 --flag file_limit=200 \
--use-github --out enriched.json
jq '.enriched' enriched.json
# To include patch diffs, opt in explicitly:
events enrich --in samples/pull_request.synchronize.json \
--flag include_patch=true --use-github | jq '.enriched.github.pr.files[0].patch'With rules (composed events):
events enrich --in samples/pull_request.synchronize.json \
--rules samples/rules/conflicts.yml \
| jq '(.composed // []) | map({key, reason})'
# note: `reason` may be omitted depending on rule configurationCoverage (Optional)
Coverage (Optional)
Default (recommended) — GitHub Action
- Prefer the official Action in CI. Add a repo secret named
CODECOV_TOKENand include a guarded step after tests generatecoverage/lcov.info:
- name: Upload coverage to Codecov (optional)
if: ${{ secrets.CODECOV_TOKEN != '' }}
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/lcov.info
# flags: pr|push (optional)
fail_ci_if_error: false- Existing workflows already follow this Action-based approach and will upload when a token is present:
.github/workflows/tests.yml(push ona5c/mainandmain).github/workflows/quick-checks.yml(PRs).github/workflows/pr-tests.yml(PRs)
- If the token is absent, the step is skipped and CI remains green.
Alternative — Script-based uploader
- For local runs or non-GitHub CI, you may use a script uploader. If your setup includes a helper script (for example,
scripts/coverage-upload.sh), call it after tests. Do not combine the script and the Action in the same workflow to avoid duplicate uploads.
Badge (optional)
For thresholds and how PR feedback works, see docs/ci/coverage.md.
After the first successful upload, add a badge to this README:
[](https://codecov.io/gh/a5c-ai/events)Replace the URL to match your VCS provider and repository if different. Private projects may require a tokenized badge; see Codecov docs.
Auth tokens: precedence & redaction
- Token precedence: runtime prefers
A5C_AGENT_GITHUB_TOKENoverGITHUB_TOKENwhen both are set (seesrc/config.ts). - Redaction: CLI redacts sensitive keys and common secret patterns in output by default (see
src/utils/redact.ts).- Sensitive keys include:
token,secret,password,passwd,pwd,api_key,apikey,key,client_secret,access_token,refresh_token,private_key,ssh_key,authorization,auth,session,cookie,webhook_secret. - Pattern masking includes (non‑exhaustive): GitHub PATs (
ghp_,gho_,ghu_,ghs_,ghe_), JWTs,Bearer ...headers, AWSAKIA.../ASIA...keys, Stripesk_live_/sk_test_, Slackxox...tokens, and URL basic auth (https://user:pass@host).
- Sensitive keys include:
Examples:
# Precedence: A5C_AGENT_GITHUB_TOKEN wins when both are set
export GITHUB_TOKEN=ghp_low_scope
export A5C_AGENT_GITHUB_TOKEN=ghs_org_or_repo_scope
events enrich --in samples/pull_request.synchronize.json --use-github | jq '.enriched.github.provider'
# Missing token with --use-github: exits 3 and marks reason
unset GITHUB_TOKEN A5C_AGENT_GITHUB_TOKEN
events enrich --in samples/pull_request.synchronize.json --use-github || echo $?
# stderr: GitHub enrichment failed: ...
# exit code: 3
See also: CLI reference for flags and exit codes: docs/cli/reference.md.
Validate against schema
Use the NE JSON Schema at docs/specs/ne.schema.json to validate CLI output.
Note: outputs that include composed are enriched; composed is optional and defined in the NE schema (docs/specs/ne.schema.json), so it does not need to be removed for validation. If you want to validate the normalized-only subset, validate before enrichment or strip it with jq 'del(.composed)'. When present, composed[].payload is object | array | null.
# Normalize a sample workflow_run payload
events normalize --in samples/workflow_run.completed.json --out out.json
# Validate result using the built-in validator
events validate --in out.json --schema docs/specs/ne.schema.json --quiet
# Alternative (ajv-cli)
# npx ajv validate -s docs/specs/ne.schema.json -d out.json --spec=draft2020Extract mentions
Extract @agent/@user mentions from text or a file. From a file:
events mentions --source pr_body --file docs/specs/README.md | jq '.[].normalized_target'Or via stdin:
echo "Please route to @developer-agent and @validator-agent" | \
events mentions --source issue_comment | jq -r '.[].normalized_target'
# => developer-agent
# => validator-agentConfiguration
Environment variables:
GITHUB_TOKENorA5C_AGENT_GITHUB_TOKEN: enables GitHub API enrichmentDEBUG: set totrueto enable debug modeA5C_AGENT_GITHUB_TOKENorGITHUB_TOKEN: required when using--use-github- Logging toggles: see
docs/observability.md(CLI flags for log format/level are proposed; current support is env-only in select paths)
CLI behavior:
- Defaults are safe for local runs (no network calls unless
--use-githubis set). - Exit codes: 0 success; 1 generic error; 2 input/validation error (missing
--in, invalid JSON, filter mismatch); 3 provider/network error when--use-githubis requested and calls fail. - For CI, prefer explicit
--inand write--outartifacts for downstream steps.
Samples
See docs/specs/README.md for examples and behavior-driven test outlines. Add your own payloads under samples/ and reference them with --in.
Development
- Build:
npm run build - Dev CLI:
npm run dev(runssrc/cli.tsvia tsx) - Lint/Typecheck/Format:
npm run lint/npm run typecheck/npm run format- CI Observability: see
.github/actions/obs-summaryand.github/actions/obs-collectorcomposite actions which write a job summary and uploadobservability.json. Both composites set up Node viaactions/setup-node@v4with default Node 20; override withwith.node-versionif needed. Example usage lives in.github/workflows/tests.yml.- Node requirement: the composites under
.github/actions/obs-*execute Node inline scripts and ensure Node internally. You can optionally pre‑setup Node in your job if you want to control the toolchain:- uses: actions/setup-node@v4 with: node-version: 20
- Node requirement: the composites under
- CI runs lint and typecheck on PRs; see
.github/workflows/lint.ymland.github/workflows/typecheck.yml.
- CI Observability: see
- Local pre-commit enforces staged-file hygiene and runs lint-staged (ESLint + Prettier); see
docs/dev/precommit-hooks.md. Conventional commits are validated via Husky + commitlint; seedocs/contributing/git-commits.md. - Minimal Node types + commander; TypeScript configured in
tsconfig.json
Node.js Version Policy
This project targets Node 20 LTS by default:
- Engines:
"node": ">=20"inpackage.json - Local:
.nvmrcpins Node 20 - CI: workflows use
actions/setup-node@v4withnode-version-file: '.nvmrc'
Typecheck CI runs a matrix on Node 20 and 22 to catch version-specific type issues, but build/tests default to Node 20.
Commit conventions
We follow Conventional Commits. Local commit messages are validated with Husky + commitlint, and PRs run a commitlint check. See docs/contributing/git-commits.md.
For local hooks and skip flags, see docs/dev/precommit-hooks.md and the pre-commit section in CONTRIBUTING.md.
To use the commit message template locally:
git config commit.template .gitmessage.txtProject structure:
src/cli.ts– CLI entrypoint (mentions, normalize, enrich, emit, validate)src/normalize.ts/src/enrich.ts– command handlerssrc/providers/*– provider adapters (GitHub mapping underproviders/github)src/utils/redact.ts– redaction utilities
Background: a5c Platform Template
This repository initially used a generic a5c platform README. That content now lives in docs/producer/platform-template.md. The top‑level README focuses on the Events SDK/CLI. For the broader platform, visit https://a5c.ai and the docs.
Composed + Validate (Walkthrough)
You can enrich with rules to emit composed events and validate the enriched output against the NE schema. The composed field is part of the NE schema and optional; enriched documents validate as‑is. If you want to validate just the normalized subset, you may drop .composed before validation.
# Enrich with rules to produce `.composed[]`
events enrich --in samples/pull_request.synchronize.json --rules samples/rules/conflicts.yml --out enriched.json
# Inspect composed events (guard for absence; `reason` may be omitted)
jq '(.composed // []) | map({key, reason})' enriched.json
# Validate the enriched document against the NE schema (as‑is)
events validate --in enriched.json --schema docs/specs/ne.schema.json --quiet
# Option: validate the normalized‑only subset (drop `.composed`)
jq 'del(.composed)' enriched.json | events validate --schema docs/specs/ne.schema.json --quietNotes:
.composedmay be absent when no rules match. Use(.composed // [])injq.- NE schema:
docs/specs/ne.schema.jsonincludes optional top‑levelcomposed.payloadisobject | array;composed[].payloadmay beobject | array | null. reasonis optional depending on rule configuration.
Links
- Specs:
docs/specs/README.md - Issues: https://github.com/a5c-ai/events/issues
- Agent registry: https://github.com/a5c-ai/registry