TaskConnectors

Inbound sources

Give a project an e-mail address, a signed webhook URL, a text channel or a Pub/Sub pull; every message is stored before it is acknowledged, then delivered once to each agent you subscribe.

Updated 9/15/2026

An inbound source is one place messages arrive: an address on our inbound domain, a webhook URL with its own secret, a text channel (Slack workspace, Telegram bot, SMS or WhatsApp number) or a Google Pub/Sub subscription we pull from. It lives on your project's Connections page like any other connection, and zero or more agents subscribe to it. Every message is written to the project's inbound ledger before the sender gets its acknowledgement, so nothing is lost when an agent is paused, out of credits, or mid-deploy.

Create one

Connections → New → Inbound offers four cards:

CardWhat you get
E-mail address<name>-<suffix>@inbound.connect0.ai; forward or point a mailbox at it
Webhook endpointhttps://webhooks.connect0.ai/inbound/<random path> and a signing secret shown once
Text messagesSlack (installed through the workspace sign-in), a Telegram bot (username + secret token), SMS / WhatsApp (number + auth token)
Pub/SubThe subscription name; we pull, so the subscription needs one grant (below)

Each card creates the source and opens its page, where you subscribe agents, pause delivery, rotate the secret, or remove it.

Subscribe agents

A source with no subscribers still stores everything; the events show as unrouted under Project → Inbound until an agent subscribes. A subscription is one agent plus two optional settings:

  • Filter — a field, an operator (eq, in, prefix, matches) and a value; only matching messages reach that agent. type eq issue.created on a Linear webhook, subject prefix [urgent] on an inbox.
  • Thread policy — where the message lands: per kind (e-mail: one sticky thread per sender; Slack: per channel; Telegram / SMS: per chat), sticky key (a payload field such as issue.id keeps one thread per issue), or new each (a fresh thread per message — the default for webhooks and Pub/Sub).

Two agents subscribed to one inbox each keep their own threads. The same subscriptions appear on the agent's Invocations tab.

How a message is verified

Every transport is verified before anything is stored; a failed check is answered 401 and never written.

TransportHeader / scheme
Your own webhook (generic)x-connect0-timestamp (unix seconds) and x-connect0-signature: sha256=<hex> — HMAC-SHA256 of ${timestamp}.${body} with the source secret; the timestamp must be within 300 s
GitHubx-hub-signature-256 over the body
Stripestripe-signature (t=…,v1=…) over ${t}.${body}, 300 s window
Linearlinear-signature over the body
Svix-delivered providers (incl. our inbound e-mail)svix-id, svix-timestamp, svix-signature
Slackx-slack-request-timestamp + x-slack-signature (v0)
Telegramx-telegram-bot-api-secret-token equal to the bot's secret token
SMS / WhatsAppx-twilio-signature over the URL and form fields
Pub/Sub pusha Google OIDC bearer token for the configured service account

Rotating a secret keeps the previous one valid for 24 hours so a sender can switch without a gap.

Deduplication and size

The sender's own event id is the deduplication key (the GitHub delivery id, the Stripe event id, the Svix message id, the Slack event id, the Telegram update id, the Pub/Sub message id); when a transport has none, send x-connect0-idempotency-key, or the timestamped body is hashed. A retry with the same id is acknowledged and stored once.

A message body is stored up to 256 KB; a larger body is kept truncated and marked as such. Each source accepts a bounded number of messages per minute (10 by default, up to 60); a sender that exceeds it receives 429 and retries — nothing is dropped.

The ledger, retention and re-delivery

Project → Inbound lists every stored message with its status (stored, delivered, unrouted, deferred, failed, expired), which agents it reached and the runs it started. Delivery pauses — and resumes on its own — when the account has no credits or a source is paused; a source's messages queue in order.

The stored body is nulled after the account's retention window (90 days by default; an owner can shorten or lengthen it); the row, its deliveries and the run links remain so the history stays readable.

Re-deliver on a message creates a fresh delivery for the agents that never received it or whose delivery failed — after fixing a filter, an agent, or an outage. It asks for a reason and is written to the audit log. Agents cannot trigger a re-delivery; only a person can.

Pub/Sub: the one grant

We pull from your subscription with our worker's service account, so the subscription needs the subscriber role once:

gcloud pubsub subscriptions add-iam-policy-binding <subscription> \
  --project=<your-project> \
  --member=serviceAccount:<the service account shown on the source card> \
  --role=roles/pubsub.subscriber

Messages are acknowledged only after they are stored; a pull that fails between store and acknowledge is simply delivered again by Pub/Sub and deduplicated on its message id.

Next

What this does not do

  • Inbound only. Replies and outbound messages are the agent's own tools, not part of a source.
  • No ordering across sources. Within one source, deliveries follow arrival order; two sources are independent.
  • No exactly-once towards the sender. We acknowledge after our own commit; a sender that retries is deduplicated by its event id, never delivered twice.
  • Retention nulls the stored message after the account's retention window (90 days by default); the ledger row, its deliveries and run links stay.
  • Unsigned webhooks are not accepted on the public endpoint. Every transport verifies a signature, a token or a Google identity.
  • E-mail attachments become files in the project media library (documents up to 50 MB, images, audio and video up to 500 MB); other types are noted in the thread but not stored.

Ask Zero

Ask a question about connect0 and get an answer grounded in the docs, with links to the sources. Signed in? Zero answers with your account in mind.