8 min de leitura

Como os limites do stderr do MCP mantêm as execuções de agentes em andamento

Defina limites para o stderr do MCP e evite que auxiliares barulhentos consumam memória, atrasem aprovações, travem o encerramento e deixem registros de ações incompletos.

Como os limites do stderr do MCP mantêm as execuções de agentes em andamento

Um auxiliar barulhento pode interromper uma execução de agente sem quebrar uma única mensagem JSON-RPC. Isso acontece quando ele transforma o stderr em uma fila sem limite e faz outra parte da pilha pagar a conta: um pipe enche, um leitor retém megabytes, o encerramento espera para sempre ou um cartão de aprovação aparece depois que o usuário já deixou de confiar na execução.

Trate o stderr como uma entrada não confiável, com um orçamento definido. Isso parece preciosismo até você ver um comando perfeitamente comum emitir um diagnóstico a cada nova tentativa, enquanto a ação que ele deveria apoiar já terminou e o processo pai ainda tenta recolher todo aquele ruído. A solução não é «desligar os logs». O caminho certo é drená-los continuamente, reter apenas uma quantidade limitada, contabilizar o que foi descartado e manter o estado da ação independente da saída de texto.

O stderr é um caminho de backpressure

O stderr pode bloquear um auxiliar quando o processo pai o conecta a um pipe e não consome esse pipe com rapidez suficiente. Os sistemas operacionais oferecem buffers de tamanho limitado para pipes. Quando um processo filho enche esse buffer, a próxima gravação espera por um leitor. Se esse filho só chega ao caminho de sucesso depois de escrever o diagnóstico, a ação parece travada, embora a requisição de rede, a conexão SSH ou o trabalho local tenham funcionado normalmente.

O problema oposto é mais silencioso, mas costuma custar mais caro. O processo pai pode ler o stderr rapidamente e acrescentar cada byte a uma string, a um buffer de eventos ou ao resultado de uma ferramenta MCP. O pipe nunca enche, mas um processo filho muito falante pode consumir memória suficiente para deixar o host lento, provocar pressão de memória ou fazer chamadas posteriores falharem. Um limite que protege apenas o pipe é incompleto. Um limite que protege apenas a memória também é.

Isso importa ainda mais com agentes porque eles incentivam a execução em paralelo. Uma tarefa pode iniciar vários auxiliares, e um loop de novas tentativas pode criar outro pico antes que o primeiro seja drenado. Uma taxa de logs que parece inofensiva em um terminal interativo se torna um problema de recursos quando várias sessões a capturam ao mesmo tempo.

Há três coisas diferentes que precisam de limites:

  • Bytes esperando no pipe do sistema operacional.
  • Bytes que o bridge retém na memória para uma chamada.
  • Bytes que o bridge expõe a um agente, a uma interface de usuário ou a uma projeção do diário.

Não confunda limite de linhas com limite de bytes. Uma linha pode conter um corpo de resposta grande, uma cadeia de certificados ou um objeto de erro minificado. Também não presuma que o UTF-8 chega sempre com caracteres completos. Os leitores de fluxo recebem bytes em blocos, e o limite ainda precisa funcionar quando um caractere multibyte atravessa o limite entre dois blocos.

Um leitor prático mantém um contador de bytes para todo o fluxo e um buffer circular separado para o trecho final retido. Quando o total ultrapassa o limite, ele continua drenando para que o processo filho possa terminar. O buffer retido para de crescer e o leitor registra que houve truncamento. Encerrar o processo filho imediatamente no primeiro excesso pode ser correto para uma ferramenta cuja saída seja abusiva por si só, mas não deve ser o padrão para diagnósticos. Em geral, você quer o status de saída real e as últimas linhas que ajudam a explicá-lo.

O MCP mantém o stdout fora dos limites

Um servidor MCP stdio precisa tratar o stdout como território do protocolo. As orientações da especificação do Model Context Protocol para o transporte stdio determinam que um servidor não escreva no stdout nada além de mensagens MCP válidas. É fácil tratar essa regra como uma questão de higiene de formatação. Na prática, ela evita uma classe muito mais grave de falhas: uma linha casual de progresso de um auxiliar pode fazer o host interpretar JSON inválido e abandonar uma sessão que, de resto, estava funcionando.

Coloque os diagnósticos destinados a pessoas no stderr, mas não presuma que isso os torna inofensivos. O stderr é um canal separado apenas no sentido do protocolo. O host do processo ainda decide se herda esse fluxo, cria um pipe, captura seu conteúdo, escreve em um terminal ou o encaminha para um log estruturado. Cada escolha muda o comportamento em caso de falha.

A herança funciona para um desenvolvedor local porque o terminal consome a saída e o desenvolvedor consegue vê-la. É um padrão ruim para um bridge de agente. Ele vaza texto arbitrário para um lugar que pode não reter o conteúdo, pode misturar a saída de chamadas simultâneas e pode transportar detalhes que o agente nunca deveria receber. A captura completa é melhor para diagnóstico, desde que tenha um orçamento.

Mantenha a fronteira do protocolo simples. O servidor MCP deve enviar mensagens JSON-RPC válidas pelo stdout, manter seus próprios diagnósticos limitados no stderr e iniciar auxiliares com os fluxos sob controle explícito. Um auxiliar deve devolver resultados estruturados pelo canal previsto. Não deve imprimir um bloco JSON no stderr esperando que o processo pai o reconheça mais tarde.

Essa distinção evita um erro recorrente: tratar o stderr como um canal alternativo de resposta. Ele não é. Não oferece enquadramento confiável, pode ficar incompleto durante um cancelamento e pode conter a saída de bibliotecas que desconhecem completamente o seu modelo de ações. Se o chamador precisa do número de tentativas, do código de erro remoto ou de uma lista de arquivos alterados, inclua isso no resultado estruturado. Reserve o stderr para evidências de que uma pessoa possa precisar ao investigar uma falha.

Capturar a saída exige seu próprio orçamento de memória

Ler o stderr em uma tarefa em segundo plano não torna a captura segura. Isso apenas transfere o gargalo do pipe para a heap. Já vi hosts corrigirem um deadlock lendo os dois fluxos simultaneamente e depois descobrirem que um auxiliar com defeito podia obrigá-los a reter cada byte até o fim da ação. O processo agora termina, mas o host sofre.

Use um buffer circular para os diagnósticos retidos. Depois que a capacidade é atingida, ele mantém os bytes mais recentes, que normalmente são justamente onde aparece o erro útil. Preserve também um prefixo curto se, no seu ambiente, a primeira linha tiver significado, como a invocação do comando ou a versão da biblioteca. Não preserve ambos indefinidamente.

O pseudocódigo a seguir descreve o comportamento que vale a pena implementar. Ele não depende de uma linguagem específica.

on_stderr_chunk(bytes):
  stderr_seen += length(bytes)
  if stderr_seen \u003c= capture_limit:
    append_tail(bytes)
  else:
    append_tail(bytes)       # ring buffer evicts older bytes
    stderr_truncated = true
  continue_reading()

O comentário merece atenção. capture_limit deve significar a quantidade que você mantém, não o ponto em que para de ler. Uma implementação mais rígida pode ignorar append_tail depois do limite e preservar os primeiros bytes. Eu prefiro o trecho final porque as mensagens de falha costumam aparecer depois de páginas de saída de progresso. Qualquer que seja a opção, registre-a no dado para que um investigador posterior saiba se está lendo o começo ou o fim.

Coloque um segundo limite no objeto que leva os diagnósticos para o contexto do agente. Um agente não precisa de uma transcrição de vários megabytes para decidir se deve tentar novamente. Ele precisa de um erro conciso, do status de saída e, no máximo, de um trecho final selecionado. Quando o bridge repassa a saída bruta do auxiliar porque «o modelo pode precisar dela», ele dá a cada auxiliar um caminho para ocupar todo o contexto restante da tarefa.

Não decodifique e recodifique um fluxo grande apenas para impor um limite de texto. Conte os bytes brutos antes de criar strings. Decodifique o trecho retido usando uma estratégia de substituição para sequências inválidas e identifique-o como stderr capturado. Isso evita desperdício de memória e falsa segurança quando um auxiliar emite dados binários por engano.

Uma ação concluída ainda pode falhar durante o encerramento

O encerramento do processo é onde as enxurradas de logs se transformam em relatórios de incidentes enganosos. A ação pode ter sido concluída remotamente, o auxiliar pode ter impresso seu diagnóstico final e o processo pai ainda pode não conseguir produzir um resultado porque espera o evento errado na ordem errada.

Uma sequência conhecida se parece com esta:

  1. O bridge inicia um auxiliar e começa a ler o stdout, mas a leitura do stderr fica para trás durante um pico.
  2. O auxiliar conclui a ação externa e depois escreve diagnósticos suficientes para encher o pipe do stderr.
  3. O processo pai cancela a sessão ou atinge um prazo e envia um sinal de encerramento.
  4. O processo pai espera o processo filho antes de fechar ou drenar os leitores dos fluxos.
  5. Um leitor espera o fim do arquivo enquanto outra tarefa espera o leitor, e a sessão nunca chega ao seu registro final.

O efeito externo pode já existir. Uma requisição HTTP pode ter sido aceita ou um comando SSH pode ter alterado um arquivo remoto. Relatar essa chamada simplesmente como «tempo esgotado» deixa o operador com a pior resposta possível: ele não sabe se tentar novamente repetirá uma alteração.

Dê a cada auxiliar um proprietário responsável por gerenciar em conjunto quatro coisas: o identificador do processo filho, o leitor do stdout, o leitor do stderr e o cancelamento. Em uma conclusão normal, aguarde o encerramento do processo e drene os leitores até o fim do arquivo antes de construir o resultado final. Em um cancelamento, solicite o encerramento, continue drenando os dois fluxos, aguarde um período de tolerância limitado e force o encerramento se a plataforma permitir. Por fim, aguarde os leitores terminarem e registre o estado de saída que você realmente observou.

Não torne os leitores dos fluxos filhos apenas do handler da requisição. Um handler pode desaparecer quando um cliente se desconecta. O auxiliar e seus leitores precisam de um proprietário que permaneça ativo pelo tempo necessário para concluir a limpeza e gravar o estado final. Caso contrário, um processo do agente pode sair, o host pode descartar as últimas referências aos leitores e um processo filho pode continuar vivo com pipes que ninguém consome.

Os grupos de processos exigem o mesmo cuidado. Um wrapper de shell pode iniciar descendentes que herdam o stderr, e encerrar apenas o wrapper pode deixar um descendente mantendo o pipe aberto. Evite um shell quando puder. Se precisar de um, inicie-o em um grupo de processos contido e defina exatamente quais descendentes serão alcançados pelo cancelamento. Depois, teste o caso em que o wrapper sai, mas um processo neto continua escrevendo.

O momento da aprovação deve ignorar o volume de logs

Mantenha o limite da ação local
Um único app assinado na barra de menus executa o núcleo do cofre no próprio processo, sem um daemon separado para gerenciar.

O momento da aprovação deve acompanhar o estado da ação, não o ritmo dos diagnósticos do auxiliar. Se a interface só apresenta a aprovação depois que um auxiliar produz uma transcrição de pré-verificação, uma pré-verificação barulhenta muda o momento em que o usuário é convidado a decidir. A aprovação passa a parecer aleatória, e as pessoas aprendem a aprovar cartões sem entender por que um deles demorou mais.

Defina as transições antes de escrever o código da interface. Uma chamada pode ser recebida, validada, estar aguardando aprovação, autorizada, despachada, concluída, cancelada ou falhar antes do dispatch. O stderr pode ser associado a uma chamada, mas não deve decidir qual transição ocorre. O bridge deve validar o destino e os parâmetros solicitados, criar o registro da chamada e apresentar qualquer aprovação necessária antes de iniciar uma ação que exija aprovação.

Há uma exceção útil. Um auxiliar pode ser necessário para descobrir qual ação ocorrerá, como resolver um nome de configuração local para um endpoint concreto. Nesse caso, trate a descoberta como uma operação própria, que não é uma ação, com seu próprio orçamento de saída. Não esconda uma ação dentro de «pré-verificação» para depois afirmar que o usuário a aprovou.

Dê à aprovação um prazo baseado no relógio que não seja reiniciado pela chegada de novos dados no stderr. Continue coletando o trecho final limitado enquanto o cartão estiver visível, mas nunca redesenhe o cartão a cada linha. Um aviso de nova tentativa ou um resumo de erro pode ser um contexto útil se chegar antes da aprovação, mas deve aparecer como uma explicação estável, não como uma exibição de logs em movimento sem fim.

Separe consentimento de atividade nos testes. Um teste de excesso deve medir o tempo entre uma solicitação de chamada válida e o cartão de aprovação, com stderr produzido antes e depois desse momento. Um teste de leitor lento deve verificar que o cartão continua utilizável enquanto o bridge drena o fluxo. Um teste de cancelamento deve verificar que dispensar o cartão não deixa nenhum processo auxiliar em execução e produz um registro final.

A consequência humana é clara: um cartão de aprovação precisa descrever uma ação específica em um momento específico. Se a saída de logs puder atrasar, alterar ou sobreviver a esse momento, a interface estará relatando a confusão do processo, em vez de dar controle ao usuário.

Os registros de chamadas precisam dos fatos do ciclo de vida antes dos diagnósticos

Um registro de chamada está completo quando explica o estado da ação, não quando contém cada linha emitida por um auxiliar. A saída dos logs é uma evidência. Os eventos do ciclo de vida são o registro.

Grave a tentativa antes do dispatch. Inclua um identificador estável da chamada, o identificador da sessão, o tipo de ação solicitado, a decisão de aprovação ou recusa e as informações de destino mostradas ao usuário. Quando o dispatch começar, acrescente esse fato. Quando terminar, acrescente o resultado observado: sucesso, falha remota, falha local, cancelamento, encerramento forçado ou resultado desconhecido causado pela perda da fronteira do processo.

Depois, anexe os metadados de diagnóstico. No mínimo, registre o total de bytes de stderr recebidos, os bytes retidos, se houve truncamento, o status de saída do auxiliar quando disponível e se o fluxo terminou corretamente. Isso torna honesto um trecho final curto. Um leitor posterior consegue distinguir entre «o comando imprimiu isto» e «o bridge manteve a parte final do que o comando imprimiu».

A estrutura de um registro pode ser pequena assim:

{
  "call_id": "c_7f2a",
  "state": "cancelled_after_dispatch",
  "stderr_bytes_seen": 184320,
  "stderr_bytes_retained": 16384,
  "stderr_truncated": true,
  "exit_status": null,
  "stream_end": "reader_completed_after_cancel"
}

Não escreva exit_status: 0 porque o processo pai recebeu um corpo de resposta bem-sucedido. Um corpo de resposta e o encerramento de um processo filho são observações diferentes. Não escreva state: failed quando o cancelamento ocorreu depois do dispatch e o lado remoto pode ter agido. Essa distinção parece preciosista durante a implementação, mas se torna a diferença entre uma investigação segura e uma nova tentativa às cegas às duas da manhã.

O NIST SP 800-92 Guide to Computer Security Log Management faz uma observação útil: o gerenciamento de logs inclui geração, transmissão, armazenamento, análise e descarte, não apenas a coleta de texto. Aplique esse raciocínio às ações do agente. Se a coleta puder impedir a conclusão, o caminho de logging passou a fazer parte da execução. Ele precisa de limites, estado e tratamento de falhas como qualquer outro caminho de execução.

O Sallyport projeta seus diários de Sessions e Activity a partir de um único log de auditoria criptografado, write-blind e encadeado por hash. Assim, o chamador consegue distinguir a execução do agente dos registros de cada ação individual, sem depender da transcrição de um auxiliar como histórico.

Limite o ruído em três lugares

Verifique os registros depois de um excesso de logs
Verifique offline o log de auditoria encadeado por hash sobre o texto cifrado com sp audit verify.

Um único limite no topo da pilha deixa espaço demais para acidentes. Defina limites no auxiliar, no bridge e no destino dos diagnósticos. Cada limite protege uma fronteira diferente.

Primeiro, torne os auxiliares menos falantes por padrão. Coloque o progresso rotineiro atrás de uma configuração de depuração explícita, emita um único resumo para uma sequência de novas tentativas e evite imprimir corpos de requisições ou respostas por padrão. Um auxiliar nunca deve gravar credenciais, cabeçalhos de autorização ou material de chave privada no stderr. A remoção de dados sensíveis depois da captura é uma proteção útil, mas não desfaz o vazamento de um segredo que já passou por um terminal, um relatório de falha ou um buffer sem limite.

Segundo, faça o bridge drenar continuamente e reter um prefixo ou trecho final limitado. Ele deve impor uma duração máxima e uma quantidade máxima de bytes retidos para cada fluxo. Também deve ter um orçamento de diagnóstico para todo o processo. Sem esse último controle, cinquenta chamadas que respeitem individualmente seu limite ainda podem criar um pico de memória em conjunto.

Terceiro, limite o destino. Se você exportar os diagnósticos da chamada para uma interface de usuário, uma resposta do agente ou um arquivo, imponha outro limite nesse ponto. Um diário pode manter campos estruturados do ciclo de vida e um resumo do conteúdo descartado sem armazenar o mesmo stack trace repetido a cada nova tentativa.

Use uma estrutura de configuração explícita. Os nomes não importam. A separação importa.

helper_output:
  stderr_retained_per_call_bytes: 16384
  stderr_retained_process_bytes: 262144
  stderr_agent_excerpt_bytes: 4096
  shutdown_grace_seconds: 5
  retain: tail

Essa configuração evita uma falha comum em que a equipe define um limite para a resposta do agente e presume que o host está protegido. O host ainda lê e armazena todos os dados antes de reduzir a resposta. O limite retido por chamada protege uma ação. O limite do processo protege ações simultâneas. O limite do trecho enviado ao agente protege o contexto que o modelo precisa compartilhar com o restante do trabalho.

Não use uma única chave global chamada quiet. Ela torna as falhas de produção mais difíceis de diagnosticar e incentiva os desenvolvedores a reativar logs ilimitados quando precisam de evidências. Mantenha a saída normal concisa, exponha um modo de depuração controlado por uma janela curta e preserve no registro da chamada o fato de que o modo de depuração estava ativo.

Evite a recomendação popular de redirecionar o stderr para /dev/null. As pessoas a recomendam porque ela remove a paralisação imediata e mantém as respostas do agente organizadas. Ela também elimina a primeira pista útil quando um auxiliar SSH não consegue autenticar, uma verificação de certificado falha ou um comando remoto retorna um erro inesperado. Em vez disso, drene, limite e identifique o fluxo.

O truncamento deve ser visível, não dramático

O truncamento é seguro quando é explícito e quando o sistema continua drenando o fluxo. Ele é inseguro quando um leitor posterior não consegue saber se a mensagem de erro está completa, quando o bridge para de ler e bloqueia o processo filho ou quando a saída descartada pode conter o único relato de uma ação que não tem outro registro.

O trecho final retido deve começar com um marcador produzido pelo bridge, não pelo auxiliar. Por exemplo:

[stderr truncated: kept last 16384 of 184320 bytes]
connection retry 18 failed: remote side closed the channel

Esse marcador faz parte do registro, não é decoração. Ele informa ao usuário por que a primeira linha visível parece abrupta e impede que um agente trate um stack trace parcial como uma explicação completa. Se você mantiver um prefixo e um trecho final, informe as duas quantidades de bytes. Nunca una os dois silenciosamente.

Defina os limites partindo da concorrência esperada, não copiando um número de outro projeto. Pergunte quantas ações uma execução de agente pode manter simultaneamente, quantas execuções o host aceita, quanta memória os diagnósticos podem consumir durante um minuto ruim e quanto texto uma pessoa consegue analisar de forma útil. A última resposta costuma ser muito menor do que as pessoas imaginam.

Mantenha o resultado da ação separado do trecho de saída. Uma ação HTTP bem-sucedida deve retornar seu resultado estruturado intencional mesmo que o stderr tenha atingido o limite, a menos que o próprio auxiliar use o excesso como sinal de falha. Da mesma forma, um fluxo stderr limpo não prova que uma ação foi bem-sucedida. Trate os diagnósticos como um campo entre várias observações.

Testes de excesso devem acompanhar os testes normais de integração

Registre o ciclo de vida antes dos diagnósticos
Os diários de Sessions e Activity separam a execução do agente de cada chamada HTTP ou SSH individual.

Um auxiliar que escreve stderr demais não é um teste exótico de segurança. É um teste básico de confiabilidade. Bibliotecas ficam detalhistas depois de uma mudança de versão, clientes remotos repetem avisos durante novas tentativas e uma entrada malformada pode disparar um loop de erros. Se o bridge só encontra auxiliares silenciosos e caminhos felizes nos testes, ele não tem evidências de que seu tratamento de processos funciona sob pressão.

Comece com um fixture que emita uma quantidade fixa de stderr, termine com um status escolhido e não faça nenhum trabalho externo. Em um sistema semelhante ao Unix, este comando cria um excesso deliberado para um harness de teste local:

yes helper-diagnostic 1\u003e\u00262

Execute-o com um prazo curto. O resultado esperado não é apenas o disparo do prazo. Confirme que o bridge não retém mais do que a quantidade configurada, marca o truncamento, encerra o processo filho, drena os fluxos até que sejam fechados e grava um evento final do ciclo de vida.

Depois, acrescente os casos que revelam erros de ordenação:

  • Um auxiliar escreve stderr antes de aguardar a aprovação.
  • Um auxiliar escreve durante a aprovação e sai imediatamente depois dela.
  • Um auxiliar conclui a ação externamente, enche o stderr e recebe um cancelamento durante a limpeza.
  • Um wrapper sai enquanto um descendente mantém o stderr aberto.
  • Um auxiliar escreve sequências de bytes inválidas e uma única linha maior que o limite retido.

Meça um pequeno conjunto de fatos em cada caso: pico de bytes de diagnóstico retidos, tempo até a aprovação, tempo entre o cancelamento e o encerramento do processo, estado final e presença do registro de chamada esperado. Não se contente com um teste que apenas verifica se uma mensagem de erro contém «truncated». Essa palavra pode aparecer enquanto uma tarefa de leitura continua bloqueada ou enquanto o registro final nunca chega ao armazenamento.

Execute os mesmos fixtures com chamadas simultâneas. Um limite por chamada pode parecer correto isoladamente e ainda falhar quando todas as chamadas atingem seus limites ao mesmo tempo. Teste também a desconexão de um cliente. O processo do agente pode desaparecer, mas o host ainda precisa concluir ou cancelar a ação de uma forma definida.

A verificação final é a validação offline da cadeia de auditoria e a comparação com o ciclo de vida esperado pelo fixture. A verificação pode informar se os registros armazenados foram alterados. A comparação com o fixture informa se o bridge gravou, desde o início, os registros que deveria ter gravado. Você precisa dos dois.

Mantenha os logs úteis sem deixá-los executar a ação

A regra útil é simples: o stdout transporta mensagens do protocolo MCP, os resultados estruturados transportam os resultados das ações e o stderr transporta diagnósticos limitados. Quando esses canais têm funções diferentes, o momento da aprovação, o encerramento, a contabilização de memória e os registros de auditoria deixam de disputar o mesmo texto não estruturado.

Comece pelo auxiliar que já lhe causou problemas: aquele que tenta novamente de forma ruidosa, trava depois de um cancelamento ou imprime uma resposta remota inteira quando falha. Coloque-o atrás de um leitor com limite e execute o fixture de excesso até que o registro da ação continue fiel aos fatos. Logs silenciosos são agradáveis. Logs limitados são controle operacional.

FAQ

A saída do stderr pode realmente travar um agente MCP?

Sim. Se o processo principal capturar o stderr sem um limite, um auxiliar pode transformar a saída de diagnóstico em memória retida ou encher um pipe que bloqueia o auxiliar. As mensagens MCP podem estar normais enquanto o processo que as transporta fica preso por causa dos próprios logs.

Um servidor MCP deve escrever logs no stdout ou no stderr?

Não envie logs para o stdout. O transporte stdio reserva o stdout para mensagens do protocolo, então uma única linha de diagnóstico pode corromper o fluxo JSON-RPC. Envie os diagnósticos para o stderr e faça o host drenar e limitar esse fluxo.

Qual limite de stderr devo definir para um auxiliar de agente?

Um bom ponto de partida é definir um limite pequeno em bytes por chamada, um trecho final retido ainda menor e um limite rígido para todo o processo. Os números exatos dependem da concorrência e da memória disponível, mas o limite precisa ser explícito e observável, não uma propriedade acidental do runtime do host.

É seguro truncar o stderr de um auxiliar?

Mantenha um trecho final limitado, registre o total de bytes recebidos e marque a chamada como truncada. Um registro de auditoria completo não precisa conter uma cópia completa de cada linha de depuração. Ele precisa explicar com honestidade o que foi executado, o que aconteceu e quais evidências foram descartadas.

Logs detalhados podem atrasar um pedido de aprovação?

A aprovação deve acompanhar o ciclo de vida da ação, não o volume de logs. Inicie o relógio da aprovação quando a ação se tornar elegível para aprovação humana e continue drenando o stderr enquanto o cartão estiver visível.

Preciso drenar stdout e stderr ao mesmo tempo?

Sempre leia os dois fluxos ao mesmo tempo. Drenar apenas o stdout pode causar um deadlock quando o processo enche o pipe do stderr, e drenar apenas o stderr pode causar o mesmo problema no sentido inverso quando o auxiliar emite uma resposta grande.

O que um log de auditoria deve registrar quando um auxiliar é encerrado?

Registre a ação tentada antes do dispatch e depois indique se o dispatch começou, se foi concluído e se a saída foi truncada. Se o auxiliar continuar ativo depois que o cliente desaparecer, ou se o cliente sair primeiro, o diário deve registrar isso em vez de sugerir um resultado limpo.

Um timeout me protege contra excesso de logs?

Não. Um timeout curto limita o tempo decorrido, enquanto um limite de stderr controla a quantidade de dados retidos e a pressão no pipe. Você precisa dos dois, além de um caminho de cancelamento que feche os fluxos e aguarde o encerramento do processo.

Como testar auxiliares MCP barulhentos?

Use um auxiliar real que emita uma quantidade controlada de stderr e execute-o pelo mesmo bridge e fluxo de aprovação usados em produção. Meça o pico de bytes retidos, o tempo até a aprovação, a latência do cancelamento, o status de saída e se todos os registros do ciclo de vida aparecem.

Por que um gateway de ações deve limitar os logs dos subprocessos?

Um gateway que executa ações em nome de um agente deve tratar a saída do auxiliar como entrada não confiável. Ele deve preservar o trecho final útil e os diagnósticos, evitando que um agente ou uma dependência com defeito consuma memória ou mantenha uma ação aberta indefinidamente.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov