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:
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/configRequirements
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:
{ "url": "https://your-app.example/review/123", "live": true }The builtin maps delivery results like this:
| Delivery state | Tool result |
|---|---|
accepted | { "success": true, "message_id": "…" } |
unavailable | success: false with the unavailable reason as the error. |
failed | success: false with a send-failed error. |
unknown | success: 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:
{
"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:
| Field | Requirement |
|---|---|
type | Must be "app". |
id | Required 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. |
url | Required absolute HTTPS URL, at most 2,048 characters, without embedded credentials. |
live | Optional boolean. |
caption | Optional string, 1–60 characters. |
subcaption | Optional string, 1–80 characters. |
Keiki adds presentationDelivery to the tool result:
{
"presentationDelivery": {
"state": "accepted",
"messageId": "<provider-message-id>"
}
}The state is one of:
| State | Meaning |
|---|---|
accepted | The provider accepted the card; this does not mean the recipient opened it. |
unavailable | The card could not be sent. reason is addon_disabled, invalid_presentation, unsupported_channel or line_not_eligible. |
failed | Delivery failed before acceptance. |
unknown | The 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.