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.yamlabra 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.