Skip to content
iMessage

The same brain, on a phone.

The demo in your browser and the thread on your phone are the same program. Not a port, not a second implementation kept roughly in step: one engine, two ways in.

He answers the handle that texted him, and there is no path by which he starts.

Two separate physical reasons rather than a setting: the lead-facing half of every conversation is routed to a sideline on the phone transport, and every number in the sample data is in the 555 reserved-fiction range, which the reachability check rejects without consulting the sample data to decide.

One brain, two transports

Every decision about what Lewis says lives in one place. The browser demo and the iMessage webhook are both thin wrappers around it, so a change to how he handles an objection is live on the phone without a second edit.

That is worth stating plainly because the alternative is so common and so quiet. Two implementations of the same assistant drift the moment somebody makes a quick fix in the route rather than the engine, and the drift is invisible until a customer sees one version and you are looking at the other.

He only ever texts the handle that texted him

There is no path by which Lewis starts a conversation with a stranger on a phone. Two separate, physical reasons, not a setting:

  • The lead-facing side of a conversation is routed to a sideline on the phone transport. It is written exactly as it always was, and it does not leave.
  • Every number in the sample data is in the 555 reserved-fiction range, and the check that rejects that range does not consult the sample data to decide.

Lifting that needs a real CRM and recorded consent. It is not a flag somebody can turn on.

A room is not a louder 1:1

Group threads are a sibling of the direct path rather than a flag on it, and the two things that make them different are both refusals.

Messages go through the endpoint that can only reach people already in the chat. That is the safety property, not the plumbing: replying by handle instead would answer the group in a private thread with whoever spoke, so the room sees silence and one person gets what reads as an aside about the others.

And a room is always the buyer half. The agent console spends a “yes” against somebody’s licence, and in a room a bare yes has no unambiguous author, which is never guessing on approvals broken by construction. So the agent side is refused rather than made to work, and the room gets the half that is better with more people in it: the search, the listings, and the argument about which one is nicer.

He answers some of what he hears, and records all of it

Deciding whether to speak is deterministic first, named, quoted, answering his own question, one human left, has not spoken yet, and modelled second. A failure in that gate means silence, which is the opposite of every other fallback here: the failure of the thing whose job is restraint must not produce a chattier bot.

The messages he does not answer still go into the transcript. Without that he goes deaf between the ones he does answer, and asks where they want to live after they have already agreed.

Names are learned or asked for, never invented. There is no @-mention an API can set on iMessage, so addressing one person is their name in the sentence plus a native quote-reply, first bubble only, and only when somebody else has spoken since he last did.

At a glance

On a phone.

The transport
iMessage. No new app on the home screen, no dashboard to remember to open.
One to one
The agent console and the buyer half, exactly as they are in the browser. Same engine, same rails, same queue.
A group
Buyer brain only. A bare yes in a room has no unambiguous author and a send spends a licence, so the agent workflow is refused rather than made to guess.
Addressing one person
Their name in the sentence plus a native quote-reply. iMessage has no @-mention an API can set, and names are learned or asked for, never invented.
Where it lives
src/v2/imessage/dispatch.ts, and group-dispatch.ts for a room.

Next to this

Your book is already full of people who meant it.

Point Lewis at the export and he works it over text, every draft still waiting on your yes.