iMessage paid
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.
- Plain text only: iMessage has no markdown. Send unformatted text; skip bold, headings, and code fences in your replies.
- Personal 1:1 messaging: this is a direct blue-bubble line to one person at a time, not a group or broadcast channel.
- Cold-initiate supported: unlike WhatsApp, your agent can text a number that never messaged it first, via
initiate().
Connect
No arguments needed. The call returns a connection whose address is the iMessage number people text.
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 channelimport { 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 channelVerify 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.