Pre-release Harn is pre-1.0 — the language, standard library, and CLI may change between releases. See the release notes

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#

ProviderUse whenSignatureRequired secretsRecipes
cronRun scheduled local workflows.None.None.Daily report, enrichment pass, health check.
webhookAccept 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-pushAccept 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, websocketConsume 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 verify command
  • required secrets and provider scopes
  • supported trigger/event types
  • mocked fixtures so CI does not need live provider credentials
ProviderPackage repoInstallPackage gateRequired secrets/scopesSupported trigger/event types
GitHubhttps://github.com/burin-labs/harn-github-connectorharn add github.com/burin-labs/harn-github-connector@v0.4.0harn package verify . --provider githubWebhook 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.
Slackhttps://github.com/burin-labs/harn-slack-connectorharn add github.com/burin-labs/harn-slack-connector@v0.2.1harn package verify . --provider slackSigning 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.
Linearhttps://github.com/burin-labs/harn-linear-connectorharn add github.com/burin-labs/harn-linear-connector (currently unreleased, manifest 0.0.0)harn package verify . --provider linearWebhook signing secret; optional API key/access token for outbound GraphQL.Issue, Comment, IssueLabel, Project, Cycle, Customer, CustomerRequest; outbound GraphQL.
Notionhttps://github.com/burin-labs/harn-notion-connectorharn add github.com/burin-labs/harn-notion-connector@v0.1.1harn package verify . --provider notion --run-poll-tickWebhook 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.
GitLabhttps://github.com/burin-labs/harn-gitlab-connectorharn add github.com/burin-labs/harn-gitlab-connector@v0.1.0harn package verify . --provider gitlabWebhook 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.
Forgejohttps://github.com/burin-labs/harn-forgejo-connectorharn add github.com/burin-labs/harn-forgejo-connector@v0.1.0harn package verify . --provider forgejoWebhook 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.
Giteahttps://github.com/burin-labs/harn-gitea-connectorharn add github.com/burin-labs/harn-gitea-connector@v0.1.0harn package verify . --provider giteaWebhook 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.
Bitbuckethttps://github.com/burin-labs/harn-bitbucket-connectorharn add github.com/burin-labs/harn-bitbucket-connector@v0.2.0harn package verify . --provider bitbucketOptional 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.
CircleCIhttps://github.com/burin-labs/harn-circleci-connectorharn add github.com/burin-labs/harn-circleci-connector@v0.1.0harn package verify . --provider circleciWebhook 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.
Buildkitehttps://github.com/burin-labs/harn-buildkite-connectorharn add github.com/burin-labs/harn-buildkite-connector@v0.1.0harn package verify . --provider buildkitePreferred 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.
SourceHuthttps://github.com/burin-labs/harn-sourcehut-connectorharn add github.com/burin-labs/harn-sourcehut-connector@v0.1.0harn package verify . --provider sourcehutWebhook 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.
Subversionhttps://github.com/burin-labs/harn-svn-connectorharn add github.com/burin-labs/harn-svn-connector@v0.1.0harn package verify . --provider svn --run-poll-tickOptional 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:

  1. Declares connector_contract = "v1" in package or registry metadata.
  2. Provides a [[providers]] manifest entry with connector = { harn = ... }.
  3. Exports provider_id, kinds, payload_schema, and the relevant normalize_inbound, poll_tick, or call exports.
  4. Declares provider-scoped setup metadata for generic host setup/status UI.
  5. Ships deterministic [connector_contract] fixtures and passes harn 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.toml package manifest with connector_contract = "v1"
  • contract fixtures that cover normal event, ack-first response, reject, and poll cases where relevant
  • a README.md with install, setup, required secrets/scopes, supported events, and harn package verify command
  • 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.