spectrum-ts: a TypeScript framework for putting agents on iMessage, SMS and email
Bring agents to any interfaces
At a glance
- What is it?
- Spectrum is Photon's open-source multi-channel agent runtime. It gives a TypeScript app a single message stream across iMessage, Slack, Telegram and other surfaces, and this review covers how it installs, where it stops, and who should skip it.
- Who is it for?
- Adopt spectrum-ts if you are already writing a TypeScript agent and the hard part for you is the transport layer: getting one message loop that works over iMessage, Slack, Telegram and email rather than a bespoke webhook handler per surface.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem spectrum-ts solves, and the developers it is aimed at
Most agent frameworks assume the conversation happens in a web widget the developer controls. That assumption breaks the moment a user wants to reach the agent from the messaging app already open on their phone. Each surface has its own delivery model, its own notion of a thread, and its own way of telling you that a message arrived. Photon's README frames Spectrum as the answer to exactly that: "Bring agents to any interface," with the explicit goal of reaching people over "iMessage, SMS, and email instead of trapping them in web chat."
The intended reader is a TypeScript developer who already has an agent and does not want to write four webhook handlers. The framework's pitch is that the channel is a provider you configure, not a subsystem you build. The repository is a Bun workspace with a packages directory, a docs directory and an examples directory, and the published artifact is the npm package spectrum-ts. If your agent is written in Python, nothing here applies to you directly.
One message stream over many providers
The mechanism visible in the README is an async iterator. You construct a Spectrum app with credentials and a list of providers, then consume app.messages with a for-await loop. Each iteration yields a pair: a space and a message. The space is the conversation context, and it exposes a responding method that wraps your reply so the framework knows the agent is handling that turn. That is the whole data flow as documented: provider receives an inbound event, the runtime normalizes it into a space and a message, your loop decides what to do, and space.responding sends the outbound reply back through the same provider.
The provider list is where the channel abstraction lives. The README's platform table maps each surface to a package: @spectrum-ts/imessage, @spectrum-ts/imessage-local, @spectrum-ts/whatsapp-business, @spectrum-ts/telegram, @spectrum-ts/slack and @spectrum-ts/terminal. Anything not on that list is expected to go through definePlatform, which the README exports from spectrum-ts and describes as the way to build your own platform provider. The import path convention is spectrum-ts/providers/<platform>, and the README states that if the matching provider package is not installed, the import fails at build or startup with an error naming the exact package to add. That is a deliberate design choice: the runtime does not silently degrade when a channel is missing.
Installing spectrum-ts and getting a first reply
The README gives one install command for the batteries-included path. It uses Bun, and the repository's package.json pins packageManager to [email protected], so the toolchain expectation is explicit rather than implied.
bun add spectrum-tsBefore any code runs you need credentials. The README directs you to sign up at app.photon.codes to obtain a project ID and a secret, which the example reads from the environment as PROJECT_ID and PROJECT_SECRET. Export both before starting the process.
The minimal app is a single file. It registers the iMessage provider and replies to every inbound message with a fixed string. Note the import path for the provider, which is separate from the main package import.
import { Spectrum } from "spectrum-ts";
import { imessage } from "spectrum-ts/providers/imessage";
const app = await Spectrum({
projectId: process.env.PROJECT_ID,
projectSecret: process.env.PROJECT_SECRET,
providers: [imessage.config()],
});
for await (const [space, message] of app.messages) {
await space.responding(async () => {
await message.reply("Hello from Spectrum.");
});
}What you should see is an inbound message on the connected iMessage surface and the agent's reply arriving in the same thread. If the provider package is absent, the import fails at startup rather than at the first message, which makes the failure obvious.
The README also documents a smaller install for people who do not want the full provider set: depend on the runtime plus only the providers you use, for example bun add @spectrum-ts/core @spectrum-ts/telegram, and import from the scoped packages directly. Local iMessage is called out as an explicit install through @spectrum-ts/imessage-local rather than being bundled, and the README says that package connects to a local iMessage database for a standalone setup.
Where spectrum-ts stops being the right tool
The provider table is the boundary. If your product needs a channel that is not iMessage, local iMessage, WhatsApp Business, Telegram, Slack or Terminal, you are writing a definePlatform implementation yourself, and the README does not describe how much work that is. Treat the custom-provider path as undocumented until you have read docs.photon.codes.
The second constraint is the runtime. The workspace pins Bun 1.3.14, and every install example in the README uses bun add. Nothing in the README says the SDK runs on Node.js, so a Node-only team is taking on an unverified assumption. That is not a small detail for a library that sits in the request path of a live messaging integration.
The third is hosting. The README's own framing is that the fastest way to ship is Spectrum Cloud, with credentials ready in minutes, and that the standalone path is covered in the docs rather than in the README. If your constraint is that message traffic must not leave your infrastructure, the README alone does not tell you what the self-hosted setup involves. The local iMessage package is the one concrete self-hosted option named, and it is iMessage-specific.
How spectrum-ts differs from a general agent framework
A general-purpose agent framework such as LangChain or the Vercel AI SDK starts from the model call and treats the interface as an afterthought: you get a chat abstraction and you wire your own transport. Spectrum starts from the opposite end. There is no model abstraction in the README at all. What you get is a normalized inbound stream and a set of packaged transports, with the reply path handled by space.responding. Your agent logic is whatever you put inside that callback.
That inversion is the whole comparison. With a general framework you own the channel code and the framework owns the prompt orchestration. With spectrum-ts you own the orchestration and the framework owns the channel code, including the credential handshake against Photon's cloud for the hosted providers. If your agent already lives inside another framework, the two are not mutually exclusive in principle, since the Spectrum loop is just an async iterator you can call into, but the README does not document an integration with any specific framework, so that would be your own glue.
Maintenance, versioning and the MIT licence
The last push to the default branch was on 2026-09-09, and the most recent release is v12.9.0 from 2026-09-08, following v12.8.0 on 2026-08-20 and v12.7.0 on 2026-07-31. The repository is not archived. The release cadence across those three versions is roughly three weeks apart, and the major version number is already in the double digits, which tells you the project has been through a lot of breaking changes over its life. Pin your version and read the release notes before upgrading rather than tracking the latest tag.
The repository carries renovate.json, which indicates dependency updates are automated, and the root scripts run through turbo with separate test:node and test:bun targets, so both runtimes are exercised in CI even though the install path shown to users is Bun-only. The licence is MIT, per the LICENSE file and the npm badge in the README. MIT is permissive: you can use the package commercially and modify it. It also means the project offers no warranty, and the README says nothing about support terms for the hosted cloud, which is a separate commercial relationship from the open-source code.
Editorial conclusion
Adopt spectrum-ts if you are already writing a TypeScript agent and the hard part for you is the transport layer: getting one message loop that works over iMessage, Slack, Telegram and email rather than a bespoke webhook handler per surface. Do not adopt it if you need a channel outside the documented provider set, if you cannot run Bun 1.3.14 or newer, or if you want to avoid Photon's cloud entirely, since the fastest path starts at app.photon.codes and the self-hosted route is documented only at docs.photon.codes. Before you commit, verify three things in order: that your target platform has a provider package listed in the README table, that you can supply projectId and projectSecret or a local iMessage database, and that your runtime matches the packageManager field in the repository's package.json. If those three hold, the adoption cost is an afternoon; if any one fails, the framework is the wrong layer for the problem.
Frequently asked questions
What is spectrum-ts used for?
It is Photon's multi-channel agent framework for TypeScript. The README describes it as a way to make AI agents reachable over real conversation surfaces like iMessage, SMS and email instead of confining them to web chat.
How do I install spectrum-ts?
The README's install command is bun add spectrum-ts, which pulls in the runtime plus the standard provider set. For a smaller install you can depend on @spectrum-ts/core plus only the providers you use, such as @spectrum-ts/telegram.
Which platforms does spectrum-ts support?
The README lists iMessage, local iMessage, WhatsApp Business, Telegram, Slack and Terminal, each as its own package. Anything else goes through definePlatform, which the README exports from spectrum-ts for building a custom platform provider.
Does spectrum-ts require Photon Cloud?
No. The README says Spectrum also runs fully standalone, and names @spectrum-ts/imessage-local for connecting to a local iMessage database, with self-hosted setups covered at docs.photon.codes. The cloud path is presented as the fastest way to ship, not the only one.
What happens if a provider package is not installed?
The README states that the spectrum-ts/providers/<platform> import paths work as long as the matching provider package is installed, and that if it is not, the import fails at build or startup naming the exact package to add.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/photon-hq-spectrum-ts)