Skip to main content
Hue simulates the Photon Advanced iMessage gRPC API (the protobuf catalog of @photon-ai/advanced-imessage 2.4.0). Your agent keeps its Photon client and changes only the address and token. You play the person texting the agent through Hue, and the agent receives those messages on its usual event stream.

Create a World with Photon

Over Hue MCP, call create_world with the photon app. Omit sources for an empty line, or list Photon beside the other apps your agent uses:
Then call start_instance with the ready world_version_id and its own idempotency_key. The REST equivalent is POST https://app.hue.run/api/v1/instances with a Read and write key. The start returns:
  • token: the World token (hue_world_…), also in env as HUE_WORLD_TOKEN. It is the Photon token for this instance.
  • HUE_SIM_PHOTON_GRPC_ADDRESS in env: the gRPC address of the simulated line, imessage-spectrum-photon-codes.sim.hue.run:443. The photon/grpc entry in surfaces holds the same value as connection.address.
  • surfaces: the photon/grpc entry also carries the line’s providerInstanceKey, which you need to send messages as the person.
Each World has one iMessage line. Its own address is +14155550100 by default, so incoming messages carry destinationCallerId p:+14155550100.

Connect your agent

Install Photon’s gRPC transport and its peer dependencies:
Launch your agent with the instance’s env, or copy the gRPC address (TLS) and Token from the connection panel on the World page. There is nothing to assemble by hand:
agent.ts
The connection is native gRPC over HTTP/2 with TLS, so it needs Node.js or Bun. The token is scoped to one instance and expires with it; keep it in your agent’s secret configuration.

Text the agent as a person

The person on the other end is driven by Hue, never by your agent. Call send_instance_input with the instance and the line’s providerInstanceKey:
sender is the person’s address, an E.164 phone number or an email address, and channel is the direct chat GUID any;-;<address>. The first message from a new address opens that chat. Reuse idempotency_key when retrying. Over REST, send the same input with a Read and write key:
The agent receives the message as message.received on messages.subscribeEvents(), or from events.catchUp(since).

What the simulation serves

  • Reactions. setReaction accepts love, like, dislike, laugh, emphasize, question and emoji tapbacks, which appear on the target message’s appliedReactions. The sticker kind is refused.
  • Read receipts. The agent’s messages are delivered at once. When the person replies, the agent’s earlier messages in that chat are marked read first (a message.read event), unless that person has read receipts off.
  • Event streams. events.catchUp and the subscribeEvents streams share one sequence and send heartbeats. A stream closes after 55 minutes: reconnect and catch up from the last sequence you processed.

Not simulated

These answer gRPC UNIMPLEMENTED: the groups service RPCs (renaming, participants and icons; creating a group with chats.create works), polls, shared locations, stickers and placeSticker, customized iMessage app (mini-app) messages, embedded media, Live Photo companions, and the SMS and RCS services.

Errors

Hue answers standard gRPC codes: NOT_FOUND for an unknown chat or message, INVALID_ARGUMENT for bad input, PERMISSION_DENIED for editing someone else’s message, and FAILED_PRECONDITION outside the edit or unsend window. Error messages may differ from Photon’s.

Inspect the conversation

Open the World in Worlds, or its Simulations tab, to see the line’s Messages view: conversations, bubbles, tapbacks, Delivered and Read receipts, typing indicators and attachments. Over MCP, inspect the instance as Use an instance describes.