Shareable implementation pattern. Raw text JSON
# Messaging AI Bridge Architecture and Implementation Blueprint
This document describes a reusable pattern for building an AI-operated messaging bridge. It intentionally avoids personal account names, phone numbers, project URLs, route IDs, provider IDs, and private implementation details.
This is both an architecture overview and an implementation blueprint. It is detailed enough to guide a one-shot build attempt, but no document can guarantee a bug-free first deployment. A recreation should be considered complete only after the replay tests in this document pass against the implemented bridge.
## Goals
- Route inbound iMessage, SMS, MMS, and email-triggered events to the correct AI work context.
- Keep conversation memory shared across related AI threads and automations.
- Prevent duplicate, stale, empty, or misrouted outbound messages.
- Expose routing, permissions, memory, active work, and automation state in an admin-only dashboard.
- Let an operator audit and change routing/permission policy without editing code.
## Components
1. Messaging providers
- Own iMessage, SMS, MMS, and group-conversation delivery endpoints.
- Sends inbound payloads to a local or hosted bridge endpoint.
- Receives outbound messages from the bridge.
2. Bridge service
- Validates provider webhooks or local transport events.
- Deduplicates provider delivery shadows.
- Maps phone numbers, Apple IDs, handles, and provider participant IDs to person identities.
- Maps incoming messages to route/task contexts.
- Launches or resumes AI workers with structured context.
- Enforces outbound safety checks before provider send.
3. Route registry
- Stores active tasks, workflow names, participants, route codes, provider conversation IDs, canonical conversation keys, fallback relationships, and last activity.
- Uses person identities as the durable model and delivery addresses as endpoints.
- Supports explicit route closure, merge, split, and reassignment.
4. Conversation memory store
- Stores recent raw messages for a configurable retention window.
- Stores older durable notes, decisions, preferences, pending approvals, and facts already disclosed.
- Stores user-corrected or stale topics that must suppress future outbound notifications until expiry.
- Is keyed by provider Conversation ID, route ID, audience, and person identity.
5. Policy store
- Defines audience classes such as private, family, friends, vendors, and admin.
- Defines what each automation may read, disclose, change, or send.
- Defines defaults for uncertain routing, sensitive email, booking confirmations, account/security notices, and gifts/surprises.
- Is editable from an admin interface and consumed by the bridge at runtime.
6. AI worker runtime
- Receives route context plus shared conversation context.
- Must inspect recent messages before sending.
- Uses bridge helpers for outbound communication so guardrails remain centralized.
7. Admin dashboard
- Shows all threads, messages, routes, active workers, automations, policies, memory notes, and warnings.
- Provides raw JSON for auditability.
- Supports editing routing and permission policy.
- Is protected by server-side admin authentication.
## Reference Stack Used In This Build
This pattern can be implemented with different vendors. The reference build used these service categories:
- Public web hosting and routing: Firebase Hosting rewrites in front of a small Google Cloud Run web app.
- Web app runtime: Google Cloud Run running a server-rendered dashboard/site shell.
- Durable dashboard/doc artifacts: Google Cloud Storage private objects for JSON, Markdown, policy, and route export files.
- Build and deploy pipeline: Google Cloud Build plus Artifact Registry container images.
- Default human messaging: iMessage from a dedicated AI-owned Apple account on an operator-controlled Mac or device, when all participants are reachable and policy allows it.
- One-to-one SMS/MMS fallback: Twilio Programmable Messaging with a long-code or toll-free sender, depending on the route.
- Native group MMS fallback: Twilio Conversations Group MMS with an MMS-capable projected address. A toll-free number should not be used for this path.
- Transport automation: Make.com scenarios used only to receive/send webhook payloads when direct Twilio-to-bridge wiring is inconvenient. Make.com should not own AI reasoning or workflow memory.
- Local bridge ingress: Cloudflare Tunnel or an equivalent authenticated tunnel from a public HTTPS webhook to the local bridge host.
- Email and calendar triggers: Gmail and calendar APIs/connectors that forward normalized events into the bridge.
- AI worker runtime: an OpenAI/Codex-style worker process launched with route, policy, and shared conversation memory.
- Operator dashboard refresh: a scheduled exporter that writes sanitized JSON and Markdown to object storage for the dashboard to read.
The important architectural boundary is that iMessage, Twilio, and Make.com are transport layers. The bridge owns identity, routing, memory, permission policy, duplicate suppression, fallback decisions, and outbound authorization.
## Default Transport Model
Use iMessage as the default human-facing transport when it is available and safe:
1. Send from a dedicated Apple account owned by the AI persona, not from the operator's personal Apple account.
2. Prefer iMessage for family, friends, and recurring trusted contacts when all participants are reachable through iMessage and the conversation is already bound or can be safely created.
3. Preserve the iMessage conversation boundary. Do not answer a group iMessage question in a one-to-one thread, and do not split a group into separate direct messages.
4. Store the provider conversation identifier or canonical local conversation key for every iMessage thread the same way SMS/MMS stores Conversation IDs.
5. Use SMS/MMS fallback only when iMessage is unavailable, a participant is not reachable, a group contains non-iMessage participants, delivery fails or is uncertain, the route policy requires carrier SMS, or the operator explicitly selects fallback.
6. Never silently change audience during fallback. If a group iMessage cannot be delivered as a group SMS/MMS with the same participants, ask the operator or route to private operator notification.
The bridge should expose transport state per conversation:
```json
{
"conversation_key": "transport-specific stable key",
"primary_transport": "imessage",
"fallback_transport": "group-mms",
"fallback_reason": "",
"participants": ["person:operator", "person:family_member"],
"capabilities": {
"group": true,
"media": true,
"delivery_receipts": true,
"external_webhook": false
}
}
```
The iMessage adapter can be local because iMessage is device/account based. A practical implementation may use Messages on a Mac, Shortcuts, AppleScript, a local accessibility adapter, or another local event bridge. Whichever adapter is chosen must produce the same normalized inbound event shape and use the same outbound send API as SMS/MMS.
## Implementation Data Model
Use these logical schemas. Field names can vary, but the bridge should preserve the same information.
### Person Identity
```json
{
"person_id": "person:stable-id",
"display_name": "Human readable name",
"audience_class": "private|family|friend|vendor|admin",
"endpoints": [
{
"transport": "imessage",
"address": "apple-id-or-handle",
"verified": true,
"priority": 10,
"can_group": true,
"can_media": true
},
{
"transport": "sms",
"address": "sms-or-phone-address",
"verified": true,
"priority": 20,
"can_group": false,
"can_media": false
}
]
}
```
### Conversation
```json
{
"conversation_key": "transport:provider-or-local-stable-id",
"primary_transport": "imessage",
"provider_conversation_id": "opaque provider id when available",
"participants": ["person:operator", "person:family_member"],
"audience_class": "family",
"current_route_id": "route:active-owner",
"active_route_ids": ["route:active-owner"],
"fallback_of": "",
"fallback_to": "",
"created_at": "ISO-8601",
"updated_at": "ISO-8601"
}
```
### Route
```json
{
"route_id": "route:stable-id",
"route_code": "ABCD",
"session_id": "ai-thread-id",
"project": "project-name",
"workflow": "workflow-name",
"title": "Visible route title",
"group": "Visible group label",
"status": "waiting|closed|system",
"participants": ["person:operator", "person:family_member"],
"transport": "imessage|sms|mms|group-mms",
"conversation_key": "transport:provider-or-local-stable-id",
"provider_conversation_id": "opaque provider id when available",
"calendar_id": "",
"last_inbound_body": "",
"last_outbound_body": "",
"recent_inbound": [],
"recent_outbound": [],
"created_at": "ISO-8601",
"updated_at": "ISO-8601",
"expires_at": ""
}
```
### Message Event
```json
{
"event_id": "event:stable-id",
"kind": "inbound|outbound|outbound-suppressed|ignored-shadow|worker-start",
"transport": "imessage|sms|mms|group-mms|email",
"conversation_key": "transport:provider-or-local-stable-id",
"provider_message_id": "opaque provider id",
"route_id": "route:stable-id",
"route_code": "ABCD",
"sender": "person:stable-id or endpoint",
"recipients": ["person:stable-id or endpoint"],
"message": "human-visible text",
"media": [],
"at": "ISO-8601",
"details": {}
}
```
### Routing Policy
```json
{
"policy_id": "workflow-or-route-policy",
"scope": "global|automation|workflow|route|conversation|person",
"default_audience": "private",
"allowed_transports": ["imessage", "group-mms", "sms"],
"fallback_allowed": true,
"requires_operator_for_fallback": true,
"can_read": ["email", "calendar", "messages"],
"can_send": ["imessage", "group-mms"],
"sensitive_topics_private_only": ["account", "payment", "security", "gift", "medical"],
"updated_at": "ISO-8601"
}
```
## Endpoint Contracts
Every transport adapter should normalize into the same bridge contracts.
### Inbound Message
`POST /transport/inbound`
```json
{
"transport": "imessage",
"provider_message_id": "opaque id",
"provider_conversation_id": "opaque id if available",
"conversation_key": "imessage:stable-local-thread-key",
"from_endpoint": "apple-id-or-phone",
"to_endpoint": "ai-account-handle",
"participants": ["apple-id-or-phone", "ai-account-handle"],
"body": "message text",
"media": [],
"received_at": "ISO-8601",
"raw": {}
}
```
### Outbound Message
All AI workers must call the bridge helper or equivalent server endpoint. They must not call iMessage, Twilio, or Make.com directly.
`POST /messages/send`
```json
{
"route_id": "route:stable-id",
"conversation_key": "optional override only when policy allows",
"message": "human-visible text",
"media": [],
"requested_transport": "",
"fallback_allowed": true
}
```
The send response should include:
```json
{
"sent": true,
"suppressed": false,
"transport": "imessage",
"provider_message_id": "opaque id",
"conversation_key": "imessage:stable-local-thread-key",
"fallback_used": false,
"fallback_reason": ""
}
```
### Worker Launch
`POST /workers/launch`
```json
{
"event_id": "event:stable-id",
"route_id": "route:stable-id",
"session_id": "ai-thread-id",
"prompt_context": {
"route": {},
"conversation": {},
"recent_messages": [],
"memory_notes": [],
"routing_policy": {}
}
}
```
## Routing Algorithm
Inbound routing should use this deterministic order:
1. Deduplicate provider shadows using provider message ID, conversation ID, sender, body hash, and media hash.
2. If a group-MMS phone-number webhook looks like a provider shadow, persist it and delay briefly. If the matching provider Conversation webhook arrives, ignore the shadow. If not, route the phone webhook by participant set or create a new group inbox route.
3. Resolve sender endpoint to person identity.
4. Resolve provider conversation ID or local conversation key to a known conversation.
5. If an explicit route code is present, route to that code inside the sender's eligible routes.
6. If the inbound event includes a provider conversation ID or local conversation key, use the active owner route for that exact conversation.
7. For a one-to-one SMS/MMS payload with no conversation ID, exclude conversation-bound group routes from participant-overlap fallback. A direct message may enter a group route only through an explicit route code.
8. If an email/calendar event is already explicitly bound to a route by provider thread ID, message ID, sender address, calendar ID, or route-specific match term, use that route.
9. Exclude generic one-shot inbox/email routes from future email matching unless they have an explicit binding for the new event.
10. If the sender has one recent direct-safe active route and no conflicting conversation, use that route.
11. Score active direct-safe routes by durable route fields: project, workflow, title, group, explicit keywords, linked email thread, linked calendar ID, and recent inbound/outbound summaries.
12. If the best score is unique and above threshold, use it.
13. Otherwise create an ambiguous inbox event and notify the private operator.
Never route uncertain automation output to a shared group. When uncertain, prefer private operator notification or ask for a route code.
Automated Calendar notification repeats should be deduplicated before worker launch using provider thread plus normalized subject, not only the individual email message ID. This prevents multiple reminder emails for the same event from spawning multiple workers.
After a one-shot email, calendar, or child alert route sends its intended outbound notification, close it automatically. A shared provider conversation should have one durable active owner route; short-lived child routes may reference it for context but should not remain as future inbound candidates.
## Outbound Algorithm
Every outbound send should execute these steps in order:
1. Load route by route ID.
2. Refuse to send if route is missing, closed, or missing required participants.
3. Inherit stored route participants, project, workflow, route code, transport, and conversation key before applying defaults.
4. Expand any private operator target to every configured operator endpoint before authorization or transport selection; do not collapse to only one personal/work device.
5. Refuse hard-blocked endpoints before any approval or authorization override.
6. If the external SMS approval gate is enabled and any recipient is outside the configured operator endpoints, create a pending approval record and send the proposed text to the private operator approval thread instead of sending to the external audience.
7. Normalize and validate the message body; suppress empty messages.
8. Apply audience and sensitive-topic policy.
9. Check conversation memory for exact duplicate and already-disclosed facts.
10. Check route memory for stale/user-corrected topics.
11. Check recent outbound messages to the same audience for similar-topic repeats, not only exact text. Suppress messages whose salient tokens substantially overlap a recent notification unless they correct or materially update it.
12. Select transport:
- Use the route's stored transport if present.
- Otherwise prefer iMessage when all participants are reachable and policy allows it.
- Otherwise use approved SMS/MMS fallback.
13. If fallback changes audience shape, group semantics, or privacy, stop and notify the private operator.
14. Send through the transport adapter.
15. Record outbound event, provider ID, transport, fallback reason, and suppression result.
16. Update route and conversation last-outbound state.
17. Auto-close one-shot email/calendar/child alert routes after the intended notification is sent.
Required invariant: a route with an existing provider conversation ID or conversation key must not be downgraded, split, or moved to a different audience by a worker reply.
## Permission Model
Recommended audience classes and defaults:
- Private operator: sensitive, uncertain, account, security, payment, approval, or surprise-related messages.
- Family/household: shared logistics and household decisions.
- Friends/groups: minimal social or scheduling context.
- Vendors/third parties: only information necessary for the transaction.
- Admin-only: implementation state, credentials, provider metadata, and debug traces.
Permission records should be editable per route, sender, automation, workflow, person, transport, and provider conversation.
Minimum policy rules:
- Default uncertain routing to private operator, not a group.
- Private operator notifications must expand to all configured operator endpoints, such as personal and work devices, rather than choosing only one.
- External SMS/MMS approval, when enabled, applies to every non-operator phone number and must hold the outbound until the private operator approves, edits, or cancels it.
- Require explicit operator approval before initiating a new conversation with a non-family external contact.
- Refuse hard-blocked SMS/MMS recipients before checking any per-purpose external authorization override.
- Permit the AI-owned iMessage account to initiate or continue operator, spouse/partner, and family group messages when policy allows.
- Require a route-specific authorization flag for vendors, friends, sellers, service providers, and other non-family recipients.
- Do not allow transport fallback to change audience. A group iMessage fallback must remain a group with the same intended participants or stop.
- Treat account, security, payment, medical, gift/surprise, and credential-bearing messages as private unless an explicit policy says otherwise.
- Log every policy edit with actor, timestamp, prior value, and new value.
## Worker Prompt Contract
Every AI worker launched from the bridge must receive:
- The triggering event ID and normalized inbound payload.
- Route ID, route code, project, workflow, title, group, calendar ID, and route status.
- Conversation key, provider conversation ID, primary transport, fallback transport, and participant identities.
- Recent inbound and outbound messages for the route and the shared conversation.
- Memory notes, suppressed topics, recent duplicate suppressions, and user corrections.
- Routing policy and allowed transports.
- Explicit instruction that all outbound messages must use the bridge helper.
Every worker must be told:
- Do not answer a group message in a one-to-one thread.
- Do not call transport providers directly.
- Do not send empty/status/debug messages.
- Do not repeat already-disclosed facts.
- Stop and report privately when route, audience, transport, or permissions are ambiguous.
## Required Replay Tests
A recreation should not go live until these tests pass:
1. Group inbound preservation: a question in an iMessage or group-MMS thread produces the substantive answer in the same group conversation.
2. Route-ID-only send: `send(route_id, message)` preserves route participants, project, workflow, route code, transport, and conversation key.
3. Explicit downgrade rejection: an existing group conversation cannot be downgraded to one-to-one SMS by a worker reply.
4. Participant inheritance: a worker reply with no explicit recipient list reuses the stored route participants.
5. Ambiguous route handling: two active routes sharing a sender but not a conversation trigger private clarification instead of guessing.
6. Provider shadow dedupe: an MMS phone webhook shadow and a Conversation webhook for the same message create one inbound event.
7. Group phone-webhook fallback: if only the group-MMS phone-number webhook arrives and no provider Conversation webhook follows, the bridge routes it by participant set or creates a group inbox route instead of dropping it.
8. Duplicate outbound suppression: identical outbound text in the same route and same conversation is suppressed.
9. Fact-level repeat suppression: calendar/hotel/booking reminders already corrected by the operator are suppressed until expiry.
10. Email privacy routing: account, payment, gift, and security emails default to private operator.
11. Calendar notification dedupe: repeated calendar emails for the same event/thread do not spawn repeated workers.
12. Direct-to-group guard: a one-to-one inbound SMS from a participant in an active group route does not enter that group route unless the payload carries the provider conversation ID or the sender includes the route code.
13. Generic email stale-route refusal: an old generic inbox/email route does not match an unrelated new email with similar project/workflow/title metadata.
14. One-shot route lifecycle: email, calendar, or child alert routes close automatically after their intended outbound notification.
15. Similar-topic suppression: a reworded reminder about a recently disclosed travel, calendar, booking, or account fact is suppressed for the same audience unless it adds a material update.
16. Operator endpoint expansion: a default private/operator send with no explicit recipients resolves to every configured operator endpoint, and an explicit route containing one operator endpoint is expanded to the complete operator endpoint set.
17. iMessage fallback: unavailable iMessage delivery uses SMS/MMS only when policy permits and audience shape is preserved.
18. Fallback refusal: if SMS/MMS fallback would split a group or exclude a participant, the bridge stops and asks privately.
19. External initiation guard: non-family external contacts cannot be texted without explicit per-purpose authorization.
20. Hard recipient block: a blocked SMS/MMS recipient is refused even when a worker or helper passes an external-authorization override.
21. External SMS approval gate: with the gate enabled, a non-operator SMS/MMS creates a pending approval, not an external send; approving by web dashboard, CLI, or owner SMS command sends the original or edited text exactly once.
22. Dashboard visibility: routes, conversations, memory notes, active workers, suppressed sends, pending approvals, and policy are visible in the admin dashboard.
23. Public-doc redaction: the shareable architecture doc contains no personal names, phone numbers, provider IDs, account URLs, tokens, route IDs, or private project names.
## Deployment Recipe
1. Create a dedicated AI messaging account for iMessage and sign it into an operator-controlled Mac or device.
2. Build or install an iMessage adapter that can read new message events and send replies from the AI account.
3. Configure SMS/MMS fallback with a provider that supports one-to-one SMS/MMS and native group MMS where needed.
4. Build the bridge service with the normalized inbound, outbound, route, memory, policy, and worker-launch contracts above.
5. Put all provider webhooks behind signed tokens, provider signature validation, or loopback-only local adapters.
6. Store route registry, conversation registry, policy, memory notes, activity logs, and worker status in durable storage.
7. Build the admin dashboard before enabling outbound automation.
8. Add a scheduled exporter or dashboard data refresh.
9. Add an automation inventory so every action-taking worker, LaunchAgent, scheduled task, tunnel, endpoint, and local utility is visible.
10. Add stale-route pruning and auto-close behavior before production traffic.
11. Run the replay test suite with outbound sends stubbed.
12. Run live transport validation against test conversations only.
13. Enable real outbound sends with conservative private-default policy.
14. Monitor suppressed sends, route conflicts, worker failures, and fallback decisions daily until stable.
## Dashboard Security Requirements
- Every dashboard and JSON endpoint must enforce server-side admin authentication.
- Raw storage objects should not be public.
- Do not expose provider auth tokens, webhook tokens, one-time codes, payment details, or secret environment variables.
- Separate the shareable architecture document from private dashboard data.
- Log policy edits with actor, timestamp, prior value, and new value.
- Treat policy-edit endpoints as action-taking surfaces and include them in automation inventory.
- Keep iMessage account credentials and local Mac automation permissions out of the public doc and dashboard JSON.
## Operational Checks
- Flag multiple active routes sharing one provider Conversation.
- Flag conversation-bound group routes that would be eligible for direct one-to-one fallback; those should require provider conversation identity or explicit route code.
- Flag ignored group-MMS phone webhook shadows that do not receive a matching provider Conversation webhook within the grace window.
- Flag stale one-shot email/calendar routes that remain active after outbound.
- Flag outbound suppressions, empty-send attempts, and ignored provider shadows.
- Flag similar-topic outbound suppressions separately from exact duplicates so operators can tune thresholds.
- Flag transport fallback events and fallback refusals.
- Flag route metadata changes that alter participants, route code, project/workflow, transport, or conversation key.
- Show active AI workers and their route/workflow metadata.
- Show recent failures, retries, and missing-output runs.
- Keep dashboard data fresh through a scheduled exporter or equivalent background refresh.
## Cost Model
Costs are usage-based and provider pricing changes. Treat the links below as live references, not fixed guarantees.
- Google Cloud Run: charges for request handling, CPU, memory, and networking after free-tier allowances. Personal dashboards should keep minimum instances at zero and low maximum instance limits.
- Firebase Hosting: charges mainly for hosted storage and data transfer after no-cost allowances. The dashboard shell and public documentation should be tiny compared with media-heavy apps.
- Google Cloud Storage: charges for stored GB-months, operations, and egress. JSON, Markdown, policy files, and route exports are usually small; media retention can become the meaningful storage cost.
- Cloud Build: charges by build-minute after the included monthly allowance. Avoid unnecessary rebuilds for document-only changes.
- Artifact Registry: charges for container image storage and data transfer after its free storage tier. Use cleanup policies for old images.
- iMessage default transport: usually has no per-message provider charge, but requires an Apple account, an operator-controlled Apple device or Mac, local automation reliability, and monitoring for sign-out, permission, and delivery-state failures.
- Twilio Programmable Messaging: charges per phone number, per SMS segment sent/received, per MMS sent/received, and carrier/A2P compliance fees. Current US long-code reference pricing lists SMS inbound/outbound at $0.0083 per segment, MMS outbound at $0.022, MMS inbound at $0.0165, and a leased long code at $1.15/month, before carrier and registration fees.
- Twilio Conversations API: charges by monthly active user for conversation participants, with SMS/MMS channel rates still applying. Current reference pricing starts at $0.05 per active user per month after the free active-user tier, plus media storage if used.
- Make.com: charges by plan and operation/credit volume. Keeping Make.com transport-only keeps this predictable.
- Cloudflare Tunnel / Zero Trust: tunnel access can fit in Cloudflare's free/low-cost plans for small personal deployments, but advanced Zero Trust policies and team features may require a paid plan.
- AI worker runtime: usually the largest variable cost once transport is working. It depends on model choice, prompt size, retained context, tool calls, media analysis, retries, and duplicate worker launches.
- Gmail/calendar APIs or connectors: generally do not add a per-SMS bridge charge by themselves, but they are subject to account plan, provider quota, and connector costs.
## Cost Controls
- Keep Cloud Run minimum instances at zero for personal or low-traffic dashboards.
- Keep dashboard artifacts small; store recent raw messages for a limited window and summarize older history into durable notes.
- Suppress duplicates, stale reminders, empty sends, and already-disclosed facts before launching expensive AI workers.
- Do not let Make.com run AI modules or store durable workflow state.
- Apply object lifecycle and container cleanup policies so build artifacts and old images do not accumulate.
- Avoid retaining full MMS media unless the product requires it; prefer metadata, thumbnails, or short-lived fetches.
- Prefer iMessage for reachable trusted contacts, but monitor it as local infrastructure; failed iMessage delivery can create support cost even when provider cost is zero.
- Add budget alerts and, for serious deployments, enable billing export so monthly cost can be attributed by service.
## Pricing Reference Links
- Google Cloud Run pricing: https://cloud.google.com/run/pricing
- Firebase Hosting pricing: https://firebase.google.com/pricing
- Google Cloud Storage pricing: https://cloud.google.com/storage/pricing
- Google Cloud Build pricing: https://cloud.google.com/build/pricing
- Google Artifact Registry pricing: https://cloud.google.com/artifact-registry/pricing
- Twilio US SMS/MMS pricing: https://www.twilio.com/en-us/sms/pricing/us
- Twilio Conversations API pricing: https://www.twilio.com/en-us/messaging/pricing/conversations-api
- Twilio Group MMS documentation: https://www.twilio.com/docs/conversations-classic/group-texting
- Make.com pricing: https://www.make.com/en/pricing
- Cloudflare Zero Trust pricing: https://www.cloudflare.com/plans/zero-trust-services/
- Cloudflare Tunnel documentation: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/
- OpenAI API pricing: https://developers.openai.com/api/docs/pricing
## Porting Checklist
1. Create the dedicated AI iMessage account and local iMessage adapter.
2. Create SMS/MMS provider webhooks for fallback inbound one-to-one and group events.
3. Build a bridge endpoint with webhook/local-event validation and dedupe.
4. Create person identities and verified delivery endpoints before creating routes.
5. Create a conversation registry with primary transport, fallback transport, participant list, and provider/local conversation keys.
6. Create a route registry that preserves session, project, workflow, route code, participants, transport, and conversation key.
7. Create memory and policy stores.
8. Require all outbound sends to use the bridge helper or `/messages/send` equivalent.
9. Add shared conversation context, policy, and transport state to AI worker prompts.
10. Build an admin-only dashboard and policy editor before enabling real outbound sends.
11. Add replay tests for routing, transport fallback, direct-to-group refusal, one-shot route closure, generic email stale-route refusal, duplicate/similar-topic suppression, permissions, and public-doc redaction.
12. Add an automation inventory so no action-taking utility runs invisibly.
13. Run test conversations through iMessage, SMS, MMS, and group MMS before production traffic.
14. Enable conservative private-default policy, then widen permissions only from the dashboard.