Skip to documentation
Documentation

iMessage Apps

Open HTTPS web pages as iMessage app cards from agent tools.

Tools can open an HTTPS web page as an iMessage app card in a direct conversation. These are not Apple App Clips: no iOS app is needed.

Turn it on

In the agent form, enable iMessage Apps in the Abilities group. New agents start with the add-on off. Agents already on an active dedicated line bought through Keiki had it switched on automatically.

You can also enable it through the developer API. A key bound to an agent can patch that agent directly; an organization-wide key includes agent_id:

Shell
curl -X PATCH -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "<agent-id>", "features": {"imessageApps": true}}' \
  https://<your-host>/api/v1/developer/config

Requirements

The agent must have an active dedicated iMessage line bought through Keiki and be replying in a direct iMessage conversation. Imported lines and shared or pool lines are not eligible. Cards are not sent in group conversations, on other channels, or during held-back, steered or detached turns.

Send a card

Use imessage_send_app

When the add-on is enabled, the imessage_send_app builtin is available. Call it with an absolute HTTPS url and an optional live boolean:

JSON
{ "url": "https://your-app.example/review/123", "live": true }

The builtin maps delivery results like this:

Delivery stateTool result
accepted{ "success": true, "message_id": "…" }
unavailablesuccess: false with the unavailable reason as the error.
failedsuccess: false with a send-failed error.
unknownsuccess: false; the error says the card may have been delivered. Do not retry automatically.

Return a presentation from a tool

Any non-builtin tool can request a card by returning a presentation object. This works for webhook, code, capability and MCP tools:

JSON
{
  "status": "confirmation_required",
  "url": "https://your-app.example/review/123",
  "presentation": {
    "type": "app",
    "id": "review-123",
    "url": "https://your-app.example/review/123",
    "live": true,
    "caption": "Review this change",
    "subcaption": "Open the details"
  }
}

The presentation fields are:

FieldRequirement
typeMust be "app".
idRequired stable intent ID, 1–128 characters. The same tool, ID and URL in one conversation reuse the delivery; use a new ID for a new card.
urlRequired absolute HTTPS URL, at most 2,048 characters, without embedded credentials.
liveOptional boolean.
captionOptional string, 1–60 characters.
subcaptionOptional string, 1–80 characters.

Keiki adds presentationDelivery to the tool result:

JSON
{
  "presentationDelivery": {
    "state": "accepted",
    "messageId": "<provider-message-id>"
  }
}

The state is one of:

StateMeaning
acceptedThe provider accepted the card; this does not mean the recipient opened it.
unavailableThe card could not be sent. reason is addon_disabled, invalid_presentation, unsupported_channel or line_not_eligible.
failedDelivery failed before acceptance.
unknownThe outcome is uncertain; the card may have been delivered. Do not retry the same intent.

Keep the page URL available in the result and show it as a normal link if delivery is unavailable, fails or is unknown. The sender, recipient and provider credentials are resolved by Keiki; tools should not provide them.

What the recipient sees

The first time, the recipient installs the iMessage Apps launcher once from inside Messages. After that, cards open their HTTPS page right in Messages. live: true only uses the destination app's own iMessage extension when the recipient has installed it.

Opening a card is not an approval. The linked app remains responsible for authorization and any action the recipient takes there.