Skip to content

Channels & Triggers

Channels page — catalog of available channels with configured WhatsApp and Slack entries and their connection status.

A channel is an inbound surface that hands a message to an agent. A trigger is an inbound event (webhook, cron tick) that launches a task. Together they turn Agentcy from a chat app into an autonomous system that reacts to your world.

Related:

Channels catalog

Channel types exposed by GET /api/v1/channels:

ChannelTransportStatusNotes
whatsappBaileys (Node.js gateway)stableQR-code pairing flow. Gateway auto-spawned.
slackSocket ModestableFeature-gated; requires Slack app creds.
webchatHTTP + SSEstableEmbeddable widget, see Chat Widget.
emailSMTP/IMAPbetaInbound email → message.
smsTwiliobetaBidirectional SMS.

The catalog endpoint lists every possible channel and, per-org, its configured state (configured: true/false, last connection, bindings).

How a channel becomes an agent run

Inbound message (WhatsApp / Slack / …)


   Channel adapter translates to ChannelMessage {
     channel: "whatsapp", from, to, text, media, thread
   }


   ChannelBinding resolver — which agent handles this?
          │         (match_rule: {channel, phone, group, user})

   Agent runtime (same loop as UI chat)


   Outbound reply → channel adapter → provider API

The key object is a binding:

json
POST /api/v1/bindings
{
  "agent": "incident-responder",
  "match_rule": { "channel": "whatsapp", "group": "+972500000001" }
}

Rules are evaluated top-to-bottom; first match wins. If no binding matches, the message is logged and dropped (never auto-responded-to by default).

WhatsApp specifics

WhatsApp connects via a local Node.js gateway running Baileys. The gateway:

  • Is auto-extracted into ~/.openfang/whatsapp-gateway/ on first configure.
  • Requires Node ≥ 18 on the host.
  • Pairs via QR code (POST /api/v1/channels/whatsapp/qr/start returns a PNG data URL; poll /qr/status?session_id=).
  • Is re-branded as "Agentcy" in the device list (the gateway's browser: line is patched at startup).

Messages arrive as ChannelMessage with media attachments downloaded to agentcy-storage and referenced by artifact id.

See How-To: WhatsApp Channel.

Slack specifics

Slack runs in Socket Mode so you don't need a public URL. You provide:

  • SLACK_APP_TOKEN — app-level token starting with xapp-
  • SLACK_BOT_TOKEN — bot token starting with xoxb-

The listener (agentcy-slack-channel) opens a websocket to Slack and fans events into the same ChannelMessage path.

See How-To: Slack Channel.

Webchat

webchat is how embedded widgets deliver messages. The widget posts to POST /api/v1/chat/incoming/webchat with a shared secret header; the API resolves it to a conversation and streams the agent's reply back over SSE.

See Chat Widget.

Triggers

A trigger is an event source that starts a scheduled task. Three types:

TriggerSourcePayload
schedulecron (UTC){ "kind": "schedule", "fired_at": "…" }
webhookinbound HTTP{ "kind": "webhook", "headers": {…}, "body": {…} }
lifecycleAgentcy events (new node, source sync failed, …){ "kind": "lifecycle", "event": "…", "payload": {…} }

Webhook triggers

Webhooks have a public URL per trigger and an HMAC secret:

URL:    https://your-agentcy/api/v1/hooks/<trigger_id>
Header: X-Agentcy-Signature: sha256=<hex>

Verification is mandatory — the receiver rejects mismatches with 401.

You can drop a sample payload into the UI and trigger a dry run without a real caller (POST /api/v1/webhook-samples/:id/run). Samples live in agentcy-api::routes::webhook_samples.

See How-To: Webhooks & Triggers.

Lifecycle triggers

Emitted by the platform itself. Useful for reactive automation: "when a new :Incident node appears, page oncall."

EventWhen
node.createdAny new node landed in the graph.
node.updatedNode properties changed.
source.sync.failedA connector sync errored out.
policy.denyA policy blocked a tool call or API request.
approval.requestedAn agent is blocked on a human approval.

Cron triggers

Standard 5-field cron, UTC. agentcy-tasks uses tokio-cron-scheduler under the hood.

*/15 * * * *      every 15 minutes
0 9 * * 1-5       weekdays at 09:00 UTC
0 0 * * 0         sundays at midnight

Authorization

Channel inbound messages can produce tool calls just like UI chat. Policies still apply. A common pattern:

rego
# Allow WhatsApp bindings to run read-only tools without approval,
# but require human approval for write tools.
deny[msg] {
  input.subject.channel == "whatsapp"
  input.action == "chat.tool.execute"
  input.resource.tool_effect == "write"
  not input.context.approval_granted
  msg := "write tool on whatsapp needs approval"
}

See Writing Rego Policies.

Channel testing

Every channel exposes POST /api/v1/channels/:name/test, which validates credentials (sends a no-op probe where possible). Always run this after configuration; if it fails, reload with POST /api/v1/channels/reload after fixing.

Under the hood

Channels and triggers share one bus (ConnectorEventBus + channel plugin) so the UI can render a single "inbound" timeline. That's why channel messages, webhook hits, and cron ticks all show up together in Activity.

Key files:

  • backend/crates/agentcy-api/src/routes/channels.rs — REST surface.
  • backend/crates/agentcy-whatsapp/ — Baileys gateway wrapper.
  • backend/crates/agentcy-slack-channel/ — Socket Mode listener.
  • backend/crates/agentcy-tasks/ — scheduler, cron, trigger dispatch.
  • backend/crates/agentcy-api/src/routes/webhook_receiver.rs — HMAC webhook verifier.

Built by AgentcyLabs. For in-house deployment or Agentcy Cloud (PaaS) access, visit agentcylabs.com.