Connector catalog
This catalog is the entry point for choosing a connector, wiring its trigger manifest, and finding a ready-to-customize example. It reflects the current runtime split:
- Cron, generic webhook, A2A push, and stream ingress are core runtime providers.
- Provider business logic belongs in pure-Harn connector packages.
- Community connectors are Harn packages that export connector contract v1 and
pass
harn package verify.
For the architecture and ownership split that closes the old connector-library epic, see Connector architecture status.
GitHub, Slack, Linear, and Notion are first-party pure-Harn packages:
harn-github-connector, harn-slack-connector, harn-linear-connector, and
harn-notion-connector. Configure one by setting
connector = { harn = "..." } on the [[providers]] table. See the
Rust-to-Harn-package migration guide
for the cutover pattern.
For an LLM-sized version of this page, use
docs/llm/harn-triggers-quickref.md.
That file is generated from the live provider catalog and checked by CI.
Built-in runtime providers#
| Provider | Use when | Signature | Required secrets | Recipes |
|---|---|---|---|---|
cron | Run scheduled local workflows. | None. | None. | Daily report, enrichment pass, health check. |
webhook | Accept generic Standard Webhooks-style HTTP events. | HMAC-SHA256, webhook-signature, webhook-timestamp, webhook-id. | webhook/signing_secret. | Stripe/Square-style handlers, HMAC-gated callbacks. |
a2a-push | Accept A2A task/update pushes from another orchestrator. | Transport auth is handled by the A2A layer. | None at catalog level. | Multi-orchestrator fanout, remote reviewer dispatch. |
kafka, nats, pulsar, postgres-cdc, email, websocket | Consume stream-shaped ingress through the shared stream connector. | Provider-specific transport configuration. | None at catalog level. | Fan-in, windowing, classifier routing. |
Cron daily report#
[[triggers]]
id = "daily-digest"
kind = "cron"
provider = "cron"
schedule = "0 9 * * 1-5"
timezone = "America/Los_Angeles"
handler = "send_daily_digest"
See examples/triggers/cron-daily-digest.
Generic webhook with HMAC#
[[triggers]]
id = "stripe-webhook"
kind = "webhook"
provider = "webhook"
match = { path = "/hooks/stripe", events = ["invoice.payment_succeeded"] }
handler = "handlers::on_webhook"
dedupe_key = "event.dedupe_key"
secrets = { signing_secret = "webhook/stripe-signing-secret" }
See examples/triggers/webhook-generic-hmac.
A2A fanout#
[[triggers]]
id = "reviewer-fanout"
kind = "a2a-push"
provider = "a2a-push"
match = { events = ["task.completed"] }
handler = "route_review_result"
See examples/triggers/a2a-reviewer-fanout.
First-party pure-Harn packages#
Each first-party connector repo should publish:
- repository URL and package install command
harn package verifycommand- required secrets and provider scopes
- supported trigger/event types
- mocked fixtures so CI does not need live provider credentials
| Provider | Package repo | Install | Package gate | Required secrets/scopes | Supported trigger/event types |
|---|---|---|---|---|---|
| GitHub | https://github.com/burin-labs/harn-github-connector | harn add github.com/burin-labs/harn-github-connector@v0.4.0 | harn package verify . --provider github | Webhook secret; for outbound, GitHub App id, installation id, and private key. App permissions depend on methods: issues, pull requests, contents/metadata, checks, deployments. | issues, pull_request, issue_comment, pull_request_review, push, workflow_run, deployment_status, check_run, check_suite, status, merge_group, installation, installation_repositories; outbound REST/GraphQL escape hatches. Each event also exposes the connector's stable github.<event>[.<action>] topic plus normalized repo/repository fields. |
| Slack | https://github.com/burin-labs/harn-slack-connector | harn add github.com/burin-labs/harn-slack-connector@v0.2.1 | harn package verify . --provider slack | Signing secret; for outbound, bot token. Typical scopes: app_mentions:read, channels:history, reactions:read, chat:write, reactions:write, users:read, files:write. | URL verification, message, app_mention, reaction_added, app_home_opened, assistant_thread_started; outbound Web API calls. |
| Linear | https://github.com/burin-labs/harn-linear-connector | harn add github.com/burin-labs/harn-linear-connector (currently unreleased, manifest 0.0.0) | harn package verify . --provider linear | Webhook signing secret; optional API key/access token for outbound GraphQL. | Issue, Comment, IssueLabel, Project, Cycle, Customer, CustomerRequest; outbound GraphQL. |
| Notion | https://github.com/burin-labs/harn-notion-connector | harn add github.com/burin-labs/harn-notion-connector@v0.1.1 | harn package verify . --provider notion --run-poll-tick | Webhook verification token; outbound API token. Notion integration capabilities depend on pages/databases/comments used. | Webhook events such as subscription verification, page updates, comments, data source schema updates; poll_tick database/page watchers; outbound Notion API via notion-sdk-harn. |
| GitLab | https://github.com/burin-labs/harn-gitlab-connector | harn add github.com/burin-labs/harn-gitlab-connector@v0.1.0 | harn package verify . --provider gitlab | Webhook signing secret (plain shared-secret X-Gitlab-Token, not HMAC); for outbound, an OAuth2 access token, PAT, or project/group access token with api scope. | push, tag_push, merge_request, note, issue, pipeline; outbound REST (notes, MR update/changes/approve, commit status, repository files), GraphQL passthrough, OAuth2 helpers, and shared GitForgePullRequestEvent emission for merge requests. |
| Forgejo | https://github.com/burin-labs/harn-forgejo-connector | harn add github.com/burin-labs/harn-forgejo-connector@v0.1.0 | harn package verify . --provider forgejo | Webhook signing secret verified as HMAC-SHA256 from X-Gitea-Signature; for outbound, a user, organization, or repository access token accepted by the instance API. | push, pull_request, issues, issue_comment, release, repository, star; outbound REST for comments, PR updates, commit statuses, repository contents, raw API passthrough, and shared GitForgePullRequestEvent emission for pull requests. |
| Gitea | https://github.com/burin-labs/harn-gitea-connector | harn add github.com/burin-labs/harn-gitea-connector@v0.1.0 | harn package verify . --provider gitea | Webhook signing secret verified as HMAC-SHA256 from X-Gitea-Signature; for outbound, an access token scoped to the target self-hosted instance. | push, pull_request, issues, issue_comment, release, repository, star; outbound REST for comments, PR updates, commit statuses, repository contents, raw API passthrough, and shared GitForgePullRequestEvent emission for pull requests. |
| Bitbucket | https://github.com/burin-labs/harn-bitbucket-connector | harn add github.com/burin-labs/harn-bitbucket-connector@v0.2.0 | harn package verify . --provider bitbucket | Optional webhook signing secret verified as HMAC-SHA256 from X-Hub-Signature; X-Hook-UUID and X-Request-UUID are preserved for dedupe. For outbound, app password, OAuth2 token, or Data Center PAT. | Cloud and Data Center repo:push, pullrequest:*, issue:*, repo:commit_status_*; outbound PR comments/updates, commit statuses, repository file fetches, and raw API passthrough. |
| CircleCI | https://github.com/burin-labs/harn-circleci-connector | harn add github.com/burin-labs/harn-circleci-connector@v0.1.0 | harn package verify . --provider circleci | Webhook signing secret verified as circleci-signature v1= HMAC-SHA256 over the raw body; for outbound, a CircleCI personal API token sent as Circle-Token. | workflow-completed, job-completed; failure normalization, workflow rerun from failed, cancel, workflow/job lookups, and artifact listing. Use the shared GitHub commit-to-PR resolver when the webhook has no PR number. |
| Buildkite | https://github.com/burin-labs/harn-buildkite-connector | harn add github.com/burin-labs/harn-buildkite-connector@v0.1.0 | harn package verify . --provider buildkite | Preferred webhook verification is X-Buildkite-Signature: timestamp=...,signature=... HMAC-SHA256 over "<timestamp>.<raw_body>" with a 5-minute freshness window; X-Buildkite-Token is accepted as a simpler fallback. Outbound calls use Authorization: Bearer. | build.finished, job.finished; failure normalization, job retry, rebuild, cancel, job log fetches, raw REST, optional GraphQL, and shared GitHub commit-to-PR lookup when build.pull_request is absent. |
| SourceHut | https://github.com/burin-labs/harn-sourcehut-connector | harn add github.com/burin-labs/harn-sourcehut-connector@v0.1.0 | harn package verify . --provider sourcehut | Webhook public key verified with Ed25519 over the raw payload; outbound GraphQL/REST calls use an OAuth2 token or PAT. | Repository push/update events, todo/ticket changes, build notifications, mailing-list oriented message metadata; outbound GraphQL/REST passthrough. |
| Subversion | https://github.com/burin-labs/harn-svn-connector | harn add github.com/burin-labs/harn-svn-connector@v0.1.0 | harn package verify . --provider svn --run-poll-tick | Optional post-commit hook HMAC secret; polling credentials are repository URL plus username/password, SSH key, or ambient host-managed credential helper. | commit, branch, tag, property_change; webhook-style post-commit normalization plus poll_tick revision scanning for repositories that cannot install hooks. |
Direct GitHub installs are the MVP path. Registry names such as
@burin/notion-connector should be used once the hosted first-party index is
available.
GitHub stale PR nudger#
[[triggers]]
id = "github-stale-pr-nudger"
kind = "cron"
provider = "cron"
schedule = "0 15 * * 1-5"
handler = "nudge_stale_prs"
See examples/triggers/github-stale-pr-nudger.
Slack keyword router#
[[triggers]]
id = "slack-keyword-router"
kind = "webhook"
provider = "slack"
match = { path = "/hooks/slack", events = ["message", "app_mention"] }
handler = "route_message"
secrets = { signing_secret = "slack/signing-secret" }
See examples/triggers/slack-keyword-router.
Linear SLA breach alert#
[[triggers]]
id = "linear-sla-breach"
kind = "cron"
provider = "cron"
schedule = "*/30 * * * *"
handler = "scan_for_sla_breaches"
See examples/triggers/linear-sla-breach.
Notion database watcher#
[[triggers]]
id = "notion-database-watcher"
kind = "poll"
provider = "notion"
handler = "on_database_change"
poll = { interval = "5m", state_key = "notion:database:watcher", max_batch_size = 50 }
secrets = { verification_token = "notion/verification-token" }
See examples/triggers/notion-database-watcher.
Git forge quickstart demo#
GitHub, GitLab, and Forgejo can be wired side by side with only provider package changes. Each provider owns its verification and outbound API details inside its pure-Harn connector package:
[dependencies]
harn-github-connector = { git = "https://github.com/burin-labs/harn-github-connector", rev = "v0.4.0" }
harn-gitlab-connector = { git = "https://github.com/burin-labs/harn-gitlab-connector", rev = "v0.1.0" }
harn-forgejo-connector = { git = "https://github.com/burin-labs/harn-forgejo-connector", rev = "v0.1.0" }
[[providers]]
id = "github"
connector = { harn = "harn-github-connector" }
[[providers]]
id = "gitlab"
connector = { harn = "harn-gitlab-connector" }
[[providers]]
id = "forgejo"
connector = { harn = "harn-forgejo-connector" }
Community connector discovery#
A community connector is any Harn package that:
- Declares
connector_contract = "v1"in package or registry metadata. - Provides a
[[providers]]manifest entry withconnector = { harn = ... }. - Exports
provider_id,kinds,payload_schema, and the relevantnormalize_inbound,poll_tick, orcallexports. - Declares provider-scoped
setupmetadata for generic host setup/status UI. - Ships deterministic
[connector_contract]fixtures and passesharn package verify ..
Minimal package shape:
[package]
name = "harn-acme-connector"
version = "0.1.0"
connector_contract = "v1"
[exports]
default = "src/lib.harn"
[[providers]]
id = "acme"
connector = { harn = "src/lib.harn" }
capabilities = ["webhook"]
[providers.setup]
auth_type = "api-key"
flow = "api-key"
required_secrets = [{ id = "acme/api-key", direction = "outbound" }]
credential_environment = [
{ secret = "acme/api-key", environment_names = ["ACME_API_KEY"] },
]
setup_command = ["harn", "connect", "api-key", "--connector", "acme", "--secret-id", "acme/api-key"]
validation_command = ["harn", "connect", "status", "--connector", "acme", "--json"]
[[providers.setup.health_checks]]
id = "api-key"
kind = "secret"
secret = "acme/api-key"
[providers.setup.recovery]
missing_auth = "Store an Acme API key as acme/api-key."
expired_credentials = "Rotate the Acme API key."
revoked_credentials = "Replace the revoked Acme API key."
missing_scopes = "Create an Acme API key with the required scopes."
inaccessible_resource = "Grant the API key access to the target Acme resource."
transient_provider_outage = "Retry after Acme or the credential backend recovers."
[connector_contract]
version = 1
[[connector_contract.fixtures]]
provider = "acme"
name = "sample webhook"
kind = "webhook"
headers = { "content-type" = "application/json" }
body_json = { id = "evt-1", type = "thing.created" }
expect_type = "event"
expect_kind = "acme.thing.created"
expect_dedupe_key = "evt-1"
expect_payload_contains = { provider = "acme", event = "thing.created", id = "evt-1" }
expect_event_count = 1
Run:
harn package verify .
Use live credentials only in provider-specific integration tests. Catalog examples and contract fixtures should run against mocked connector fixtures so Harn CI, connector repo CI, and local authoring all stay deterministic.
Authoring a connector#
Start with Connector authoring, then add:
- a
harn.tomlpackage manifest withconnector_contract = "v1" - contract fixtures that cover normal event, ack-first response, reject, and poll cases where relevant
- a
README.mdwith install, setup, required secrets/scopes, supported events, andharn package verifycommand - mocked tests for outbound
call(...)methods - a small recipe example under
examples/triggers/when the connector is first-party or broadly useful
The Harn-side contract is deliberately small. Keep provider SDKs or generated
API clients in separate packages when that makes the connector easier to test
and reuse, as with notion-sdk-harn.