Documentação oficial desta página · v0.20.6
Photon (iMessage)
Conecte o Hermes ao iMessage pelo Photon, um serviço gerenciado que cuida da alocação de linhas da Apple e da camada de prevenção de abuso, para você não precisar manter o seu próprio relay em um Mac.
O plano gratuito usa o pool de linhas de iMessage compartilhadas do Photon — destinatários diferentes podem ver números de envio diferentes, mas cada conversa se mantém estável. O plano pago Business dá a mesma linha dedicada para todo usuário; o plugin funciona com os dois, e o plano gratuito é o ponto de partida recomendado.
O pool de linhas compartilhadas do Photon é gratuito. Não é preciso assinatura para mandar o seu primeiro iMessage pelo Hermes — só um número de telefone que possamos vincular à sua conta.
Arquitetura
O Photon é um canal de conexão persistente, como o Discord ou o Slack — sem webhook, sem URL pública, sem segredo de assinatura para administrar.
O SDK spectrum-ts mantém um stream gRPC de vida longa com o Photon, nas duas direções. Como o SDK só existe em TypeScript, o Hermes o roda num pequeno sidecar Node supervisionado e conversa com ele por loopback:
- Entrada — o sidecar consome o stream gRPC
app.messagesdo SDK e encaminha cada mensagem ao adaptador Python por umGET /inboundem loopback (NDJSON). O adaptador deduplica e despacha para o agente, reconectando sozinho se o stream cair. - Saída — as respostas são POSTs em loopback para o sidecar, que chama
space.send(...)no SDK.
O plugin Python inicia, supervisiona e encerra o sidecar automaticamente.
Pré-requisitos
- Uma conta no Photon — cadastre-se em app.photon.codes
- Node.js 18.17 ou mais novo no PATH (
node --version) - Um número de telefone que receba iMessage (usado para vincular a sua conta)
É só isso — não há URL pública nem túnel para configurar.
Configuração inicial
Rode o assistente unificado do gateway e escolha Photon iMessage:
hermes gateway setup
…ou rode a configuração do Photon direto (o assistente chama o mesmo fluxo):
# Login por device code + projeto + usuário + dependências do sidecar, tudo de uma vez
hermes photon setup --phone +15551234567
A configuração, em ordem:
- Login do dispositivo (
client_id=photon-cli) — abrehttps://app.photon.codes/para aprovação e guarda o bearer token. - Encontra ou cria o projeto
Hermes Agentna sua conta. - Habilita o Spectrum, lê o id de Spectrum do projeto e gira o segredo do projeto.
- Registra o seu número de telefone como usuário do Spectrum — pula se já existir um usuário com aquele número, então rodar de novo é seguro.
- Imprime a linha de iMessage atribuída a você — o número para o qual você manda mensagem para falar com o seu agente.
- Roda
npm installdentro do diretório do sidecar do plugin. Em árvores de instalação somente leitura ou imutáveis (imagens Docker hospedadas, Podman, Nix), o sidecar recorre automaticamente a um espelho gravável em~/.hermes/photon/sidecar; definaPHOTON_SIDECAR_DIRpara fixar um local explícito.
As credenciais de runtime são gravadas no ~/.hermes/.env (PHOTON_PROJECT_ID = o id do projeto Spectrum, PHOTON_PROJECT_SECRET), no mesmo lugar em que todo outro canal guarda o seu token. Os metadados de gerenciamento (token do dispositivo, id do projeto no painel) ficam no ~/.hermes/auth.json, em credential_pool.photon / credential_pool.photon_project.
Autorizar usuários
O Photon usa o mesmo modelo de autorização de todos os outros canais do Hermes. Escolha uma abordagem:
Pareamento por DM (padrão). Quando um número desconhecido escreve para a sua linha do Photon, o Hermes responde com um código de pareamento. Aprove com:
hermes pairing approve photon <CODE>
Use hermes pairing list para ver os códigos pendentes e os usuários aprovados.
Autorize números específicos de antemão (no ~/.hermes/.env):
PHOTON_ALLOWED_USERS=+15551234567,+15559876543
Acesso aberto (só para desenvolvimento, no ~/.hermes/.env):
PHOTON_ALLOW_ALL_USERS=true
Quando PHOTON_ALLOWED_USERS está definido, remetentes desconhecidos são ignorados em silêncio, em vez de receberem um código de pareamento (a lista de permissão sinaliza que você restringiu o acesso de propósito).
Exigir menção em conversas de grupo
Por padrão o Hermes responde a toda DM e a toda mensagem de grupo autorizada. Para tornar as conversas de grupo opt-in, habilite o portão por menção (as DMs continuam sempre funcionando):
gateway:
platforms:
photon:
enabled: true
require_mention: true
Com require_mention: true, mensagens de grupo são ignoradas a menos que casem com um padrão de palavra de ativação. Os padrões default casam com Hermes e variações de @Hermes agent. Para um nome de agente personalizado, defina padrões de regex:
gateway:
platforms:
photon:
require_mention: true
mention_patterns:
- '(?<![\w@])@?amos\b[,:\-]?'
As duas chaves também aceitam variáveis de ambiente (PHOTON_REQUIRE_MENTION, PHOTON_MENTION_PATTERNS). É o mesmo modelo de portão por menção que o canal iMessage do BlueBubbles usa.
Suba o gateway
hermes gateway start
Você vai ver algo assim:
[photon] connected — sidecar on 127.0.0.1:8789, streaming inbound over gRPC
Mande um iMessage para o número atribuído a você e o Hermes responde.
Status e resolução de problemas
hermes photon status
Imprime as credenciais salvas, a saúde do sidecar, o seu número registrado e a linha de iMessage atribuída que o Hermes usa. Quando há um token do Photon e um projeto no painel disponíveis, o status atualiza as linhas de número que estiverem faltando a partir do painel, sem provisionar linhas novas.
Photon iMessage status
──────────────────────
device token : ✓ stored
dashboard project : 3c90c3cc-0d44-4b50-...
spectrum project id : sp-...
project secret : ✓ stored
my number : +15551234567
assigned number : +16282679185
node binary : /usr/bin/node
sidecar deps : ✓ installed
Problemas comuns:
sidecar deps : ✗ run hermes photon install-sidecar— o Node está instalado, mas ospectrum-tsnão. Rode o comando sugerido.device token : ✗ missing— rodehermes photon setuppara fazer login.No iMessage line assigned yet— o Spectrum está habilitado, mas nenhuma linha foi provisionada; rodehermes photon setupde novo ou confira o painel.- O sidecar não sobe — confirme que
node --versioné 18.17 ou superior e que ohermes photon install-sidecarterminou sem erros.
Limitações de hoje
- Anexos de entrada trazem só metadados. Os eventos de entrada carregam o nome do arquivo e o tipo MIME; o agente vê um marcador, mas ainda não consegue ler os bytes. O SDK expõe os bytes do anexo por
content.read(), então isso é um trabalho pendente no sidecar. - Anexos de saída são suportados. O Hermes envia imagens, notas de voz, vídeo e documentos pelos construtores de conteúdo
attachment()/voice()do spectrum-ts, através do endpoint/send-attachmentdo sidecar. As legendas chegam como um balão de iMessage separado, depois da mídia. - Enquetes nativas são suportadas. O Hermes envia conteúdo de enquete pelo construtor
poll()do spectrum-ts, através do endpoint/send-polldo sidecar. - Efeitos de mensagem são suportados. O Hermes envia texto com efeitos nativos de balão e de tela do iMessage pelo construtor
effect()de iMessage do spectrum-ts, através do endpoint/send-effectdo sidecar. - Cotas gratuitas do Photon: 5.000 mensagens por servidor por dia e 50 conversas novas iniciadas por linha compartilhada por dia. Dá para aumentar — escreva para
help@photon.codes. - Envios por cron e avulsos exigem o gateway rodando. Remetentes fora do processo (cron jobs,
hermes send, o painel) reaproveitam o sidecar que o gateway criou — eles leem a porta e o token dele em<hermes-home>/runtime/photon-sidecar.json, gravado assim que o sidecar passa na verificação de saúde e removido quando ele para. Se um envio avulso avisar que o gateway parece estar fora do ar, suba (ou reinicie) o gateway antes. - Linhas compartilhadas do plano gratuito não iniciam conversas com destinos novos. É política do lado do Photon: uma linha compartilhada só pode escrever para um número depois que aquele número tiver escrito para a linha primeiro. Um envio por cron ou avulso para um destinatário totalmente novo é rejeitado pelo Photon, mesmo com o Hermes configurado corretamente — ou peça para o destinatário escrever para a linha uma vez, ou migre para uma linha dedicada.
Variáveis de ambiente
| Variável | Padrão | Observações |
|---|---|---|
PHOTON_PROJECT_ID | do .env | Id do projeto Spectrum (o projectId do SDK); definido pela configuração |
PHOTON_PROJECT_SECRET | do .env | Segredo do projeto; definido pela configuração |
PHOTON_SIDECAR_PORT | 8789 | Porta de loopback para o controle do sidecar e o canal de entrada |
PHOTON_SIDECAR_AUTOSTART | true | Se o adaptador deve criar o sidecar |
PHOTON_NODE_BIN | which node | Sobrescreve o caminho do binário do Node |
PHOTON_HOME_CHANNEL | (não definida) | Id de space padrão para cron e notificações |
PHOTON_HOME_CHANNEL_NAME | (não definida) | Rótulo legível do canal principal |
PHOTON_ALLOWED_USERS | (não definida) | Lista de permissão em E.164, separada por vírgula |
PHOTON_ALLOW_ALL_USERS | false | Só para desenvolvimento — aceita qualquer remetente |
PHOTON_REQUIRE_MENTION | false | Exige palavra de ativação antes de responder em grupos |
PHOTON_MENTION_PATTERNS | palavras de ativação do Hermes | Padrões de regex para menções em grupo, em lista JSON, separados por vírgula ou por quebra de linha |
PHOTON_DASHBOARD_HOST | app.photon.codes | Sobrescreve o host do painel e do login por dispositivo |
PHOTON_SPECTRUM_HOST | spectrum.photon.codes | Sobrescreve o host da API do Spectrum |