Channels

iMessage

Give your agent a personal blue-bubble iMessage line for 1:1 conversations. Like email, iMessage needs no per-connection setup: one connect_imessage() call and your handler is answering texts from iPhones.

iMessage is a paid channel: it runs on Caspian's network (Apple has no public API, so the gateway owns the number via an AgentPhone relay). You need a one-time sign-in. See Authentication. First sign-in includes $100 in free credit.

How it works

The gateway owns the iMessage number, so there is nothing for you to provision: no tokens, no Apple developer account, no device to pair. You connect, get back a phone number, and hand it out. Inbound texts arrive at the same on_message handler as every other channel, and message.reply() texts back in the same conversation.

Connect

No arguments needed. The call returns a connection whose address is the iMessage number people text.

agent.py
from caspian_sdk import CommClient

client = CommClient()                       # reads COMM_API_KEY / COMM_BASE_URL

imessage = client.connect_imessage()        # provider: agentphone-imessage
print("iMessage number:", imessage["address"])

@client.on_message
def handle(message):
    # plain text only, no markdown on iMessage
    message.reply(f"You said: {message.text}")

client.listen()                             # one loop, every channel
agent.ts
import { CommClient } from "caspian-sdk";

const client = new CommClient();                  // reads COMM_API_KEY / COMM_BASE_URL

const imessage = await client.connectImessage();  // provider: agentphone-imessage
console.log("iMessage number:", imessage.address);

client.onMessage(async (message) => {
  // plain text only, no markdown on iMessage
  await message.reply(`You said: ${message.text}`);
});

await client.listen();                            // one loop, every channel

Verify it

Run your program, then text the printed number from an iPhone. Your handler fires and the reply lands back in the same thread within a few seconds.

!

This gateway shares one iMessage number, so it is one connection at a time. A 409 / "already connected" on connect_imessage() means another agent currently holds the line. Per-agent numbers are a follow-up.

Cold-initiate

iMessage supports starting a conversation with someone who never messaged first. Pass the connection id and the recipient's number:

client.initiate(imessage["id"], recipient="+15551234567", text="Hi, it's your agent. Anything you need?")
await client.initiate(imessage.id, "+15551234567", "Hi, it's your agent. Anything you need?");

Want your agent to reply the iMessage way automatically (plain text, casual, no markdown)? Pull the per-channel etiquette with behavior_prompt() / behaviorPrompt() and inject it into your system prompt. See Behavior guides.

Next steps

SDK reference →
Every method, Python and JS.
Authentication →
Sign in to unlock paid channels.
Channels overview →
What each channel needs.