Caspian ships one handler for many channels, and its own quickstart still calls the class it retired
Agent communication SDK. The open-source agent communication layer for AI agents — email, WhatsApp, Slack, Discord, Telegram, SMS. Python & TypeScript.
At a glance
- What is it?
- Caspian is an AGPL-3.0 communication SDK in Python and TypeScript that puts email, Slack, Discord, Telegram, WhatsApp and more behind a single channels.add() call, with either a hosted gateway or a self-hosted process on the inbound path. The version story, the deployment config and the two language surfaces disagree with each other in ways worth reading before you integrate.
- Who is it for?
- Caspian is worth a look if your agent has to talk to people across several channels and you would rather not maintain four auth flows and four retry paths yourself. Before you integrate, pin an exact release, because the README describes a 1.0 rewrite while the newest tag is v0.1.2 and the workspace manifest reads 0.1.0.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 39 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A 1.0 rewrite is announced, but the newest tag is v0.1.2
Version 1.0 is described as a full rewrite, with the public surface renamed from `CommClient` in the 0.6.x line to `Caspian`, and a migration anchor pointing at a section named for 0.6.x. The release history tells a different story. One tag exists, v0.1.2, dated 2026-07-21 and annotated as an open core launch, with nothing above it. The workspace manifest agrees with the tag and not with the prose: `pyproject.toml` declares `name = "caspian-sdk-workspace"` at `version = "0.1.0"`, with `package = false` under the uv table, so that number governs the workspace rather than a published artifact. Three version stories are therefore in play at once: 0.1.0 in the manifest, 0.1.2 in the tag list, and 1.0 in the page. Pin an exact release before relying on the rename, because the class name in your first line of code is precisely the thing that moved.
The gateway quickstart still instantiates the class the rewrite retired
The self-hosting instructions live in `docker-compose.yml`, and the header comment there tells you to point the SDK at the local gateway using the old name. It gives the arguments verbatim: `CommClient(base_url="http://localhost:8000", api_key="comm_dev_key_change_me")`, against a server bound to `COMM_HOST: 0.0.0.0`. That is the class the front page says was replaced, with a 0.6.x-era constructor signature, sitting in the first file a new user opens to self-host. The naming does not stop at one line either. The server package is still `server/src/comm_gateway/`, its settings object is `comm_gateway.config.Settings`, and the environment prefix throughout `.env.example` is `COMM_`. The gateway is the product's own service and it kept the old name end to end.
The API key has one name in the quickstart and another in the config template
The hosted example constructs the client with `Caspian(api_key="...")` and attaches a trailing comment naming `CASPIAN_API_KEY` in a `.env` file. The env template that actually ships says something else. Its header states that adapter configuration is read by `comm_gateway.config.Settings` under the prefix `COMM_`, and under the heading covering the SDK and CLI it carries two commented keys, `COMM_BASE_URL` and `COMM_API_KEY`. A deployment configured from the template therefore names its gateway address and its secret with a different prefix than the quickstart tells you to use, and nothing in the tree reconciles the two. There is a second split alongside it. The template states that per-connection credentials, a bot token or a page token, are supplied at connect time rather than there, and that the file holds deployment-level adapter knobs only. So the gateway secret and the channel tokens travel by two different routes depending on which one you are setting.
docker compose up runs a fixed bootstrap key against a caspian/caspian database
The compose file is arranged so the stack comes up with no credentials at all. `COMM_PROVIDERS` defaults to `fake`, described in the header as an in-memory provider needing none, and `COMM_BOOTSTRAP_API_KEY` falls back to the literal string `comm_dev_key_change_me`. The database service is no tighter: `POSTGRES_USER`, `POSTGRES_PASSWORD` and `POSTGRES_DB` are all set to `caspian`. The port mapping publishes `8000:8000` and `COMM_HOST` is `0.0.0.0`, so the gateway listens on every interface. The `env_file` block that would load your own `.env` is present but commented out, which means a fresh `docker compose up` runs entirely on those defaults until you uncomment it and fill in `COMM_PROVIDERS` along with that channel's credentials. Convenient for a first run against a fake provider, and worth changing before the gateway is reachable by anything other than you.
Python and TypeScript spell the same inbound contract two different ways
The TypeScript block is introduced as the same contract. The shapes are close but not identical. Inbound for a self-hosted channel is `results = cx.handle("telegram", request_body, request_headers)` in Python, where the call takes a channel name plus a body and a header mapping, and it is `cx.webhooks.telegram(req)` in TypeScript, where the channel is baked into a per-channel property and the argument is a request object. Channel registration agrees on `via` and little else: Python takes keyword arguments `bot_token` and `webhook_url`, TypeScript takes a single object with `botToken` and `webhookUrl`. The handler decorator accepts a rules dictionary in both languages, but the TypeScript callback is handed two parameters where the Python one takes three, the third being a context object. Moving between the two is mechanical, but it is still a mapping rather than an identity.
The manifest floor is Python 3.10 while the linter targets 3.12
`pyproject.toml` requires Python 3.10 or newer, and the uv workspace has exactly one member, `packages/python`, with tests under `packages/python/tests`. The ruff configuration in the same file sets `target-version = "py312"`, two feature releases above the declared floor, and the gap is handled rather than ignored. A per-file exemption exists for `packages/python/src/caspian/_compat.py`, listing `UP036` and `UP042`, with a comment saying the version block is the point: ruff targets py312 but the SDK supports 3.10, where `enum.StrEnum` does not exist. The practical shape is a compatibility module that backfills the newer syntax, plus a lint exemption so the backfill does not trip rules meant for current code. Line length is set to 100, and two files are exempted from it because their long lines are guide prose and an inline auth page rather than code.
The config file warns that automating a personal account can cost the account
One provider block in `.env.example` is labelled `ToS-GRAY` and states that automating a personal account risks the account, requiring explicit opt-in configuration and pointing at the README channel notes first. It configures a Telegram user-account provider over MTProto through `COMM_TELEGRAM_USER_SESSION`, `COMM_TELEGRAM_API_ID` and `COMM_TELEGRAM_API_HASH`, kept separate from the Bot API provider above it. The contrast between the two blocks is the useful part. The Bot API provider takes only a webhook base in deployment config, because the developer supplies their own BotFather token at connect time. The user-account provider has nothing to bring, so it asks for session material and an API id and hash, which is the shape of code that operates an account rather than a bot. Note also the packaging split: this block says to install the extra `caspian-adapters[telegram-user]`, while the front page gives the Discord socket extra as `caspian-sdk[discord]`, so extras are named under two different distributions.
The fastest documented setup is a markdown file fetched from the vendor's API host
The quickest route to an integration offered here is not a package manager. You paste two lines into a coding agent, one of which is a URL, and the instruction is to read that guide end to end and carry out the whole integration. The guide lives at `api.trycaspianai.com/SKILL.md`, and the page insists it is always current. Nothing in the tree pins that document, so the instructions your agent follows can change independently of the version you installed, and the setup path offers no way to diff one against `pip install caspian-sdk`. The same page carries the positioning numbers: the largest open source agent frameworks each maintain 25 or more channel adapters and still spend 8 to 15 percent of their issue trackers on channel plumbing, 42 open source agent projects were measured before the code was written, and the alternative side of that comparison is around 1,500 lines before an agent says a word. Those figures carry the argument, and no table or dataset for them appears in the repository.
pip install caspian-sdk # Python 3.10+
npm install caspian-sdk # TypeScript / Node 18+ / BunThe rewrite ships its own CLI in `packages/cli`, written in TypeScript and run with Bun, described as a thin client of the same surface. Init mints a key into `~/.caspian/.env` or a project `.env`, and the channel and call commands mirror the SDK.
caspian init # mint a key → ~/.caspian/.env or project .env
caspian channels add telegram
caspian channels add telegram --via self-host --bot-token "$TG" \
--webhook-url https://myapp.example.com/hook
caspian call post --thread telegram:123:456 --text "shipping now"
caspian threads tail telegram:123:456Editorial conclusion
Caspian is worth a look if your agent has to talk to people across several channels and you would rather not maintain four auth flows and four retry paths yourself. Before you integrate, pin an exact release, because the README describes a 1.0 rewrite while the newest tag is v0.1.2 and the workspace manifest reads 0.1.0. Self-hosting needs its environment variable names settled in advance, since the quickstart and the shipped template disagree on the prefix. Change the bootstrap key and the database password before anything but localhost can reach the gateway, and read the terms-of-service note on the user-account provider before enabling it.
Frequently asked questions
Which channels does the Caspian repository have examples for?
The `examples/` directory holds discord, email, imessage, linear, messenger, slack, sms, telegram, telegram-ts, voice, whatsapp and x, plus a `serve.py`. The intro sentence names Slack, Discord, Telegram, email, WhatsApp, X and Linear, so imessage, messenger, voice and sms appear as examples without appearing in that list.
How many releases does Caspian have?
One tag is listed: v0.1.2 on 2026-07-21, annotated as an open core launch, even though the README describes version 1.0 as a full rewrite. The last push on the default branch is 2026-08-25.
Can Caspian receive messages without the hosted gateway?
Yes. `via="self-host"` puts your process and your tokens in charge with no gateway polling, and inbound arrives through `cx.handle("telegram", request_body, request_headers)`. Discord and Slack can instead hold a socket open with `cx.listen("discord")`, which needs the optional extra `caspian-sdk[discord]`.
What license does Caspian use, and is it open source?
The repository is AGPL-3.0. Its own summary calls it the open-source agent communication layer for AI agents, while the single release tag is annotated as an open core launch, and no statement in the page says where that boundary falls.
What does the Caspian CLI do beyond the SDK?
It is a thin client in `packages/cli` on TypeScript with Bun. `caspian init` mints a key into `~/.caspian/.env` or a project `.env`, `caspian channels add` registers a channel with the same self-host flags as the SDK, and `caspian call post` and `caspian threads tail` address a thread as `telegram:123:456`.
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/trycaspian-caspian-sdk)