Dev Tools (adk-devtools)

adk-devtools は、コーディングエージェントが必要とする内側ループ用のツールセットです。読み取り、編集、検索、実行を行い、各操作は ワークスペースディレクトリにスコープされます。これは adk-core のみに依存する独立した公開可能な crate であり、任意の LlmAgent と組み合わせられます(CodingAgent harness があなたのために接続します)。

ツール

DevToolset は、6 つのツールをまとめた Toolset です:

ツールパラメータ挙動
read_filepath, offset?, limit?ファイル内容を行番号付きで返す
write_filepath, contentファイルを作成/上書きする(親ディレクトリを作成する)
edit_filepath, old_string, new_string, replace_all?完全一致文字列置換
globpattern, path?glob に一致するファイルを一覧表示(例: src/**/*.rs
greppattern, path?, glob?, case_insensitive?正規表現による内容検索
bashcommand, timeout_secs?ワークスペースのルートでシェルコマンドを実行

知っておくべき安全動作を2つ挙げます。

  • edit_file は、そのファイルをセッション内で事前に read_file していることを要求し、デフォルトでは対象文字列は ちょうど1回 出現していなければなりません(これを上書きするには replace_all)。これは、無条件の上書きを防ぐためです。
  • grep は、一般的なビルド/VCS ディレクトリ(target.gitnode_modules、…)や、バイナリ/大きすぎるファイルをスキップします。

bash ツールは、コマンドの実行中に ToolContext::emit_progress を使って stdout/stderr を1行ずつ ストリーム します。そのため、UI はライブのターミナルを表示できます。各チャンクはエージェントの EventStream 上の部分イベントとして到着し(event.tool_progress_stream() で検出)、完全な出力は最終結果としてツールから返されます。streaming_bash の例ツールからの進行状況のストリーミング を参照してください。

Workspace

Workspace は、すべての操作をディレクトリを起点にし、少数のポリシーを強制します。

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);
  • パスの包含 — ルート外に解決されるパスは拒否されるため、エージェントは ../../etc/... を読み書きできません。包含は、文字通りのパスではなく 解決後 のパスに対して強制されます。つまり、ルートの外を指すシンボリックリンクは、見かけ上はルート内にあっても拒否されます。これは、シンボリックリンクされた末尾コンポーネントとシンボリックリンクされた親ディレクトリの両方をカバーするため、リダイレクトされたディレクトリ経由での作成も拒否されます。ターゲットが workspace 内に収まるシンボリックリンクはそのまま機能し続けます。リポジトリには内部リンクが正当に含まれるためです。

    このチェックはロックではありません。チェックとその後の open の間に植え込まれたシンボリックリンクは、それでもたどられてしまいます。この隙を塞ぐには、プラットフォームの no-follow セマンティクスを伴う descriptor-relative なトラバーサルが必要です。ファイルツールは、歩き回るエージェントに対する包含として扱い、workspace に並行して書き込める adversary に対する分離としては扱わないでください。

  • 読み取り専用モードWorkspace::read_only(..) は変更系ツールを完全に隠します(モデルが見るのは read_file/glob/grep だけです)。

  • bash 環境はクリアされる — コマンドは PATHHOMELANGLC_ALLTMPDIRTERMUSERSHELL だけを受け取るため、エージェントプロセスが保持している provider API キーは env では読み取れません。Workspace::inherit_env(true) は、以前の「すべて渡す」動作を復元し、env_allowlist はそのセットを置き換えます。

  • bash のタイムアウト + 出力上限 — 長すぎる、またはおしゃべりすぎるコマンドは制限されます。タイムアウトしたコマンドは プロセスグループ として kill されるため、それが開始したものもすべて kill されます。以前は直接の子プロセスにだけ signal が送られ、子孫は生き残っていました。

直接使う

ツールセットを任意のエージェントに追加します。

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 は workspace が許可するツールだけを公開するため、読み取り専用の workspace なら自動的に読み取り専用のエージェントになります。

サンドボックスモデル

Phase 1 は bashhost-local に実行します(sh -c、作業ディレクトリは root に固定)し、タイムアウトとクリアされた環境を伴います。これで何が得られて、何が得られないか:

強制される強制されない
ファイルツールは、symlink 経由を含め、ルート外を解決できないbash は引き続き絶対パスを使える — 作業ディレクトリは OS の境界ではない
コマンドは agent の環境変数を読み取れないコマンドはネットワークにアクセスできる
タイムアウトによりコマンドとその子孫が終了するメモリや CPU を制限するものはない

つまり、これはパス内に限定され、環境は分離され、境界はあるものの、OS は分離されていません。ポリシーの語彙は adk-codeSandboxPolicy と一致しています。強い分離が必要な場合は、コンテナ化された実行環境の背後で bash を実行してください(design doc を参照)。adk-guardrail(コマンドの allowlist、シークレットの秘匿化)およびトークン化されたツール向けの adk-auth(例: GitHub)と組み合わせてください。

次へ: The harness →