@photon-ai/chat-adapter
connects Chat SDK bots to the channels connected to a
Photon Beta project: iMessage, SMS, WhatsApp, WhatsApp Business, Telegram, and
email. It calls the Photon API with a project API key and receives events through
signed webhooks or a WebSocket connection.
This guide covers the published 0.1.0 adapter and Chat SDK 4.44.0.
The source and issue tracker are
maintained by Photon.
This replaces the retired
@photon-ai/chat-adapter-imessage adapter. It uses
createPhotonAdapter() and adapters.photon, not createiMessageAdapter()
and adapters.imessage. See Migrating from the iMessage adapter.Installation
Use Node.js 20 or later in a server-side application:Configuration
- Set up a Beta project and API key. Use a project
API key with
project:readandproject:writefor receiving messages and sending replies. - Connect the channels you want to use in the Beta dashboard. Start with the iMessage or email guide.
- Set these variables in your server’s environment or secret manager. For local
development, use a gitignored
.env.localfile:
.env.local
REDIS_URL, or replace it with your hosted Redis connection URL.
Never put keys, signing secrets, or Redis credentials in browser code or commit
them to source control.
Options passed to
createPhotonAdapter() override environment variables. The
optional userName option controls group mention matching; it defaults to the
Chat instance’s userName. REDIS_URL belongs to createRedisState(), not the
Photon adapter.
Add the adapter
Register the adapter asphoton. Direct messages reach onDirectMessage.
In groups, this example subscribes when someone mentions @mybot, then replies
to subsequent messages in that Space.
lib/bot.ts
Receiving messages
Choose a webhook for a public HTTPS backend, or WebSocket delivery for a process without a public URL. Both delivermessage.received
events to the same Chat SDK handlers.
Webhooks
Create a webhook destination pointing at your bot’s HTTPS route and subscribe tomessage.received. Save its signing
secret as PHOTON_WEBHOOK_SECRET in the server environment.
For example, in Next.js, with the @/ alias pointing at your application root:
app/api/webhooks/photon/route.ts
Request; do not parse or reserialize its body first.
bot.webhooks.photon initializes the bot and verifies the Standard Webhooks
headers: webhook-id, webhook-timestamp, and webhook-signature. Invalid or
expired signatures return 401; a missing signing secret returns 500.
Events other than message.received are acknowledged without invoking handlers.
On serverless hosts, pass the host’s background-task hook as waitUntil so
handlers can finish after the response. The 200 response acknowledges the
event, not successful completion of your handler or delivery of its reply.
WebSocket gateway
The gateway uses Photon’s Socket.IO event stream. It needs the project ID and API key, but no webhook destination or signing secret. Initialize the bot before starting the listener:gateway.ts
"type": "module":
Threads and direct messages
A thread represents a Photon Space and the Agent that received the message:photon:<spaceId>:<agentUserId>:<spaceKind>. Replies use that Agent, including
in a fresh webhook invocation. Direct Spaces are DMs; group Spaces use the
mention and subscription handlers.
To start a conversation, set PHOTON_AGENT_USER_ID to a connected Agent User and
pass an existing Photon User ID, not a phone number, to the adapter’s openDM:
bot.openDM() does not recognize
Photon User IDs. The adapter finds or creates the direct Space between the Agent and that User.
Use an Agent and recipient on the same platform; the platform’s messaging rules
still apply.
Feature support
Support depends on the connected platform. An unsupported operation raises Chat SDK’sNotImplementedError; typing is a no-op on platforms without it.
Reactions, edits, and deletions arrive as content inside
message.received;
they do not require separate webhook event subscriptions.
Migrating from the iMessage adapter
This is a new adapter and API, not a drop-in package rename. Keep the legacy guide for an existing Spectrum integration.
Create a Beta project, connect its channels, replace the credentials and webhook
destination, and review feature support before switching
traffic. Old thread IDs, subscriptions, and gateway cursors are not portable;
use a separate state store or namespace for the new bot.