Skip to content
Guides8 min read

iMessage Apps vs. iMessage Bots: When You Need a Messages Extension

An iMessage app is a Messages extension people install; an iMessage bot is an agent on a number. Here's how they differ and when you need both.

Grainy film still of four white houses along a green hilltop at dusk, a figure in a blue cloak climbing the steps toward them, with the words "iMessage apps vs. iMessage bots"

Short answer: An iMessage app is a Messages extension that runs inside Messages and gives people stickers, cards or a small interface in a thread, while an iMessage bot is an agent on a phone number that reads texts and replies from a server. You need both when the conversation needs a screen, such as a calendar, a form or a Face ID approval, and on Keiki the agent sends that screen as a card in the Keiki Vault iMessage app, so you don't ship your own extension.

A customer texts your cleaning company: "Can you come Thursday instead?" Your agent checks the calendar and finds six open slots across three days. It could list all six in a text bubble and ask the customer to type one back. Or it could send a small calendar the customer taps, right inside the thread.

That second option is where teams start asking whether they need "an iMessage app". The phrase means two different things. Sometimes people mean an iMessage bot, an agent that answers texts. Sometimes they mean an iMessage app in Apple's sense, a Messages extension installed from the App Store. They are built differently, run in different places and solve different problems.

This guide covers:

  • What an iMessage app (Messages extension) is
  • What an iMessage bot is, and why Apple's framework doesn't give you one
  • How the two compare side by side
  • When you need both, and how Keiki gives an agent an iMessage app without you building one

It's part of Building iMessage agents, our complete guide. If you want the options for getting an agent onto iMessage at all, start with what the iMessage API does and doesn't offer.

What an iMessage app is

An iMessage app is an extension that runs inside the Messages app on an iPhone or iPad. Apple opened Messages to developers in iOS 10. Its June 13, 2016 iOS 10 announcement said the release "brings the power of the App Store to Messages", with stickers, payments and scheduling as early examples.

You build one with Apple's Messages framework, which Apple describes as a way to "create app extensions that allow users to send text, stickers, media files, and interactive messages." The extension's main screen is a subclass of MSMessagesAppViewController, and it can show:

  • A compact view below the transcript, about the height of the keyboard.
  • An expanded view that fills most of the window.
  • A live bubble in the transcript, drawn by your extension through MSMessageLiveLayout.

Apple's design guidance for iMessage apps frames them as tools for a conversation in progress: sharing a shopping list or a trip itinerary, or a simple shared task, like deciding where to eat.

Three facts about iMessage apps matter for anyone building an agent:

  1. The person installs it. An iMessage app ships through the App Store, alone or inside your iOS app. Apple's live layout docs say you need an alternative layout for devices that don't have your app installed, or that can't run iMessage apps at all, such as SMS devices.
  2. It runs on the phone. Its code runs on the device of the person using it, against the conversation they have open.
  3. The person acts first. Someone opens your app from the app drawer or taps a message your app made. Nothing in the framework lets your server read the thread or text someone on its own.

So an iMessage app is interface. It isn't a bot.

What an iMessage bot is

An iMessage bot, or iMessage agent, is software on the other end of the conversation. A customer texts a number, the message reaches a server, a model decides what to do and calls your tools, and a reply comes back as a blue bubble. Nobody installs anything.

Apple doesn't publish an API for sending and receiving iMessages from an ordinary phone number on a server. Its official business channel is Apple Messages for Business, where your company registers a business account and connects through an Apple-approved Messaging Service Provider. That works well for brands built around customer support. It doesn't give you an agent on a phone number that people text like a friend.

That gap is why agents run on hosted iMessage lines. How to run an iMessage agent without a Mac explains how that works, and the iMessage API guide compares the routes.

iMessage app vs. iMessage bot at a glance

iMessage app (Messages extension)iMessage bot (agent on a number)
What it isAn extension inside MessagesA server that reads and sends texts
Where the code runsOn the recipient's iPhone or iPadOn your server or a platform
How people get itInstall from the App StoreText a phone number
Who startsThe person, from the app drawer or a bubbleEither side, in a normal thread
What it's good atTaps, forms, pickers, stickers, live bubblesQuestions, decisions, follow-ups, calling your APIs
What you buildA native iOS extension, plus App ReviewInstructions, tools and a line

An iMessage app has a screen but no voice. A bot has a voice but only text, images and links.

When you need both

Most of the time, an agent on a number is enough. Text handles questions, status checks, simple choices and handoffs. For answers with several parts, an agent can send a swipeable stack of images instead of a wall of text, which is how carousels work, using rich cards.

You need a screen when the person has to do something text does badly:

  • Choose from a lot of options. Times across a week, seats on a plane, sizes and colors.
  • Fill in a form. An address with validation, a booking with several fields, a support ticket with a photo.
  • Review before committing. An order summary, a quote or a contract with line items.
  • Approve something risky. A payment or a cancellation where a typed "yes" isn't proof enough.

In each case the conversation still matters. The agent works out what the customer needs, prepares the page, sends it at the right moment and picks up again after the tap. The bot decides when; the app gives the customer the screen.

Building that pair yourself means two products: an agent on a line, and a native Messages extension your customers install, submitted through App Review and kept current with iOS. The agent also has to know whether each customer has the extension, and fall back when they don't.

How Keiki gives an agent an iMessage app

Keiki runs the agent and ships the iMessage app. Keiki Vault is Keiki's own iOS app with a Messages extension, published on the App Store by Zero Email, Inc. Every agent on Keiki uses the same app, so there's no per-agent build and nothing to submit to Apple. Your customer installs it once.

The extension opens two kinds of cards, both described in the Keiki Vault docs:

  • Presentation cards load your HTTPS page in a web view inside Messages.
  • Approval cards show Approve and Decline, both behind Face ID, before a gated tool runs.

Turn on Dynamic UI

Presentation cards need the Dynamic UI add-on, under Abilities in the agent form. They are sent only from a dedicated iMessage line bought through Keiki, in a one-to-one conversation. Imported, shared and pool lines, group chats and other channels don't get cards. The full rules are in the iMessage Apps docs.

Return a presentation from a tool

Any tool that isn't a Keiki builtin, whether a webhook, code, capability or MCP tool, can ask for a card by returning a presentation beside its normal result. With the TypeScript SDK:

TypeScript
// src/tools.ts
import { Effect, Schema } from 'effect'
import { defineTool } from '@onkeiki/agents'

export const reviewBooking = defineTool({
  name: 'review_booking',
  description: 'Prepare a rebooking for the customer to review. Returns a review page URL.',
  input: Schema.Struct({ bookingId: Schema.String }),
  policy: { requiredScopes: ['bookings:write'] },
  execute: (input, ctx) =>
    Effect.promise(async () => {
      const res = await fetch('https://api.acme.com/rebookings', {
        method: 'POST',
        headers: {
          Authorization: 'Bearer ' + process.env.ACME_API_KEY,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ phone: ctx.phone, bookingId: input.bookingId }),
      })
      const draft = (await res.json()) as { id: string; url: string }
      return {
        status: 'ready',
        url: draft.url,
        presentation: {
          type: 'app',
          id: 'rebooking-' + draft.id,
          url: draft.url,
          caption: 'Pick a new time',
          subcaption: 'Tap a slot to confirm',
        },
      }
    }),
})

The id names the card. The same tool, id and url in one conversation send once, so a retry doesn't send a second bubble. Keiki adds presentationDelivery to the result the model reads, with a state of accepted, unavailable, failed or unknown. Keep url in the result, so the agent can send it as a normal link whenever the card isn't accepted. The agent can also send a card directly with the imessage_send_app builtin.

Build the page for a card

The page is an ordinary web page, which makes it much faster to change than an App Store build. A few rules from the docs:

  • Keep the whole flow on one origin. Same-origin links load in the card; a link to another origin opens outside Messages, so a sign-in or payment step on another domain leaves the card.
  • Keep live off for anything interactive. live: true draws the page in the transcript bubble, and transcript views don't take taps.
  • Don't treat opening as approval. Opening a card isn't an approval. Your page still authorizes whatever the customer does there. For tools that need a decision, set approval: 'ask' and Keiki sends its own Face ID card. See governed actions.

Send cards only after the customer has replied at least once. A plain-text first message is one of the iMessage best practices that keep a line in good standing, and links preview properly once the conversation is established.

When to build your own Messages extension anyway

Keiki Vault covers web cards and approvals for agents. Build your own extension when the extension itself is the product: sticker packs, games played turn by turn in a thread, features for group chats, your own icon in the app drawer, or native device features beyond a web view. Expect to go through App Review, keep an alternative layout for people without your app, and plan for customers who never install it.

If what you need is an agent that sometimes hands the customer a screen, start with the agent. Add cards when a text reply stops being enough.

FAQ

Is an iMessage app the same as an iMessage bot? No. An iMessage app is a Messages extension people install from the App Store that runs on their iPhone or iPad. An iMessage bot is an agent on a phone number that receives texts on a server and replies. One adds interface to a conversation; the other takes part in it.

Can a Messages framework app extension work as a bot without a public server API? Not on its own. The Messages framework runs your extension on the recipient's device and acts in the conversation they have open, so it can't receive texts on your server or start a conversation. To answer texts you need an agent on an iMessage line, and Apple doesn't publish a server API for that from an ordinary number.

What are iMessage apps used for? Stickers, games, shared lists, payments, scheduling and other small interfaces inside a thread. For an agent, the useful part is a card the customer taps to pick a time, review an order or approve an action without leaving Messages.

Is there an iMessage API for bots? Apple offers Apple Messages for Business, which connects a registered business account through an Apple-approved Messaging Service Provider. For an agent on a regular phone number, teams use a hosted line. Our iMessage API guide compares the options.

Do my customers need to install anything to get cards from a Keiki agent? Yes, once. The first time, they install Keiki Vault from the App Store, and after that every Keiki agent's cards open in it. On a line or channel that can't carry cards, nothing is sent, and the agent can share the page as a normal link instead.

Sources