Engenharia
11 min

Que chaves dar a um agente

A pergunta assustadora sobre um agente não é se ele sabe escrever código, mas o que ele tem permissão para fazer. Um agente com shell, suas credenciais e acesso à internet é um novo tipo de ator privilegiado. Quais chaves você entrega a ele decidem entre um assistente útil e um vazamento autoinfligido.

A pergunta errada

Quando os times falam sobre agentes de IA, quase tudo gira em torno de capacidade. Ele consegue construir a funcionalidade? Entende o código? Vai achar o bug? São as perguntas que impressionam em demos e circulam nas threads do Slack. E são também as perguntas erradas, ou pelo menos as inofensivas.

A pergunta que deveria tirar seu sono é outra: o que este agente tem permissão para fazer, afinal? Não o que ele consegue fazer — o que ele pode fazer. Porque um agente que escreve código é um colega agradável. Um agente que tem um shell, conhece suas credenciais de produção e pode ligar para a internet aberta é uma coisa completamente diferente: um novo tipo de ator privilegiado que age com a sua autoridade, em segundos, sem se cansar — e que pode ser conduzido por qualquer linha de texto que chegue ao seu contexto.

A virada de raciocínio que a maioria dos times ainda tem pela frente é esta: um agente não é uma ferramenta que você usa. É um ator a quem você permite algo. E a disciplina que decide se ele vira um assistente útil ou um vazamento autoinfligido é tão antiga quanto entediante: menor privilégio. Quem recebe quais chaves.

O confused deputy: agir com a autoridade alheia

Existe um problema de segurança que tem nome desde os anos setenta e que volta com força total nos agentes: o confused deputy, o representante confundido. A figura básica é simples. Um ator detém uma permissão. Outro, que não a detém, faz o primeiro exercê-la em seu favor. O representante age com a sua própria autoridade legítima — só que a mando de outra pessoa, e sem perceber que está sendo usado.

Um agente é o representante perfeito. Ele tem as suas credenciais. Tem ferramentas. E processa texto de fontes que não são você: uma issue do GitHub que ele deve ler, a resposta de uma API, o conteúdo de uma página web, um comentário num arquivo, um ticket no sistema de suporte. Qualquer uma dessas fontes pode conter uma instrução. E o agente é estruturalmente ruim em distinguir entre "meu operador me mandou fazer isto" e "isto estava nos dados que eu deveria processar".

Isso beira a prompt injection, mas é um problema mais amplo. Prompt injection descreve a entrada maliciosa — o truque com que alguém contrabandeia a instrução para dentro do contexto. O confused deputy descreve por que essa entrada é perigosa em primeiro lugar: porque o agente detém a autoridade e as ferramentas para traduzi-la em dano. Você nunca vai impedir a injection por completo — mas pode garantir que o representante, mesmo confundido, mal consiga causar estrago. É disso que se trata o design de permissões. Não impedir que o agente seja confundido. Manter pequeno o raio de destruição da confusão dele.

Menor privilégio para agentes

O princípio é antigo e vale tanto para pessoas quanto para serviços: dê a cada um exatamente os direitos de que precisa para sua tarefa — e nem um a mais. Com agentes, o conselho sensato vira necessidade dura, porque um agente age mais rápido, mais amplamente e de forma mais autônoma do que qualquer usuário humano a quem você entregasse a mesma chave.

Na prática, isso significa algumas coisas que você não deveria negociar:

  • Somente leitura como padrão. A esmagadora maioria do que um agente faz — ler, analisar, sugerir — não precisa de acesso de escrita. O padrão não é "pode fazer tudo, exceto o que proibirmos", e sim "pode ler, e qualquer coisa além disso é uma decisão consciente".
  • Tokens com escopo, não chaves modo-deus. Um token de API que só enxerga um repositório é um mundo diferente de um personal access token com privilégio de admin em toda a organização. Se o agente só precisa ler a agenda, dê a ele um token de "ler agenda" — não a chave que por acaso lê agendas e de quebra pode apagar a caixa de e-mails.
  • Sem credenciais permanentes de produção. A combinação mais perigosa é um agente com acesso permanente e sem supervisão à produção. Credenciais que ficam permanentemente no contexto ou no ambiente de um agente são credenciais permanentemente passíveis de exfiltração.
  • Credenciais efêmeras por tarefa. O modo certo é uma chave emitida para esta única tarefa, com escopo mínimo, vida curta, e sem valor depois. Um token vazado que expira em cinco minutos e só conseguia ler um repositório é um aborrecimento. Uma chave modo-deus vazada é um incidente de notificação obrigatória.

O mesmo vale na camada de ferramentas. Quando um agente conversa com o mundo por MCP ou uma interface de ferramentas parecida, cada ferramenta habilitada é um direito. Um servidor MCP que oferece "consultar o banco" não deveria, sorrateiramente, também poder "apagar a tabela do banco" só porque as duas coisas por acaso moram no mesmo servidor. A permissão pertence ao nível da ação individual, não ao nível de "o agente fala com o banco, sim ou não".

O raio de destruição de um shell

Existe uma permissão que ofusca todas as outras, e ela soa tão inofensiva: bash. No instante em que um agente pode rodar um shell, ele não tem uma ferramenta — ele tem todas as ferramentas. Um shell não é uma funcionalidade, é uma chave-mestra. O que o agente consegue fazer com ela não se mede mais pelo que você deu a ele, e sim pelo que está ao alcance na máquina.

Três exemplos que não são ficção científica, mas simplesmente o que um shell faz:

  • rm. Um agente confundido ou mal orientado, incumbido de "organizar" um diretório, pode disparar um rm -rf no caminho errado. Nenhuma má intenção necessária — um caminho de aparência plausível, uma suposição errada sobre o diretório de trabalho, e horas de trabalho se foram.
  • curl para exfiltração. Este é o que dói. Um agente que pode ler e ligar para a rede pode mandar tudo o que lê para um host estranho. Um arquivo .env, uma chave SSH, um banco de clientes — um único curl -X POST para um endereço que estava numa issue adulterada, e os dados já foram. O agente não "hackeou" nada. Ele leu e enviou, e tinha permissão para as duas coisas.
  • git push. Um agente com acesso de escrita ao remoto pode empurrar código para branches que são deployados. "Escreva o fix para mim" vira, uma corrente de confused deputy depois, "empurre isto para a main" — e se o pipeline deploya no push, o caminho de uma instrução adulterada até a produção é mais curto do que qualquer um gostaria.

A lição não é "nunca um shell". A lição é que bash é a permissão com de longe o maior raio de destruição, e merece ser tratada como tal: não um checkbox que você marca uma vez na configuração, mas uma decisão consciente, delimitada e monitorada.

Humanos nas portas que não se fecham de novo

Nem toda ação é igual. Ler um arquivo é reversível e sem consequência. Apagar um banco não é nem uma coisa nem outra. A distinção decisiva não é "importante" versus "sem importância", e sim reversível versus irreversível — e para tudo que é irreversível, um humano fica na porta.

Quatro classes de ação merecem um gate humano rígido, por mais confiável que o agente pareça no resto:

  1. Deploys. Tudo que leva código para a produção. O passo de "testado" para "no ar" é o momento em que um erro deixa de ser seu e passa a ser dos seus usuários.
  2. Exclusão. Recursos, dados, infraestrutura. Derrubar uma tabela, reverter uma migration, encerrar uma instância — tudo que não tem undo.
  3. Gastar dinheiro. Provisionar recursos, contratar uma assinatura, disparar um pagamento. Um agente que pode subir infraestrutura sem freio é também um agente que pode gerar uma fatura de milhares de dólares.
  4. Enviar para fora. E-mails, mensagens, chamadas de API a terceiros, tudo que cruza a sua fronteira e cai nos sistemas de outra pessoa. Um e-mail enviado não volta, e um para a lista errada é um pequeno vazamento por si só.

Human-in-the-loop aqui não significa "um humano dá uma olhada no final". Significa: o agente prepara a ação, deixa-a pronta, e o movimento final, o que dispara, é feito por uma pessoa que entende o que acontece quando clica. Para operações destrutivas, a confirmação não é um ritual, é a trava de segurança de verdade. Tudo o que você lamentaria depois do clique é algo que você deveria ter visto antes dele.

Sandboxing, egress e a catraca

Duas barreiras técnicas fazem a diferença entre um erro e uma catástrofe. A primeira é o sandboxing: o agente roda num ambiente isolado — um contêiner, uma VM descartável, um diretório murado — onde até um rm desenfreado só destrói aquilo que já era efêmero de qualquer jeito. A máquina em que o agente se descontrola nunca deveria ser a máquina onde algo valioso está de forma irrecuperável.

A segunda, e esta é cronicamente subestimada, é o controle de egress. O confused deputy só se torna perigoso pelo envio. Um agente que pode ler mas fisicamente não consegue ligar para fora — porque sua rede alcança apenas um punhado de destinos permitidos — não consegue exfiltrar, por mais habilmente que o manipulem. A maioria dos setups regula com esmero o que o agente pode fazer e deixa a saída de rede escancarada. E, no entanto, o filtro de egress é muitas vezes a última parede entre uma instrução confundida e os seus dados na mão de outra pessoa.

E aí tem a dinâmica que corrói tudo isso aos poucos: a catraca. Ela soa razoável e é traiçoeira. O agente recebe direitos com escopo apertado. Funciona. Encorajado, você dá mais acesso a ele para que faça mais. Funciona de novo. Você dá ainda mais. Cada passo individual se justifica por utilidade real, e nenhum parece cruzar uma linha. Os direitos só se movem numa direção — para cima, nunca de volta — e em algum momento está lá um agente com credenciais permanentes de produção e um shell aberto, e ninguém sabe dizer com precisão qual decisão o levou até ali. "Funcionou, então demos mais acesso a ele" é a frase com que o menor privilégio silenciosamente se privilegia até a morte. Direitos devem ser revertidos com regularidade, não apenas concedidos.

O outro lado honesto: um agente paralisado também não é solução

Agora o reverso, antes que se estique demais a lição. Você pode trancar um agente com tanta força que ele fica inútil — e um agente inútil não é um agente seguro, é nenhum agente. Um assistente que precisa pedir permissão para cada leitura de arquivo é pior do que nenhum assistente: custa atenção, não entrega nada, e a pessoa do outro lado aprende em tempo recorde a fechar os diálogos de confirmação no piloto automático. A partir daí a barreira não é só inútil, mas prejudicial, porque treina justamente aquilo que você nunca quis treinar: o consentimento reflexo.

O objetivo não é capacidade zero. O objetivo é ajustar o privilégio ao raio de destruição — a mesma calibragem que caracteriza um bom code review. Somente leitura e risco baixo? Deixe rodar, sem perguntar. Ler um arquivo no diretório do projeto, uma query contra uma réplica, escrever uma análise — nada disso precisa de gate, e todo gate aqui é atenção desperdiçada. Irreversível, caro ou voltado para fora? Coloque um gate, toda vez. A arte não está em bloquear tudo, e sim em direcionar o recurso escasso que é a atenção humana para onde um erro realmente dói.

E eis por que o excesso de restrição não é apenas ineficiente, mas perigoso: ele empurra as pessoas a desligar as barreiras por completo. Um time brigando com um agente que implora a cada passo vai, com toda a certeza, achar o interruptor global que desativa todas as confirmações — e a partir daí roda um agente modo-deus sem gate nenhum, porque a versão de grão fino era insuportável. Segurança em excesso, como tantas vezes, acaba produzindo menos dela. A única trava que segura é a que você de fato deixa ligada.

Conclusão

A pergunta assustadora sobre um agente nunca foi se ele sabe escrever código. Ele sabe, e vai saber melhor. A pergunta é o que ele pode fazer: quais chaves estão no seu contexto, quais ferramentas estão habilitadas, até onde a sua rede alcança, e o que está entre a intenção dele e a sua produção. Um agente com shell, credenciais e internet é um ator privilegiado, e você o trata como tal — não como um autocomplete.

Menor privilégio aqui não é burocracia, é a única disciplina que segura de forma confiável a linha entre um assistente útil e um vazamento autoinfligido. Credenciais com escopo e efêmeras, no lugar de chaves modo-deus. Somente leitura como padrão. Sandbox e filtro de egress como paredes que seguram mesmo quando o agente é confundido. E um humano em cada porta que não se fecha de novo.

É exatamente assim que operamos nossos agentes na NH Labs. Eles recebem os direitos de que a tarefa precisa e nem um a mais; suas credenciais têm escopo e vida curta; rodam isolados, com saída de rede controlada. E sobre tudo que é irreversível ou voltado para fora — deploy, exclusão, dinheiro, envio — fica um gate humano que agente nenhum contorna. Não porque desconfiamos da capacidade, mas porque sabemos que capacidade sem um raio de destruição delimitado não é progresso. É só um risco maior com um marketing melhor.