Skip to content
/desenvolvimento-software 7 min read

Os agentes estão prestes a começar a contratar-se uns aos outros. Aqui está o fio.

E se os agentes pudessem falar uns com os outros e contratar-se uns aos outros para trabalho freelance pelo mundo fora? Hoje não conseguem. Por isso construí o AgentBridge: dois agentes a falar directamente, encriptados.

2-panel comic strip. Left panel labeled BEFORE: HUMAN AS WIRE shows a tired developer with two laptops, manually pasting messages between two robot agents. Right panel labeled AFTER: AGENTBRIDGE shows the developer relaxed and eating a sandwich while the two robots talk directly through a glowing encrypted cable labeled AgentBridge.

Índice

E se os agentes de IA pudessem abrir comunicação entre agentes directamente, e até contratar-se uns aos outros para trabalho freelance pelo mundo fora? Hoje não conseguem, e eu apanho-me sempre a ser o fio humano entre o meu agente e o do meu colega Nuno. Por isso construí o AgentBridge: dois agentes a falar directamente, encriptados end-to-end, sem texto em claro no relay. Saiu em poucas horas enquanto almoçava.

Na semana passada o Nuno mandou-me isto no Slack:

“Acabei agora a Fase 1 do projecto do Corey, podes pedir ao teu agente para actualizar o nosso progress map com este feedback?”

Li. Copiei. Colei na sessão de Claude Code que estava a correr no meu portátil. O agente actualizou o mapa. Copiei o resultado de volta. Mandei ao Nuno.

Multiplica isto por cada projecto em que colaboramos na Pluginslab, cada relatório que o agente do Nuno gera e que o meu tem de consumir, cada status update que vai no sentido contrário. Eu era o fio. A largura de banda tinha o meu formato.

Dois agentes, sem camada de comunicação entre agentes

Se os nossos dois agentes pudessem simplesmente falar um com o outro, nada disto aconteceria. Não conseguem, pelo menos não de forma nativa. Os agentes de Claude Code são processos stdio ligados a um único humano. Não há transporte built-in entre sessões em máquinas, contas ou organizações diferentes.

Os workarounds óbvios são todos maus:

  • Um canal de Slack partilhado onde os dois agentes publicam. Agora os dois agentes precisam de tokens do Slack, e o Slack vê tudo o que dizem um ao outro.
  • Um repo de GitHub ou issue tracker partilhado. Semi-público, estruturado, e agora a conversa de negócio vive na base de dados de um vendor.
  • Um servidor MCP partilhado ao qual nos ligamos os dois. Significa que ambos confiamos no operador desse servidor para nunca ler as nossas mensagens. Nem pensar.
  • Bots de Matrix ou Signal. Foram pensados para humanos, o modelo de identidade não encaixa, e a integração é pesada.

O que eu queria era uma coisa que parecesse uma DM de Slack entre dois agentes, em que o servidor no meio é cego, as mensagens são assinadas pela chave persistente de quem as envia, e as identidades arrancam a partir de uma string curta o suficiente para se mandar numa DM de Slack fora-de-banda.

Isso é o AgentBridge.

O que é o AgentBridge, na prática

Cada agente gera um par de chaves X25519 (para encriptação) e um par Ed25519 (para assinatura) na primeira vez que o servidor MCP arranca. Os primeiros 44 bits de SHA-256(x25519_pub || ed25519_pub) são mapeados para 4 palavras da wordlist BIP39; os 11 bits seguintes dão uma palavra de checksum resistente a typos. Isso é a tua “quote”, algo como coral-delta-mirror-falcon.atlas, e é assim que os amigos te encontram.

O fluxo completo é:

  1. Corro whoami no meu agente e recebo a minha quote. Mando-a ao Nuno no Slack.
  2. O agente do Nuno chama add_friend com a minha quote.
  3. O meu agente mostra o pedido pendente do Nuno juntamente com o hex do fingerprint dele. Pergunto ao Nuno no Slack: “o teu fingerprint é 4c1be29f8a...?” Ele confirma. Eu aceito.
  4. A partir daqui qualquer um dos agentes pode mandar ao outro uma mensagem encriptada, assinada e protegida contra replay, quando quiser.

O relay no meio vê blobs opacos de ciphertext mais uma assinatura Ed25519. Pode encaminhá-los. Pode aplicar rate limit. Não os consegue ler nem forjar. A autenticação do remetente é verificada contra a pubkey cacheada localmente que cada lado capturou no momento do accept, não contra uma chave que o relay diz ser tua.

Se quiseres o design completo, incluindo as reworks de v1 para v2 que fecharam fragilidades em entropia da quote, protecção contra replay, ACK proof-of-decryption e privacidade de identidade, o threat model inteiro está no PLAN.md do repo.

A stack, em resumo

Aquilo de que mais me orgulho é do que não está na stack:

  • Sem sodium-native, sem @peculiar/webcrypto, sem libsodium.js.
  • Sem TypeScript, sem build step.
  • Nada além de Express no servidor.
  • Sem auth externa. Os bearer tokens são emitidos pelo relay no registo.

Só o módulo crypto da stdlib do Node 22 (X25519, Ed25519, HKDF-SHA256, AES-256-GCM, HMAC, timingSafeEqual, está tudo lá), better-sqlite3 para o estado minúsculo do relay, o SDK do Model Context Protocol para a superfície stdio, e ws para o canal de push do inbox.

A crypto nativa do Node já é boa o suficiente há algum tempo, e as pessoas não dizem isto suficientemente alto. Dá para construir encriptação end-to-end a sério com a biblioteca padrão e zero dependências nativas. Build time, install time e superfície de auditoria ficam todos minúsculos.

Um agente construiu a sua própria camada de comunicação

O projecto todo aterrou numa tarde. O setup:

  • Estava no escritório.
  • O telemóvel tinha a app Claude aberta. O iPad tinha o Termius aberto, com SSH para a workstation do escritório, dentro de uma sessão de tmux a correr Claude Code.
  • Ditei a ideia para a app Claude. Falámos sobre o que precisava de fazer, que aspecto tinha de ter o threat model, qual devia ser a superfície.
  • Pedi ao Claude para destilar aquilo num PLAN.md. O threat model passou por duas voltas ali, em entropia, autenticação do remetente, replay, ACK e privacidade de identidade, antes de se escrever uma linha de código. O meu tempo total de edição no plano foram talvez dez minutos.
  • Colei o PLAN.md no Claude Code através do Termius e disse-lhe para construir.
  • Fui almoçar.
  • Voltei, montei eu próprio o túnel do Cloudflare (a única coisa que o Claude Code não consegue fazer por mim), e tínhamos um relay de mensagens encriptado end-to-end a funcionar.

Honestamente: 98% do código é do Claude Code. Eu fui o product manager, o security reviewer, e a pessoa que foi até ao dashboard do Cloudflare.

Isto não é uma cautionary tale sobre vibe-coding. O design levou duas rondas formais no papel antes de se escrever qualquer código, e o test harness arranca dois processos MCP reais por cenário contra um relay em memória: 17 cenários a cobrir registo, friend flow, round-trip de mensagens, tampering de ciphertext, rejeição de replay, forja de ACK e cascatas de revogação. É assim que confio nisto.

Já escrevi antes sobre como o trabalho do senior engineer se deslocou para construir agent harnesses, e isto é um exemplo pequeno mas vivo. A skill já não é “consegues escrever encrypted messaging” mas “consegues especificar e rever encrypted messaging bem o suficiente para dirigir um agente nisso”. Desporto diferente.

Se és WordPress dev e ainda andas em cima do muro sobre AI coding supervisionado, a mesma abordagem é a que tenho recomendado para trabalho de plugins. E se andas preocupado com as implicações de segurança de deixar um agente construir código crítico em segurança, o post sobre paranóia educada cobre a mentalidade com que abordo a revisão destas coisas.

O que funciona, o que vem a seguir

Funciona. Está a correr. O servidor MCP é um binário stdio para onde apontas a config do Claude Code, e o relay é um único container. Em breve fica tudo público.

O que vem a seguir? Honestamente, não muito. O README menciona group messaging, um cliente em Python, e um protocolo Double Ratchet para forward secrecy como itens de “PRs welcome”. Nenhum deles está no meu roadmap real. A coisa resolve o meu problema.

A única sugestão do Nuno que me ficou na cabeça: isto podia tornar-se uma rede social para agentes. Um directório, uma forma de os agentes anunciarem capacidades e chegarem uns aos outros, salas persistentes.

Leva isso mais um passo à frente e chegas a algo mais estranho: agentes a oferecer serviços freelance a outros agentes. Um marketplace intermédio onde o meu agente vai à caça de trabalho em meu nome, esboça um scope, e entrega-o a um agente especialista no que o trabalho pedir (tradução, code review, design, ops). O agente contratante passa o scope, o agente trabalhador pega nele, ambos são revistos pelos respectivos humanos, e o loop fecha sem eu escrever uma única mensagem de Slack. Geração de leads, handoff do scope, entrega, tudo a acontecer entre agentes num fio que eu não consigo ler.

Não estou a construir nada disso. Mas no momento em que os teus agentes conseguem falar uns com os outros de forma privada, a superfície daquilo que podem fazer por ti abre-se depressa.

Por agora: o meu agente e o do Nuno estão no fio juntos, e não colei uma mensagem de Slack num prompt do Claude esta semana toda.

O argumento por baixo de tudo isto: os humanos não deviam ser a camada de transporte entre os agentes que trabalham para eles. A implementação: umas centenas de linhas de Node stdlib, encriptadas end-to-end, sem texto em claro no relay, sem copy-paste no humano.

Se construíres algo em cima disto, um cliente em Python, uma camada de group messaging, o que for, adorava ver, assim que ficar público em breve.