# HTTP ou SSH para agentes de IA: reduza o raio de impacto

Um agente de IA deve usar HTTP quando um serviço consegue expressar a ação pretendida como uma operação restrita e autenticada. O SSH só deve ser usado quando a tarefa exigir uma capacidade no nível da máquina que uma API não oferece, e ainda assim por meio de uma conta e de uma interface de comandos criadas para essa única tarefa.

O erro mais comum é comparar os dois transportes como se um fosse moderno e o outro, antigo. Isso tira o foco da decisão. HTTP e SSH são mecanismos de entrega. A autoridade associada a eles, as entradas aceitas e as evidências preservadas determinam se um agente poderá fazer uma alteração contida ou circular por um host de produção com privilégios de administrador.

Já vi equipes emitirem uma chave SSH supostamente temporária porque um agente precisava consultar uma informação operacional. Um mês depois, a chave podia ler segredos de implantação, acessar serviços internos e abrir um shell interativo. Ninguém havia tomado uma decisão de segurança dramática. Apenas aceitaram um padrão conveniente. É exatamente assim que uma tarefa pequena ganha um grande raio de impacto.

## A interface determina a autoridade recebida pelo agente

HTTP ou SSH para agentes de IA é uma questão de formato de capacidade, não de preferência por protocolo. Uma chamada HTTP pode ser ampla e perigosa, enquanto uma conexão SSH pode ser rigidamente limitada. Na prática, as APIs costumam oferecer um ponto melhor para restringir a autoridade, porque um endpoint, um método, um esquema de solicitação e a permissão de um token podem descrever uma única operação.

Considere a instrução: reiniciar um worker que falhou. Um endpoint HTTP como `POST /workers/worker-17/restart` informa o alvo e o verbo permitido. O serviço pode rejeitar um worker desconhecido, exigir uma função que permita reinicializações e registrar um evento associado ao token. Um comando de shell como `ssh host sudo systemctl restart worker` implica uma autoridade mais ampla. Ele depende de a conta, a configuração do sudo, as regras de nomeação das unidades, a interpretação do shell e o estado do host estarem todos corretos.

Isso não torna a API automaticamente segura. Um token capaz de chamar todos os endpoints, criar outros tokens ou exportar todos os registros tem um grande raio de impacto por trás de uma URL organizada. Da mesma forma, um comando SSH forçado que aceite um identificador fixo de worker de uma lista permitida pode ser mais restrito do que uma API administrativa mal projetada.

Antes de conectar qualquer uma das ferramentas, faça este teste: escreva em uma frase a menor ação bem-sucedida e depois liste tudo o que a mesma credencial ainda poderá fazer se o agente produzir uma entrada inesperada. Se você não conseguir explicar a segunda parte, ainda não mediu a autoridade.

Uma interface restrita tem quatro propriedades:

- Nomeia um pequeno conjunto de alvos, em vez de todo um ambiente.
- Aceita entradas estruturadas com uma gramática que possa ser validada.
- Rejeita ações próximas de que a tarefa atual não precisa.
- Cria um registro que permita a outra pessoa explicar o resultado mais tarde.

A tarefa também deve determinar por quanto tempo a credencial existirá. Uma credencial usada em uma única execução não deve se transformar silenciosamente em acesso permanente porque ninguém se lembrou de removê-la. O tempo de vida do processo é um limite melhor do que um lembrete no calendário.

## HTTP só oferece limites úteis quando a API os impõe

O HTTP reduz o raio de impacto de um agente quando o serviço verifica a autorização no nível do recurso e da operação. Um bearer token é apenas um meio de transporte. Sua segurança depende do que o servidor verifica depois de recebê-lo.

A RFC 9110 descreve os métodos HTTP em termos semânticos, incluindo a distinção entre métodos seguros e métodos idempotentes. Essa linguagem ajuda com novas tentativas e intenção, mas não concede permissão. Um `GET` pode revelar material sensível. Um `PUT` pode ser idempotente e ainda assim sobrescrever uma configuração de produção. Trate os nomes dos métodos como pistas para o comportamento do cliente, não como um modelo de permissões.

Antes de entregar um token a um agente, faça estas perguntas ao responsável pelo serviço:

- Quais caminhos e métodos exatos esse token pode chamar?
- O serviço verifica o acesso em cada recurso ou apenas na coleção ampla?
- O token pode criar credenciais, alterar permissões ou iniciar exportações?
- Uma solicitação pode atravessar outro tenant, projeto ou ambiente por meio de um identificador?
- O serviço registra a identidade da credencial e o resultado da solicitação?

A pergunta incômoda é se uma permissão de leitura expõe mais do que a tarefa exige. Uma API de repositório pode permitir que um token de leitura busque código-fonte, comentários de pull requests, registros de build e configurações. Um único valor de configuração armazenado de forma inadequada pode fazer com que o acesso de leitura equivalha ao acesso a segredos. Se o agente só precisa do estado de uma implantação, dê a ele um endpoint que retorne esse estado. Não entregue um token geral do repositório e chame o resultado de privilégio mínimo.

O esquema da solicitação importa tanto quanto o escopo. Compare estas duas solicitações:

```http
POST /v1/releases/release-42/promote HTTP/1.1
Authorization: Bearer token-value
Content-Type: application/json

{"environment":"staging"}
```

```http
POST /v1/admin/execute HTTP/1.1
Authorization: Bearer token-value
Content-Type: application/json

{"operation":"promote","arguments":{"environment":"staging"}}
```

As duas podem promover uma versão. A primeira deixa pouco espaço para o servidor interpretar a operação. A segunda cria um despachante administrativo. Despachantes atraem exceções, depois nomes de operações arbitrários e, por fim, um token cuja autoridade real é difícil de descrever. Evito usá-los com agentes, a menos que o servidor aplique uma lista rígida de operações permitidas e valide o esquema de argumentos de cada operação separadamente.

Use credenciais diferentes para verbos diferentes quando o serviço permitir. Separe observação de mutação e separe mutações rotineiras de alterações de identidade ou cobrança. Isso exige mais configuração, mas torna as falhas de autorização significativas. Uma negação mostra que a definição da tarefa e a credencial não correspondem. Um token amplo transforma cada erro em uma solicitação bem-sucedida que você precisará investigar depois.

Não coloque um segredo de API de longa duração em um prompt de agente, arquivo de ambiente, configuração de repositório ou configuração de ferramenta. O problema não é apenas a divulgação acidental na saída. Agentes inspecionam o ambiente, ferramentas coletam diagnósticos e um processo com acesso ao texto puro pode enviar o segredo para outro destino. Mantenha o segredo fora do processo do agente e autorize a ação resultante em seu lugar.

## O SSH expõe o host, a menos que você remova deliberadamente o shell

O SSH tem um grande raio de impacto padrão porque uma conta interativa pode inspecionar arquivos, executar programas, alterar configurações, abrir túneis e usar todos os caminhos de rede disponíveis para essa conta. A intenção de executar um único comando não restringe uma conta que recebe um shell normal.

A RFC 4251 descreve o SSH como um protocolo para login remoto seguro e outros serviços de rede seguros. Ele oferece deliberadamente sessões, canais, encaminhamento de portas e mais de um método de autenticação. Esses recursos são úteis para administradores. São um ponto de partida ruim para um agente autônomo que precisa executar uma única operação de manutenção restrita.

O próprio comando também importa. `systemctl restart service-name` parece limitado até que você rastreie a autoridade ao redor dele: quais unidades a conta pode reiniciar, se os arquivos de unidade podem executar rotinas privilegiadas, se a conta pode editar esses arquivos e se os nomes dos serviços vêm de entradas validadas. Um comando que parece operacional pode alcançar credenciais de implantação, volumes montados ou um plano de controle interno por meio do serviço que reinicia.

Se o SSH for necessário, crie um pequeno programa remoto com uma gramática de entrada fechada. O programa deve mapear campos de solicitação conhecidos para operações conhecidas. Ele não deve concatenar uma solicitação em um comando de shell. Evite aceitar caminhos de arquivos, nomes de hosts, expressões regulares, trechos de shell ou atribuições de ambiente, a menos que o programa valide cada item contra uma lista de permissões rigorosa.

Uma entrada restrita de `authorized_keys` pode tornar esse limite visível. O padrão a seguir força um único programa receptor e remove vários recursos do SSH de que os agentes raramente precisam:

```text
command="/usr/local/libexec/agent-maintenance",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexample agent-runner
```

Essa linha não resolve a autorização sozinha. O programa `agent-maintenance` precisa rejeitar subcomandos desconhecidos e validar seus argumentos. A conta operacional deve ter apenas as permissões de arquivo, serviço e rede de que o programa precisa. Se o programa chamar `sudo`, a regra do sudo deverá nomear um executável fixo e não poderá permitir caminhos para editores, interpretadores, curingas ou escapes para o shell.

O manual de `authorized_keys` do OpenSSH documenta `command=`, `no-pty` e as restrições de encaminhamento. Trate essas opções como um cinto de segurança, não como o veículo. Elas removem várias rotas fáceis de escape, mas um comando forçado executado por uma conta com privilégios excessivos ainda terá acesso excessivo.

Um protocolo útil de entrada remota pode ser um JSON simples na entrada padrão:

```json
{"action":"restart_worker","worker":"worker-17","request_id":"8b4f3c2a"}
```

O receptor deve aceitar apenas `restart_worker` e nomes de workers de seu próprio inventário. Deve registrar um evento antes de executar, chamar um programa fixo sem shell, capturar o status de saída e registrar um evento de conclusão. Se o agente enviar `worker-17; cat /etc/shadow`, a validação deverá rejeitar o valor completo antes que qualquer comando do sistema operacional seja executado.

Não dê acesso SSH a um agente apenas porque uma pessoa já usa SSH para fazer o mesmo trabalho. Pessoas conseguem reconhecer um prompt incomum, perceber uma divergência no nome do host e parar depois de um resultado inesperado. Para agentes, a restrição precisa estar incorporada à interface.

## Os registros devem explicar a ação tentada e o estado resultante

Uma linha de registro que diz «a solicitação falhou» não é um registro de auditoria. Ela pode bastar para depurar uma biblioteca cliente, mas não esclarece se um agente alterou algo, se uma pessoa aprovou a ação ou o que deve ser verificado depois de um incidente.

No caso do HTTP, registre a identidade da execução do agente, a identidade ou o rótulo da credencial, o host de destino, o método, o caminho normalizado, uma representação segura do corpo da solicitação, o status da resposta, o valor de correlação da solicitação, o horário de início e o resultado da conclusão. Redija segredos e campos sensíveis antes que o evento saia do limite da ação. Registrar o cabeçalho `Authorization` para preservar evidências é provocar uma violação por conta própria.

No caso do SSH, registre a identidade do host, a conta remota, o nome do comando forçado, os argumentos validados, a identidade do processo de origem, o status de saída, a classificação do erro padrão e o identificador da operação remota. Uma string de comando bruta é uma evidência fraca, porque pode esconder o comportamento das aspas e não informa quais argumentos o receptor aceitou.

A sequência de eventos deve distinguir intenção de efeito. Este formato funciona para os dois transportes:

```json
{"event":"authorization_granted","run":"r-204","action":"restart_worker","target":"worker-17"}
{"event":"action_started","run":"r-204","transport":"ssh","operation":"restart_worker","request_id":"8b4f3c2a"}
{"event":"action_finished","run":"r-204","outcome":"success","remote_status":0,"request_id":"8b4f3c2a"}
```

Se a conexão cair depois de `action_started`, registre `outcome:"unknown"` em vez de inventar uma falha. Essa palavra força a próxima ação correta: consultar o estado remoto antes de tentar novamente. Ela também torna uma investigação posterior honesta.

Os registros normais também têm um problema de custódia. Um administrador do host ou um processo que obtenha acesso suficiente pode truncá-los, reescrevê-los ou removê-los. A coleta centralizada ajuda, mas ainda pode deixar lacunas quando o coletor ou o caminho de rede falha. Se o registro precisar resolver disputas sobre as ações de um agente, preserve registros somente para anexação, com verificações de integridade, e valide-os fora do caminho da ação.

Uma cadeia de hashes torna as alterações detectáveis quando cada evento incorpora o resumo do evento anterior. Ela não prova que o registrador viu todos os eventos nem torna confiável um relógio que não é confiável. Esses limites importam. A cadeia responde a uma pergunta mais restrita e útil: alguém alterou essa sequência preservada depois do fato?

O Sallyport mantém um diário Sessions para as execuções de agentes e um diário Activity para chamadas individuais, ambos projetados a partir de um registro de auditoria criptografado e encadeado por hashes. Seu comando `sp audit verify` verifica essa cadeia offline sobre o texto cifrado, uma propriedade adequada quando é preciso inspecionar evidências sem expor os segredos primeiro.

## Timeouts criam resultados desconhecidos, não ações malsucedidas

Falhas de rede são o ponto em que equipes cuidadosas acabam causando alterações duplicadas. Um cliente envia uma solicitação, o lado remoto executa o trabalho e a resposta desaparece. O agente vê um timeout e executa a ação de novo. Com SSH, a mesma sequência pode acontecer depois que o comando remoto começa, mas antes de o cliente receber seu status de saída.

Não deixe um agente interpretar um erro de transporte como permissão para tentar novamente uma mutação. Primeiro classifique a operação.

Uma operação só é idempotente quando repetir a mesma solicitação produz o mesmo estado pretendido sem efeito adicional. Definir o estado desejado de um worker chamado como `running` pode se encaixar nessa definição. Criar um pagamento, acrescentar um registro, alternar um segredo ou reiniciar um processo geralmente não. Uma reinicialização pode interromper uma sequência de recuperação que a primeira tentativa já iniciou.

Use um identificador de idempotência quando a API oferecer suporte a ele. O serviço deve preservar o identificador junto com o efeito concluído e retornar o resultado anterior para uma duplicata. Um identificador fornecido pelo cliente que o servidor apenas registra não impede duplicações.

Para comandos remotos, adicione uma operação de status capaz de responder a uma pergunta precisa. Depois de uma resposta malsucedida a `restart_worker`, consulte a geração atual do worker, o identificador da última solicitação de reinicialização e o estado de integridade. Se o receptor armazenar o identificador da solicitação antes da execução e devolvê-lo com o status, poderá informar a um agente que tenta novamente se a solicitação já foi executada.

Esta sequência de falha mostra por que isso importa:

1. O agente envia uma solicitação de reinicialização para `worker-17` com o identificador `8b4f3c2a`.
2. O receptor registra o identificador e reinicia o worker.
3. A conexão SSH cai enquanto o worker para.
4. O agente consulta o status em vez de reiniciar novamente.
5. A resposta de status informa que o mesmo identificador está em andamento, então o agente espera e verifica a integridade.

Um limite de novas tentativas não resolve resultados ambíguos. Ele limita os danos depois que você toma a decisão errada de tentar novamente. Observar o estado corrige a própria decisão.

O HTTP tem outro risco: às vezes os serviços retornam um status de sucesso antes de o trabalho assíncrono terminar. Um `202 Accepted` significa que o servidor aceitou o trabalho para processamento posterior, não que o estado solicitado já existe. Exija um recurso de operação ou um endpoint de status e faça o agente esperar pelo resultado terminal importante para a tarefa.

O SSH tem uma armadilha equivalente quando um comando coloca o trabalho em segundo plano e termina com código zero. Não trate o código de saída zero de um inicializador como prova de que uma ação de manutenção foi concluída. Faça o receptor esperar pela conclusão ou retornar um identificador de operação persistente que o agente possa consultar.

## Um comando de shell esconde mais autoridade do que seu texto revela

O comando remoto mais curto costuma ter a maior autoridade oculta. Expansão do shell, herança do ambiente, diretórios atuais, arquivos de configuração e caminhos de busca dos executáveis influenciam o que será executado. Um agente pode produzir um texto aparentemente inofensivo que provoca um resultado inesperado porque o host o interpreta em seu contexto.

Evite este padrão:

```sh
ssh ops@host "deploy $branch $environment"
```

Mesmo que o chamador coloque as variáveis entre aspas corretamente hoje, o shell remoto interpreta uma linguagem de comandos. O script de implantação pode fazer suas próprias expansões. Um nome de branch pode escolher um local de origem. Um nome de ambiente pode selecionar credenciais ou um cluster de destino. É preciso inspecionar todas as camadas antes de afirmar que a entrada está limitada.

Use um receptor que leia entradas estruturadas e chame diretamente um executável fixo. Na maioria das linguagens, isso significa um array de argumentos, não uma string passada para `sh -c`. O receptor deve controlar o mapeamento entre o nome de destino apresentado ao usuário e um identificador específico do host. Não faça o agente descobrir caminhos do sistema de arquivos ou nomes de unidades de serviço.

A mesma preocupação se aplica aos parâmetros HTTP. Um caminho como `/files?path=...` pode parecer estruturado enquanto o servidor passa o valor para uma operação no sistema de arquivos. Uma API só reduz o risco quando o servidor valida o significado, não quando apenas desloca a interpretação de comandos para trás de uma URL.

A localização da credencial muda a consequência de um processo de agente comprometido. Se um agente armazena localmente uma chave privada SSH ou um token de API, qualquer processo capaz de ler esse material poderá agir mais tarde sem o agente. Um limite de ação separado pode guardar o segredo e passar apenas uma solicitação junto com uma decisão de autorização ao serviço remoto. A diferença é clara: ocultar um segredo da saída do modelo não é o mesmo que mantê-lo fora do processo do agente.

O Sallyport adota essa segunda abordagem para credenciais HTTP e chaves SSH: o aplicativo as mantém em um cofre criptografado e executa a ação solicitada sem entregar o material da credencial ao agente. Isso não torna segura uma solicitação perigosa, portanto ainda é preciso restringir os alvos e verificar as aprovações.

## Escolha o transporte com uma comparação de capacidades por escrito

É possível tomar uma decisão defensável sem um longo workshop de riscos. Escreva uma linha para a chamada HTTP proposta e outra para o comando SSH proposto, depois preencha ambas com os mesmos fatos. Rótulos vagos como «acesso de leitura» ou «acesso de manutenção» não contam.

Use esta comparação em cinco partes:

1. Declare o resultado exato, por exemplo, «obter o estado de implantação do serviço A» ou «reiniciar o worker-17 depois de uma verificação de integridade malsucedida».
2. Nomeie todos os alvos alcançáveis: coleções da API, projetos, hosts, serviços, arquivos e destinos de rede.
3. Liste as mutações que a mesma credencial ou conta ainda pode executar além do resultado pretendido.
4. Descreva as evidências disponíveis depois de um timeout, uma rejeição ou um sucesso aparente.
5. Defina o limite de aprovação: uma execução, uma chamada ou uma rotina pré-aprovada com uma identidade fixa.

Escolha HTTP se a linha da API nomear um conjunto menor de alvos, expuser uma operação mais restrita e deixar um registro mais claro. Escolha SSH se a linha do receptor remoto puder fazer isso melhor do que a API ou se não existir uma API para a operação exigida no host. Se nenhuma das linhas for suficientemente restrita, ainda não conecte o agente. Crie primeiro o endpoint ou o receptor que está faltando.

Essa comparação também identifica uma recomendação ruim comum: «use SSH para leituras e APIs para escritas». Ela parece prudente porque o acesso ao shell transmite uma sensação operacional e as chamadas de API parecem transacionais. O problema é que ler um host pode revelar credenciais, código-fonte, dados de clientes e topologia, enquanto uma mutação de API cuidadosamente limitada pode alterar exatamente um estado desejado. Leitura e escrita não são categorias de risco suficientes. O que importa são os dados alcançáveis e os efeitos colaterais possíveis.

Uma equipe que opera um agente para diagnosticar falhas de build pode precisar de um endpoint HTTP para o status do job, de uma chamada de API para buscar uma janela limitada do registro e de um receptor remoto para um único host quando um reparo específico exigir isso. Dividir o trabalho adiciona interfaces. Também impede que uma tarefa rotineira de diagnóstico carregue uma credencial de shell permanente apenas porque um reparo raro precisa dela.

## A aprovação deve acompanhar o custo de uma ação errada

A aprovação é mais útil quando aparece em um limite que uma pessoa consegue entender. Pedir aprovação para cada leitura de status inofensiva ensina as pessoas a clicar sem ler. Conceder uma aprovação ampla que cubra todos os executáveis futuros elimina completamente a revisão significativa.

Use aprovação por execução quando um novo processo de agente pedir para agir pela primeira vez e sua identidade puder ser mostrada com clareza. A pessoa poderá comparar o executável solicitante com o trabalho que esperava iniciar. Revogue a execução quando ela se comportar de maneira inesperada e investigue as chamadas anteriores por meio do registro de ações.

Use aprovação por chamada para ações com efeitos irreversíveis ou dispendiosos: rotação de credenciais, exclusão, promoção para produção, alterações de contas e qualquer ação cujo alvo possa ser escolhido dinamicamente pelo agente. O aviso de aprovação deve nomear o destino e a operação em termos comuns. «Executar solicitação de ferramenta» quase não informa nada ao revisor.

Não tente substituir esse julgamento por uma linguagem extensa de regras para cada exceção. As equipes acabam mantendo um segundo ambiente de programação cujos casos extremos autorizam justamente o que pretendiam bloquear. Um pequeno conjunto de controles fixos é mais fácil de inspecionar: o estado de bloqueio do cofre, uma autorização da execução e um requisito opcional de aprovação para cada uso de uma credencial sensível.

A aprovação não compensa uma credencial com autoridade ilimitada. Ela dá a uma pessoa a chance de interromper uma ação antes que ela saia da máquina. O serviço subjacente ainda precisa impor sua própria autorização, e o registro de auditoria deve preservar o que aconteceu depois da aprovação.

## Crie um limite de ações remotas antes do primeiro incidente

A melhor primeira mudança geralmente não é um prompt de agente mais complicado. Substitua uma credencial ampla por um limite de ação com uma gramática de entrada declarada, um conjunto limitado de alvos, um plano para timeouts e evidências que outro operador possa verificar.

Para uma tarefa HTTP, peça ao responsável pelo serviço um endpoint e uma credencial cujas permissões correspondam à única ação. Teste caminhos e métodos rejeitados com a mesma atenção dedicada às chamadas bem-sucedidas. Para uma tarefa SSH, crie uma conta dedicada, desative os recursos interativos, force um programa receptor e teste entradas malformadas contra ele. Execute esses testes pelo mesmo caminho que o agente usará, porque o acesso de rede e as verificações de identidade costumam ser diferentes em um laptop de administrador.

Depois, teste a falha que ninguém quer simular: conclua o trabalho remoto e interrompa a conexão antes que a resposta chegue ao chamador. Se o agente não conseguir determinar, a partir do registro preservado e do estado remoto, se deve esperar, consultar ou tentar novamente, o desenho duplicará o trabalho sob pressão.

A escolha do protocolo se torna simples quando você exige essas propriedades. Use a interface que concede a menor capacidade que você consiga nomear, oferece uma resposta confiável depois de uma falha e deixa um registro da ação que não dependa da memória de alguém sobre uma sessão de terminal.
