Ferramentas de Dev (adk-devtools)
adk-devtools é o conjunto de ferramentas de loop interno que um agente de programação precisa — ler, editar,
buscar e executar — com cada operação limitada a um diretório de workspace. É
um crate independente e publicável, dependendo apenas de adk-core, então ele se compõe com
qualquer LlmAgent (o harness CodingAgent o conecta para você).
As ferramentas
DevToolset é um Toolset que reúne seis ferramentas:
| Ferramenta | Parâmetros | Comportamento |
|---|---|---|
read_file | path, offset?, limit? | Retorna o conteúdo do arquivo, com numeração de linhas |
write_file | path, content | Cria/sobrescreve um arquivo (cria diretórios pai) |
edit_file | path, old_string, new_string, replace_all? | Substituição exata de string |
glob | pattern, path? | Lista arquivos que correspondem a um glob (por exemplo, src/**/*.rs) |
grep | pattern, path?, glob?, case_insensitive? | Busca de conteúdo com regex |
bash | command, timeout_secs? | Executa um comando de shell na raiz do workspace |
Dois comportamentos de segurança que vale conhecer:
edit_fileexige umread_fileprévio desse arquivo na sessão, e por padrão a string de destino deve ocorrer exatamente uma vez (replace_allpara substituir). Isso protege contra sobrescritas cegas.grepignora diretórios comuns de build/VCS (target,.git,node_modules, …) e arquivos binários/grandes demais.
A ferramenta bash faz streaming de stdout/stderr linha a linha via
ToolContext::emit_progress enquanto o comando é executado, para que as UIs possam mostrar um
terminal ao vivo. Cada chunk chega como um evento parcial na EventStream do agente
(detecção com event.tool_progress_stream()); a saída completa ainda é
retornada como resultado final da ferramenta. Veja o
exemplo de streaming_bash e
Streaming Progress from a Tool.
O Workspace
Um Workspace ancora cada operação em um diretório e impõe uma pequena política:
use adk_devtools::Workspace;
use std::time::Duration;
let ws = Workspace::new("./my-repo"); // read-write, bash enabled
let ws = Workspace::read_only("./my-repo"); // explore/plan: no writes, no bash
let ws = Workspace::new("./my-repo")
.allow_bash(false) // file edits, but no shell
.bash_timeout(Duration::from_secs(60))
.max_output_bytes(512 * 1024);
-
Contenção de caminho — qualquer caminho que resolva fora da raiz é rejeitado, então o agente não pode ler ou escrever
../../etc/.... A contenção é aplicada ao caminho resolvido, não apenas ao literal: um symlink apontando para fora da raiz é rejeitado mesmo que esteja lexicalmente dentro. Isso cobre um componente final symlinkado e um diretório pai symlinkado, então a criação por meio de um diretório redirecionado também é recusada. Um symlink cujo destino permaneça dentro do workspace continua funcionando, já que repositórios legitimamente contêm links internos.A verificação não é um bloqueio. Um symlink colocado entre a verificação e a abertura subsequente ainda seria seguido; fechar essa janela exige travessia relativa ao descritor com semântica no-follow da plataforma. Trate as ferramentas de arquivo como contenção contra um agente que vagueia, não como isolamento contra um adversário que pode escrever no workspace simultaneamente.
-
Modo somente leitura —
Workspace::read_only(..)oculta completamente as ferramentas que modificam (o modelo só vêread_file/glob/grep). -
Ambiente
bashé limpo — o comando recebe apenasPATH,HOME,LANG,LC_ALL,TMPDIR,TERM,USEReSHELL, então as chaves de provedor API mantidas pelo processo do agente não podem ser lidas comenv.Workspace::inherit_env(true)restaura o antigo comportamento de passar tudo, eenv_allowlistsubstitui o conjunto. -
bashtimeout + limites de saída — comandos longos ou muito verbosos são limitados. Um comando que estoura o tempo é encerrado como um grupo de processos, então tudo o que ele iniciou também é encerrado; antes apenas o filho direto era sinalizado e os descendentes sobreviviam.
Usando diretamente
Anexe o conjunto de ferramentas a qualquer agente:
use adk_devtools::{DevToolset, Workspace};
use adk_agent::LlmAgentBuilder;
use std::sync::Arc;
let agent = LlmAgentBuilder::new("coder")
.model(model)
.toolset(Arc::new(DevToolset::new(Workspace::new("./my-repo"))))
.build()?;
DevToolset expõe apenas as ferramentas permitidas pelo workspace, então um
workspace somente leitura gera automaticamente um agente somente leitura.
Modelo de sandbox
A fase 1 executa bash localmente no host (sh -c, diretório de trabalho fixado na raiz) com um
timeout e um ambiente limpo. O que isso oferece e o que não oferece:
| Aplicado | Não aplicado |
|---|---|
| As ferramentas de arquivo não podem resolver fora da raiz, inclusive por meio de symlinks | bash ainda pode usar caminhos absolutos — o diretório de trabalho não é um limite do sistema operacional |
| O comando não pode ler as variáveis de ambiente do agente | O comando pode acessar a rede |
| Um tempo limite encerra o comando e seus descendentes | Nada limita a memória ou a CPU |
Então, ele é contido pelo caminho, isolado do ambiente e delimitado, mas não isolado do SO. O vocabulário da política se alinha com adk-code's SandboxPolicy; para
isolamento forte, execute bash atrás de um executor conteinerizado (veja o
design doc).
Combine com adk-guardrail (listas de अनुमति de comandos,
mascaramento de segredos) e adk-auth para ferramentas
com tokenização (por exemplo, GitHub).
Próximo: O harness →