Ir para o conteúdo

47 · Verificação de grafos de agentes

A Verificação de Grafos de Agentes (Agent Graph Verification) verifica cada caminho de um agente, ou de uma equipe de agentes, antes de ele entrar no ar. Você envia o grafo do agente e o catálogo pelo qual as suas ferramentas são classificadas; toda ferramenta que o grafo consegue alcançar é confrontada com a sua verificação, a sua confirmação, as suas regras de ordem e o que uma escrita desfazível exige, e cada caminho que escapa de uma delas volta como um achado, com o caminho que chega a ela. Este capítulo trata da exportação que ela lê, do que ela decide e de como ler o que ela encontra.

Um agente construído com o Construtor de Bots é verificado assim antes do seu primeiro turno, e no CI pelo stalwart verify (capítulos 45 e 46). Este capítulo é a mesma verificação para qualquer grafo: um que você construiu com o LangGraph, ou um que você mesmo exporta.

O que ela lê

Três entradas, para o modo graph:

  • a exportação, o grafo como um documento qls-graph/1: os seus nós, as suas arestas e onde ele pausa para uma pessoa;
  • o catálogo, que diz o que é cada ferramenta: uma leitura ou uma escrita, como uma escrita é desfeita, as suas regras de ordem, se ela lê o mundo exterior, e as demais palavras do capítulo 30;
  • um rulebook, opcionalmente: uma política Colang cujas regras a verificação de ferramentas aplica, caçada junto com o grafo.

Os campos da exportação:

Campo Significado
nodes O id de cada nó -- único no seu grafo e sem /, que qualifica os nós de um subgrafo pelo seu caminho --, o seu kind e as ferramentas que um nó de ferramentas associa.
edges O from de cada aresta, o seu kind (fixed, conditional, command ou stalwart_edge) e os destinations que o seu autor declarou. Uma aresta condicional ou Command exportada com destinations: null pode chegar a qualquer nó, e é relatada como QG015.
sends Ramificações Send: um nó que inicia vários ramos de uma vez.
interrupts Onde o grafo pausa para uma pessoa, e a ferramenta cuja chamada a pessoa confirma ali.
subgraphs Os grafos que os nós subgraph executam, por nome, exportados pelas mesmas regras e incorporados em cada uso.

Um agente do Construtor de Bots escreve a sua exportação com stalwart verify agent.yaml --export-only graph.json, ou Agent.export() em Python. Um grafo do LangGraph é exportado com export_graph (capítulo 27), que lê o grafo compilado e nomeia os nós onde um modelo escolhe.

Perguntando

result = client.verify_graph("desk.graph.json", catalogue="desk.catalogue.json", session_steps=2)
for finding in result.findings:
    print(finding.rule, finding.severity, finding.location)   # the line that declared the node
    print("  fix:", finding.fix)

A requisição é um job como qualquer outro (capítulo 3): mode: "graph", a exportação e o catálogo como entradas, e session_steps como operando. Ela precisa da permissão graph_check, cada job é um graph_checks, e um grafo é limitado pelo graph_nodes do seu plano, contado depois de os seus subgrafos serem incorporados onde são usados (capítulo 16).

O que ela decide

Para cada ferramenta, o grafo é vasculhado em busca de um caminho que quebre uma destas:

Obrigação Levantada por Quebrada quando Relatada como
A verificação de ferramenta Toda ferramenta que um nó associa Um caminho executa a ferramenta num nó tools_plain, onde a sua chamada pula a verificação. QG001
Uma confirmação Uma escrita para a qual o grafo pausa Um caminho executa a escrita num nó comum antes de a pessoa a confirmar. QG001
A regra de ordem order.after A ferramenta é executada antes de todas as ferramentas depois das quais deve vir. QG014
A regra de ordem order.not_after A ferramenta é executada depois de uma que nunca deve seguir, ou depois de qualquer ferramenta que lê o exterior, quando a regra nomeia untrusted. QG014
A regra de ordem order.at_most A ferramenta é executada mais vezes do que o seu limite. QG014
Contaminação Uma escrita, e toda ferramenta marcada reads_outside A escrita é executada, sem confirmação, depois de uma ferramenta que leu o exterior: no mesmo agente, ou depois de uma transferência vinda de outro. QG011, QG012
A saga Uma escrita compensável e uma irreversible A escrita compensável pode ser executada depois da irreversível. QG013
Recuperação Uma escrita sem compensation que não é irreversible Outra escrita compartilha um caminho com ela. QG105

Um caminho que quebra uma delas é um achado, e cada achado nomeia a regra sob a qual é relatado:

Regra Título Levantada quando Como corrigir
QG001 Verificação ausente a ação é alcançável e nada nas regras a relaciona com o controle Adicione o controle como condição em toda rota que registra a ação. O patch nomeia a condição e os fluxos onde colocá-la; um fluxo novo não pode apertar a ação, porque as guardas de uma ação se combinam como um OU.
QG003 Fuga em vários turnos a obrigação vale num turno e falha na profundidade de conversa declarada Vincule o controle ao passo que o usa -- leia-o no mesmo turno que a ação, ou leve-o junto com a chamada que aprovou -- e analise de novo na mesma profundidade.
QG011 Delegado confuso uma ferramenta privilegiada é alcançável sob contaminação sem confirmação nem recusa Associe a ferramenta ao nó de ferramentas protegido, para que uma chamada que carrega o rótulo seja confirmada ou recusada; ou marque a ferramenta de origem como reads_outside onde ainda não estiver, e analise de novo.
QG012 Injeção em cascata como um delegado confuso, quando a contaminação entrou num agente ou subgrafo diferente daquele que age Associe a ferramenta ao nó de ferramentas protegido do agente que age, para que uma chamada que carrega um rótulo do agente que transferiu seja confirmada ou recusada; ou faça a transferência passar por uma confirmação.
QG013 Irreversível antes do desfazível uma escrita compensável pode ser executada depois de uma irreversível num caminho, sem que a confirmação do passo irreversível o tenha dito Mova o passo irreversível para o fim, ou associe-o ao nó de ferramentas protegido para que a sua confirmação diga que os passos seguintes não podem desfazê-lo.
QG014 Regra de ordem contornável uma ferramenta é alcançável com a trava de uma regra de ordem no estado proibido Associe a ferramenta ao nó de ferramentas protegido, onde as suas regras de ordem são verificadas sobre o histórico da sessão, e analise de novo.
QG015 Rota não declarada uma aresta condicional ou Command sem destinos declarados Declare os destinos da aresta: um path_map, uma anotação Command[Literal[...]] ou uma stalwart_edge com o conjunto permitido.
QG016 Caminho não modelado uma campanha de ataque aberta realizou uma chamada privilegiada num grafo em que o motor não encontrou passagem Exporte de novo o grafo a partir do código que roda e analise de novo; depois compare o rastro do atacante com o export para descobrir o que falta no export.
QG105 Escrita irrecuperável uma escrita sem compensação, não marcada como irreversível, num caminho com outra escrita Declare a compensação da ferramenta no catálogo, ou marque-a como irreversível para que uma pessoa a confirme sabendo disso.
QG107 Canal entre agentes sem autenticação uma transferência para ou de um agente remoto trafega por um canal que o catálogo declara sem autenticação Declare e use mtls, oauth2 ou signed_messages no canal; ou aceite o ponto de atenção indicando a camada que o autentica.

A página completa de cada regra, com a sua categoria, as suas funções do AI RMF e as suas entradas da OWASP, está em as páginas de regras.

Lendo um achado

Cada achado traz:

  • a regra e a sua severidade, pelo que a ferramenta pode fazer: uma escrita destrutiva ou irreversível é Crítica, uma escrita é Alta, uma leitura é Média;
  • a testemunha: o caminho pelo grafo que chega à ferramenta, nó a nó, com as escolhas que os modelos fizeram ao longo dele;
  • a localização: a linha do arquivo que declarou o nó, para que um achado sobre um agent.yaml abra na linha do agente;
  • a correção, nos termos do catálogo ou do grafo;
  • uma impressão digital que sobrevive a edições não relacionadas, para que o mesmo achado seja reconhecido varredura após varredura.

Os achados também voltam como SARIF, para a varredura de código. Uma testemunha pode ser reproduzida no seu próprio grafo, com toda ferramenta substituída por um stub e um modelo roteirizado fazendo as escolhas da testemunha: replay_witness, ou stalwart verify --replay para um agente do Construtor de Bots. Um achado que não se reproduz é uma discordância entre o motor e o grafo que roda, e é relatado primeiro.

Até que profundidade ela olha

Um caminho é procurado ao longo de um número de turnos de conversa: session_steps, um quando não informado. Uma verificação lida uma vez e usada depois, como uma aprovação dada num turno e gasta em outro, pode valer num turno e falhar em dois; isso é relatado como QG003, um escape de múltiplos turnos. Pergunte na profundidade que as suas conversas alcançam.

Os limites

  • Um nó de modelo é lido como escolhendo qualquer coisa. A verificação prova que nenhum caminho chega a uma ferramenta sem a sua verificação, a sua confirmação ou a sua regra de ordem; ela não prova que o modelo escolhe bem.
  • Um nó que não é da própria Stalwart é opaco. O seu código não é lido: considera-se que ele pode fazer qualquer coisa que as suas arestas permitem, e é por isso que uma aresta condicional não declarada, uma cujos destinos ninguém declarou, pode chegar a todo nó e é relatada como QG015.
  • Um resultado limpo vale até a profundidade verificada, e não além.
  • As declarações do catálogo são aceitas como declaradas. Uma ferramenta declarada como leitura que escreve é verificada como leitura. O próprio código das ferramentas é conferido pelas verificações de código, não aqui (capítulo 46).
  • O grafo verificado é a exportação que você enviou. Se o grafo que roda é diferente dela, o resultado é sobre a exportação; reproduzir as testemunhas, e a equipe vermelha do capítulo 33, é como uma diferença aparece.