The Good Tech Companies - Your Convex Agent Can Send and Receive iMessage with Photon

Episode Date: September 2, 2026

This story was originally published on HackerNoon at: https://hackernoon.com/your-convex-agent-can-send-and-receive-imessage-with-photon. Add iMessage to a Convex AI age...nt with Photon. See durable webhooks, burst handling, cancellation, deduplication, and reliable outbound messaging in TypeScript. Check more stories related to undefined at: https://hackernoon.com/c/undefined. You can also check exclusive content about #ai-agents, #imessage, #photon-imessage-api, #serverless, #typescript, #convex, #photon-spectrum, #good-company, and more. This story was written by: @photonhq. Learn more about this writer by checking @photonhq's about page, and for more stories, please visit hackernoon.com. @spectrum-ts/convex lets a Convex backend send and receive iMessage through Photon without a separate long-running server. It persists verified webhooks before returning 200, handles message bursts and stale-reply cancellation, and sends responses through a paced, deduplicated outbox.

Transcript
Discussion (0)
Starting point is 00:00:00 This audio is presented by Hacker Noon, where anyone can learn anything about any technology. Your convex agent can send and receive iMessage with Photon by Photon. Convex developers can now add a durable iMessage inbox and outbox to an agent back end with, the new convex component for Photon Spectrum. The component receives Photon webhooks, writes each verified delivery to Convex before returning an HTTP 200, and hands everything after that to Convexas scheduler. Outbound messages move through a paced outbox to a photon sender running inside a convex node action. No separately hosted message loop.
Starting point is 00:00:37 No sidecar server just to keep alive. The component is now available on NPM and listed on convex components. What the component does handles the messaging pipeline that sits between photon and your agent, verified, durable webhook ingestion. The route verifies Photon's HMAC signature and persists the delivery before returning 200. An acknowledged inbound message is already in convex. Immediate or collapsed turns. Immediate mode handles every message separately.
Starting point is 00:01:05 Collapse mode lets a follow-up supersede an unfinished turn and carries its earlier messages into the next handler call. Cooperative cancellation. Convex cannot interrupt an action that is already running, so your handler checks after slow work and before it sends a reply. A paced outbox. Sends are queued in convex, spaced when needed, and delivered by an app-owned node action over Photon's GRPC transport.
Starting point is 00:01:30 Deduplication at the durable boundaries. Inbound redeliveries are deduped on the provider message ID. The Outbox uses a deterministic client GUID to avoid queuing the same logical send twice. The result is a messaging component built around convex's execution model instead of a long-lived process pretending to be serverless. Why this needed a convex component, the normal spectrum receive loop is intentionally long-lux. lived. That model works in a normal server process. It does not fit a convex HTTP action, which runs for a request and may be frozen as soon as the response returns. The usual webhook
Starting point is 00:02:06 shortcut has the same problem. Photons dispatches its handler after the HTTP response. On convex, work started after that response is not a safe durability boundary. So the component reverses the order. Persistence comes first. Once the delivery is acknowledged, the scheduler owns the remaining work. How collapse mode handles real conversations, people do not send one perfectly composed prompt. They send, greater than hey, greater than greater than, so I was thinking greater than greater than can you check xa naive agent starts three model calls and sends three replies. Collapse mode etrates that sequence as an evolving turn. If another message arrives before the previous reply ships, the new message supersedes that turn.
Starting point is 00:02:50 Messages already drained by the earlier handler return is context, and the new burst arrived. in. Your agent can answer the final intent without forgetting what came before it. Cancelation is cooperative. Convex's scheduler cannot stop an action that is already running, so the handler must recheck after the model call and before speaking. That check is what keeps a stale reply out of the conversation. Set it up. The component itself is one package. Cloud Sending also needs Photon's iMessage provider and its GRPC peers. The setup below is adapted from the repository's complete app at commit. The agent handler replaces its echo function with the integration point. One, register THE components set three variables in the convex dashboard. Variable purpose verifies the H-MAC
Starting point is 00:03:36 signature on inbound webhooks identifies the Spectrum Cloud Project authenticates the photon sender to. Configure the turn policy and sender is the default. Use it for commands, notifications, or other cases where every inbound message should produce its own handler call. Use when the reply is expensive or when answering each fragment would make the agent talk over Thyser. 3. Register the webhook route point the Spectrum Cloud Webhook at that route. 4. Run your agent once per settled turn as your agent logic. The component owns the turn life cycle around it. 5. Add the photon sender the component stores and schedules outbound work. A node action in your app performs the GRPC call. The Spectrum runtime is cached once per
Starting point is 00:04:19 convex node container. So Warm sends do not rebuild the connection every time. Six, make the GRPC Peers available TO Convex add the dynamically loaded peers to. Convex installs an external package only when the bundle contains a static reference to it. The GRPC packages are optional peers loaded dynamically, so add this small bundling shim. Nothing imports this file. Its job is to make the peer dependencies visible to the convex bundler. That is the complete path. Component state and scheduling inside convex, with the provider call performed by a convex node action. There is no separate railway or render process to operate. What is guaranteed and what is not. The component draws a deliberate boundary around
Starting point is 00:05:04 reliability. A correctly signed inbound delivery is durable before the webhook returns 200. Redeliveries with the same provider message ID do not create another inbound row or handler call. The outbox does not enqueue the same logical send twice for the same chain and sequence. A failed sender result is recorded and retried with backoff. Read receipts and typing indicators do not start agent turns. There is one important outbound caveat. The deterministic de-duplicates the convex outbox, but Photon does not currently accept that caller supplied key asked provider requests ID impotency key. If a send reaches the provider and its acknowledgement is lost, a retry can still post twice. Closing that last GIP requires the key to pass through the SDK. That distinction
Starting point is 00:05:50 matters. Inbound persistence, inbound deduplication, outbox deduplication, and provider-level ID impotency are four different guarantees. Current limitations. The first release is intentionally narrow. The durable outbox currently reconstructs text and markdown. Attachments, polls, and other rich content need adjacent to builder mapping or a public SDK path for replaying resolved content. Replies, reactions, and red receipts require an extra message lookup because the public spectrum API addresses A, not only a message ID. The sender's external packages are not installed by Convex's anonymous local back end. Use a cloud development deployment to test sends is an iMessage component. Photon can provide SMS, RCS fallback on the iMessage delivery path, but that is not
Starting point is 00:06:39 the same as installing standalone RCS and SMS providers in this component. The repository's verification covers signed and forged webhooks, durable ingest, redelivery deduplication, collapsed bursts, handler dispatch, outbox queuing, retries, and a successful authenticated GRPC request to Spectrum Cloud. The published transport test used a reserved fictional target and stopped Atfodin's target policy validation, so that test does not claim physical phone delivery. These are not footnotes. They are the current contract. How we verified this release. This article describes NPM package version and source commit, verified on August 26, 26. We cloned that commit into a clean temporary directory and Ronte repository's own install
Starting point is 00:07:25 and validation commands with node and NPM. Check result completed. The packages prepare build passed 45 of 45 tests passed across four test files passed for the package and typescript build past biome checked 28 files. No fixes applied the install also reported 13 moderate severity findings in the dependency audit summary. We did not treat a successful build as evidence that those transitive findings are resolved. You can reproduce the same source-level checks. These checks verify the components tested behavior, types, build, and static analysis. They are not a comparative benchmark against another messaging provider, and they do not prove delivery to a physical phone. The transport test boundary is described in the limitations above,
Starting point is 00:08:08 so the evidence does not overstate what was observed. What this means for convex developers? Before this component, using Spectrum's ordinary receive loop with convex miente operating a separate long-running process or rebuilding the delivery pipeline around convex yourself. Now the durable state lives where the application state already lives. Webhook ingestion is a convex HTTP route. Messages in outbox rows are convex data. Turn handling runs through convex's scheduler. Your model call runs in a convex action. Photon delivery runs in a convex node action. You still own the agent. You still choose the model, tools, memory, and turn policy. The component owns the messaging state machine around it. Why we built
Starting point is 00:08:52 this, Photon's goal is to give agents a native presence in the places people already talk, starting with a phone number. That only works if messaging fits the backend developers are already using. A channel integration should not force a convex team to deploy a second server, rebuild webhook durability, or write its own burst cancellation state machine before the agent can answer one message. Is what first-class messaging looks like inside convex. Durable inbound state, explicit turn semantics, an outbox, and a narrow provider boundary. Convex is already a back-end developers love. Now it can receive a text, run an agent, and send the answer back. Get started. Install on NPM, then use the complete example in the source repository linked above.
Starting point is 00:09:37 Build an agent people can text. Related reading. Give your Mastra agent an iMessage number. Using Photon, add hosted iMessage to a Mostra agent with Photon Spectrum. The iMessage adapter for Vercel Chad SDK. Bring native iMessage behavior into a chat SDK agent. How we rebuilt our shared iMessage routing to handle 10M plus messages a day. The durable routing and event delivery architecture behind Photon. P.S. shout out to our good friend at Wayne Sutton at Convex for making this happen with us. About Photon, Photon is a unified API that brings agents to interfaunch.
Starting point is 00:10:12 like iMessage, WhatsApp, Telegram, Slack, and more. It is free to start, and it scales as your agent grows. Follow Photon X, Twitter, LinkedIn, GitHub, Discord, Instagram, start building with Photon View pricing. Contact the Photon team. Thank you for listening to this Hackernoon story, read by artificial intelligence. Visit hackernoon.com to read, write, learn and publish.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.