iMessage Inbox
Text an agent on iMessage. It replies in the same chat with context kept.
Private beta. Not available via the API today.
client.bridges.provision()/bridges.createreturn403 feature_disabled. iMessage is paused for self-serve API developers; the flow below is documentation for the platform preview and will change. For production API use, trigger agents by email or webhook.
Branding. The hosted flow runs on a shared m8tes number. Dedicated numbers exist today, one per app or per end-user, and we provision the line with you: email sales@m8tes.ai.
Hosted Setup (Recommended)
m8tes hosts iMessage. No server to run:
- Provision a hosted connection. You get the m8tes number to text and a short link code.
- Each person texts the link code once to that number to link their phone.
- They text the number; the message triggers a run; the agent replies in the same chat.
from m8tes import M8tes
client = M8tes()
bridge = client.bridges.provision() # idempotent: returns the same bridge if it exists
print(bridge.m8tes_handle) # the number your team texts
print(bridge.link_code) # each person texts this once to link their phone
# Once people have linked their phones, list or unlink them:
for h in client.bridges.list_handles(bridge.id):
print(h.handle, h.verified_at)Everyone shares one m8tes number, so inbound is routed to your account by the sender's verified handle (that is what the link code establishes). Rotate the code with client.bridges.regenerate_link_code(bridge.id); unlink a phone with client.bridges.remove_handle(bridge.id, handle_id). provision() raises a 503 if the platform's central server is not configured.
Hosted iMessage links a handle to your account; it does not carry an end-user
user_id. For per-end-user channels in an embedded app, use email instead.
A dedicated number lifts that limit. It routes by number rather than by handle, so it can carry a user_id and give one app or one end-user its own line. Ask us to provision it.
Bind an Agent to a Chat
Give a specific agent one 1:1 chat by its chatGuid. Unbound inbound messages route to your account's Lead Mate instead.
bot = client.agents.create(
name="ops mate",
instructions="Handle requests sent over iMessage. Keep replies short.",
tools=["slack"],
inbound_imessage_enabled=True,
bridge_id=bridge.id,
imessage_chat_guid="iMessage;-;+15551231234", # a 1:1 chat (group chats are rejected)
allowed_imessage_senders=["+15551231234"], # required, fail-closed
)Allowed Senders
allowed_imessage_senders takes phone or email handles (formatting and case are normalized). Without a listed sender, inbound messages are silently dropped, so only listed handles can spend a run. Same allowlist model as every inbox channel: see Allowed Senders.
client.agents.update(bot.id, allowed_imessage_senders=["+15551231234", "you@icloud.com"])Conversation Continuity
Only 1:1 chats are supported. Binding a group chat is rejected so an agent never broadcasts replies to a group.
Multi-Tenant iMessage
Self-hosted bridges support user_id scoping per chat, following the shared model in Multi-Tenant Sender Scoping:
bot = client.agents.create(
name="inbox bot",
instructions="Handle this customer's iMessage requests",
inbound_imessage_enabled=True,
bridge_id=bridge.id,
imessage_chat_guid="iMessage;-;+15557654321",
allowed_imessage_senders=["+15557654321"],
user_id="alice_123",
)Advanced: bring your own BlueBubbles server
Run your own server (your own Apple ID and number) by registering a self-hosted bridge. A bridge is account-scoped and can serve many of your agents, each bound to a 1:1 chat.
Register a bridge
from m8tes import M8tes
client = M8tes()
bridge = client.bridges.create(
name="my mac",
server_url="https://my-bridge.example.com", # https, publicly reachable
password="bluebubbles-api-password", # stored encrypted, never returned
owner_handle="+15551231234", # your own iMessage handle (optional)
)
print(bridge.webhook_secret) # shown ONCE: set it as the BlueBubbles webhook secret now
print(bridge.connection_ok) # True if m8tes reached your server and the password workedConfigure the BlueBubbles webhook to POST new-message events to https://api.m8tes.ai/api/v1/webhooks/inbound/imessage with header X-Webhook-Secret: <webhook_secret>.
owner_handle lets you text your Lead Mate the moment the bridge is registered, with no allowlist edit. It is honored only on the default-agent path; an agent bound to a specific chat still uses its own allowlist.
Check the connection
result = client.bridges.test(bridge.id) # pings the server; sends no message
print(result["ok"], result.get("detail"))Run this if a bridge stops receiving or replying. It confirms the Mac is reachable and the password is still accepted.
Next: Email Inbox · Webhook Triggers · Memories & Documents