Gateway Provider Readiness¶
Gateway providers in this document are Cloud Channel Gateway adapters. They never own OpenCode execution, sessions, workflow scheduling, or Cloud control-plane state. Every provider normalizes channel input into Cloud channel APIs and renders Cloud session events back to the channel.
Standalone Team Gateway may reuse provider packages later, but its private runtime/control-plane ownership is a separate product mode and not part of this Cloud Channel Gateway readiness matrix.
The typed source of truth is apps/gateway/src/provider-readiness.ts. The Gateway test suite verifies that this page, the matrix, and actual provider capabilities stay aligned.
Provider Identity Contract¶
Gateway provider configuration separates provider kind from provider instance:
kindis the adapter implementation, such astelegram,slack,email, orwebhook.idis the configured provider instance, such astelegram-main,telegram-support,slack-work, orwebhook-ci.channelBindingIdis the Cloud control-plane binding that maps the provider instance to a headless agent and delivery route.
Kind-only ids such as telegram remain supported for existing self-hosted configs. New production configs should use explicit instance ids so multiple providers of the same kind can coexist without sharing cursors, health, deliveries, or channel-thread bindings. Legacy downstream ids such as acme-telegram are accepted for compatibility, but kind-prefixed ids are the recommended convention for new deployments.
Every provider exposes id, kind, and capabilities, and may expose runtime health. Provider readiness and diagnostics use the instance id for routing and the kind for capability/policy decisions.
Provider Readiness Matrix¶
| Provider | Tier | Status | Modes | Auth / signing | Approvals | Files | Contract tests |
|---|---|---|---|---|---|---|---|
telegram | Tier 1 | Launch | polling, webhook | Bot token; webhook secret when webhook mode is enabled | Inline buttons plus token fallback | Upload/download | packages/gateway-provider-telegram/src/telegram-provider.test.ts, packages/gateway-provider-telegram/src/telegram-retry.test.ts, apps/gateway/src/daemon.test.ts |
slack | Tier 1 | Launch | webhook | Bot token and Slack signing secret | Inline buttons plus token fallback | Upload/download | packages/gateway-provider-slack/src/slack-provider.test.ts, apps/gateway/src/daemon.test.ts |
email | Tier 1 | Launch | webhook | Inbound shared secret plus stable messageId/id replay key; SMTP credentials where required | Token fallback | Inbound uploads capped by Gateway request-body limit; outbound artifact links | packages/gateway-provider-email/src/email-provider.test.ts, apps/gateway/src/event-renderer.test.ts |
webhook | Tier 2 | Utility | webhook | HMAC/timestamp shared secret for ingress and outbound delivery | Inline buttons if bridge supports them; token fallback otherwise | Inline inbound files capped by Gateway request-body limit; outbound links | packages/gateway-provider-webhook/src/webhook-provider.test.ts, apps/gateway/src/daemon.test.ts |
cli | Tier 2 | Utility | stdio | Trusted local process boundary; no public HTTP ingress | Token fallback | Inbound metadata; outbound links | packages/gateway-provider-cli/src/cli-provider.test.ts, scripts/gateway-cloud-smoke.mjs |
discord | Tier 3 | Later hardening (Discord Bridge) | signed bridge webhook | Bridge shared secret | Inline buttons plus token fallback | Bridge uploads/downloads capped by Gateway request-body limit | packages/gateway-provider-discord/src/discord-provider.test.ts, packages/gateway-provider-webhook/src/webhook-provider.test.ts |
whatsapp | Tier 3 | Later hardening (WhatsApp Bridge) | signed bridge webhook | Bridge shared secret | Inline buttons plus token fallback | Bridge uploads/downloads capped by Gateway request-body limit | packages/gateway-provider-whatsapp/src/whatsapp-provider.test.ts, packages/gateway-provider-webhook/src/webhook-provider.test.ts |
signal | Tier 3 | Later hardening (Signal Bridge) | signed bridge webhook | Bridge shared secret | Token fallback | Bridge uploads/downloads capped by Gateway request-body limit | packages/gateway-provider-signal/src/signal-provider.test.ts, packages/gateway-provider-webhook/src/webhook-provider.test.ts |
fake | Tier demo | Demo only | local fake webhook | Explicit OPEN_COWORK_GATEWAY_ENABLE_FAKE_PROVIDER=true; loopback by default | Inline buttons plus token fallback | In-memory test files capped by Gateway request-body limit | packages/gateway-testing/src/fake-channel.test.ts, apps/gateway/src/daemon.test.ts, scripts/gateway-cloud-smoke.mjs |
Tier Policy¶
Tier 1 providers are the launch target. They must have local provider contract tests, Gateway daemon wiring tests, signed ingress where public, approval round-trips, file behavior where advertised, and documented live-provider smoke instructions.
Tier 2 providers are local or integration utilities. They are production-safe only inside their intended boundary: signed webhook bridges for webhook, and trusted local process boundaries for cli.
Tier 3 providers are bridge-backed adapters for later live-provider hardening. They are useful for downstream experiments, but public launch does not depend on them until a live provider recipe and smoke path are promoted.
Discord, WhatsApp, and Signal are bridge-mode providers, not native platform webhook endpoints. A trusted relay must verify the native platform signature or channel-specific auth first, normalize the payload, and then re-sign it with the Open Cowork bridge shared secret. Do not point Discord Interactions, Meta WhatsApp webhooks, or an unauthenticated Signal bridge directly at Gateway; use the Tier 1 providers or the generic signed webhook provider for public ingress until native adapters are promoted.
The fake provider is not a real channel. It exists for local demos and CI smokes only. Public exposure is blocked unless a deployer explicitly opts into the demo override.
Capability Expectations¶
- Inline approvals must use provider-native buttons when
inlineButtonsis true. - Channels without buttons must render
/approve,/deny,/answer, or/rejecttoken fallback commands. - Channels with message editing may update streaming assistant output in place.
- Channels without message editing must chunk or buffer output.
- Files are only sent as provider files when the provider advertises download support and the artifact fits provider limits.
- Otherwise, artifacts render as Cloud artifact links.
- Typing indicators are best-effort and must never block prompt execution.
Security Expectations¶
- Public webhook providers must fail closed without signing/HMAC/shared-secret verification.
- Gateway and Standalone Gateway webhook HTTP surfaces apply source-scoped request throttles with
Retry-Afterbefore provider dispatch. - Generic webhook outbound delivery is signed with timestamped HMAC headers by default; legacy shared-secret headers are local compatibility only.
- Gateway service-token authority is separate from inbound actor authority. Cloud resolves the channel actor and enforces approval authority.
- Production providers must map incoming messages, commands, and interactions to stable provider event ids before Gateway prompts Cloud. Replaying the same signed provider event after a Gateway restart must hit the Cloud provider-event claim and produce no second prompt.
- Provider sends must preserve the Cloud delivery id as the provider delivery id when the provider API allows it. Webhook and bridge providers must also send that value as
deliveryId,idempotencyKey, andx-open-cowork-gateway-delivery-id. - Diagnostics, logs, provider health, delivery summaries, and metrics must not expose raw provider tokens, webhook secrets, API tokens, local paths, or signed artifact URLs.
- Local/demo providers must remain loopback-only by default.
Live Smoke Instructions¶
Use pnpm deploy:gateway:smoke against a real Cloud URL when validating a deployed appliance. The smoke creates an ephemeral gateway-scoped token, proves prompt-to-session continuation, exercises approval fallback, creates an async delivery, verifies delivery acknowledgement, and revokes the token.
Provider-specific live checks:
- Telegram: start with polling for private installs; webhook mode requires an HTTPS public URL and webhook secret.
- Slack: configure Events and Interactivity to POST to
/webhooks/slack; verify signed events and button callbacks. - Email: send an inbound webhook/mail fixture and verify the threaded reply.
- Webhook: send signed bridge payloads and verify unsigned, stale, and replayed requests fail.
- CLI: use only for trusted local smoke and never expose it over public HTTP.