Skip to content
AGH RuntimeBridges

Bridges Overview

How AGH bridge instances connect workspace agents to external messaging platforms.

Audience
Operators running durable agent work
Focus
Bridges guidance shaped for scanability, day-two clarity, and operator context.

A bridge is a workspace-facing adapter between AGH sessions and a messaging platform. The platform can be Slack, Discord, Telegram, or any installed extension that advertises the bridge.adapter capability. The bridge instance stores the operator-owned configuration; the provider extension owns platform-specific webhook validation, message normalization, and outbound delivery.

That split keeps AGH responsible for sessions, routing, persistence, and delivery bookkeeping while letting each platform adapter speak the platform API directly.

Hand-drawn Bridges poster showing generic messaging platforms, bridge adapters, routing, delivery, and workspace-scoped bridge config with the octopus mascot.

In this section

Runtime model

ObjectOwned byWhat it does
Provider extensionExtension catalogDeclares bridge.adapter, platform name, display name, required secret slots, and provider config schema hints.
Bridge instanceAGH bridge registryStores scope, workspace, provider selection, routing policy, delivery defaults, provider config, status, and degradation metadata.
Secret bindingAGH daemonMaps a provider slot such as bot_token to a vault-backed secret reference and stores the write-only secret value encrypted.
Bridge routeAGH routing layerMaps one canonical platform identity to one AGH session and agent name.
Delivery targetDelivery brokerIdentifies where a response should be posted, replied to, edited, or deleted on the platform.

The provider catalog is dynamic. GET /api/bridges/providers returns every installed and enabled extension that provides bridge.adapter. In this repository, the catalog includes provider manifests for Slack, Discord, Telegram, WhatsApp, Microsoft Teams, Google Chat, GitHub, and Linear. This setup guide covers Slack, Discord, and Telegram because those are the supported walkthroughs for this section.

Message flow

Rendering diagram...

An inbound platform event is normalized by the adapter, routed to an AGH session, and streamed back through the delivery broker to the same platform.

Adapter architecture

The bridge adapter runs as an extension subprocess. During initialization, AGH gives it the bridge instances assigned to that extension and a Host API surface. The adapter then:

  1. Resolves bridge secret bindings from the daemon-provided cache.
  2. Starts webhook listeners for configured bridge instances.
  3. Verifies incoming platform requests before ingestion.
  4. Converts platform payloads into normalized bridge envelopes.
  5. Reports bridge state back to AGH as ready, degraded, auth_required, or error.
  6. Delivers response events back to the platform API and acknowledges delivery to AGH.

AGH does not parse Slack, Discord, or Telegram webhook payloads in the daemon. The daemon accepts the normalized envelope only after the provider extension authenticates itself and the bridge instance is enabled for that extension.

Bridge instance format

Bridge instances are persisted runtime records. They are created through the bridge API or the agh bridge create command, not through config.toml.

{
  "scope": "workspace",
  "workspace_id": "ws_8f33a913d23c4fd1",
  "platform": "slack",
  "extension_name": "slack",
  "display_name": "Slack support",
  "enabled": false,
  "status": "disabled",
  "dm_policy": "allowlist",
  "routing_policy": {
    "include_peer": false,
    "include_thread": true,
    "include_group": true
  },
  "provider_config": {
    "webhook": {
      "listen_addr": "127.0.0.1:18081",
      "path": "/slack/support"
    },
    "dm": {
      "allow_user_ids": ["U0123456789"]
    }
  },
  "delivery_defaults": {
    "group_id": "C0123456789",
    "thread_id": "1713200000.000100",
    "mode": "direct-send"
  }
}
FieldRequiredNotes
scopeyesworkspace or global. Use workspace for inbound sessions.
workspace_idworkspace onlyRequired when scope is workspace; forbidden for global.
platformyesPlatform identifier such as slack, discord, or telegram.
extension_nameyesInstalled extension that owns the provider, usually the same as the platform.
display_nameyesOperator-facing name shown by CLI/API output.
enabledyesDisabled instances do not accept routing work. Create disabled, bind secrets, then enable.
statusyesdisabled, starting, ready, degraded, auth_required, or error.
dm_policynoopen, allowlist, or pairing; empty normalizes to open. Providers enforce this against their dm config.
routing_policyyesChooses which platform identity dimensions join the canonical route key.
provider_confignoProvider-owned JSON object. The transport accepts any JSON object or null; each adapter validates the keys it uses.
delivery_defaultsnoJSON object with peer_id, thread_id, group_id, and mode. thread_id requires peer_id or group_id.

Package-managed instances can be created by extension bundles. Those records report source: "package" and reject direct spec mutation through the generic update API.

Supported provider slots

ProviderRequired secretsOptional secretsWebhook auth
Slackbot_token, signing_secretnoneSlack request signing secret.
Discordbot_token, public_keynoneDiscord Ed25519 interaction signature headers.
Telegrambot_tokenwebhook_secretTelegram X-Telegram-Bot-Api-Secret-Token header when configured.

Bind each slot to an AGH-managed vault secret before enabling the bridge. The API accepts the plaintext only through the write-only secret_value field and never returns it:

curl -X PUT http://localhost:2123/api/bridges/brg_123/secret-bindings/bot_token \
  -H "Content-Type: application/json" \
  -d '{"secret_ref":"vault:bridges/brg_123/bot_token","secret_value":"xoxb-...","kind":"token"}'

The reference must be scoped to the edited bridge: vault:bridges/<bridge>/<slot>. Restart or enable the bridge after changing a binding so the provider receives fresh launch material.

Bridge Vault refs are visible as redacted metadata through Settings > Vault, agh vault list --namespace bridges, and /api/vault/secrets?namespace=bridges. The plaintext secret_value is accepted only on write.

Operational states

StatusMeaningIngest behavior
disabledOperator disabled the instance.Rejected as unavailable.
startingExtension is launching, restarting, or reconnecting.Rejected until the provider reports readiness.
readyProvider is healthy and can ingest and deliver.Accepted.
degradedProvider can still work but reported a known issue.Accepted; health payload includes the degradation reason.
auth_requiredRequired credential or platform authorization is missing or invalid.Rejected until fixed and restarted.
errorProvider reached a terminal or repeated fault.Rejected until restarted or repaired.

Bridge health is exposed with each bridge payload and through the bridge health stream. It includes route count, delivery backlog, dropped delivery count, delivery failures, auth failures, last success, last error, and degradation metadata.

On this page