maestro/docs/tools/webfetch.md
oss-sync 29ccaf1e92
Some checks failed
CI / build-and-test (push) Has been cancelled
sync: update from private repo (dfadcd5f)
2026-06-23 06:38:48 +00:00

111 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WebFetch
URL を HTTP GET してレスポンス本文を取得するツール。静的ページ向け。
## 基本
```js
WebFetch({ url: "https://example.com/article", timeout: 30 })
```
- HTML は **readability 抽出**でクリーンな Markdown に変換されて返る(ナビ・広告・ヘッダー・フッターを除去し、見出し・リスト・テーブル・リンクは保持)
- JSON / XML / プレーンテキストもそのまま取得可能
- リダイレクトは自動で追従
返却テキストは context 節約のため約 10,000 文字で切り詰められる。**スペースタスクでは全文(未切り詰め)が `source/` に保存される**ので、切り詰めが起きると末尾に `... (truncated; full version saved to source/<file>)` という案内が付く。全文を読みたいときは保存された `source/` のファイルを `Read` で開けばよい。
## いつ使うか
| 状況 | 使うツール |
|------|-----------|
| 静的 HTML ページ | **WebFetch** |
| JS で動的レンダリングされる SPA | BrowseWeb |
| ボタン・フォーム操作が必要 | BrowseWeb |
| ファイルダウンロード | DownloadFile |
| 検索結果を一覧で取得 | WebSearch |
WebFetch は軽量で速い。BrowseWeb はブラウザ起動コストがかかるので、できる限り WebFetch を優先する。
## クリーン本文抽出readability
取得した生 HTML は、記事本文だけを取り出す readability エンジンで処理してから返す。
内部パイプラインは `HTML → linkedom で DOM 化 → @mozilla/readability で記事抽出 → turndown(+gfm) で Markdown 化`
- **除去されるもの**: ナビゲーション、広告バナー、ヘッダー、フッター、サイドバー等のボイラープレート
- **保持されるもの**: 見出し(`#` 記法、箇条書き、番号付きリスト、テーブルGFM 記法)、リンク、コードブロック
- 相対リンクは取得 URL を基準に絶対 URL へ変換される
- `selector` を指定すると、その CSS セレクタにマッチする要素のサブツリーだけをクリーン抽出する(見つからなければページ全体の抽出にフォールバック)
抽出に失敗するページ(記事構造のない LP、JS で本文を生成する SPA、空ページ等では、
従来の素朴なタグ除去にフォールバックするので WebFetch が失敗扱いになることはない。
本文がほぼ空のときは SPA の可能性が高いので `BrowseWeb` に切り替える。
### 全文は source へ、切り詰め版は agent へ
- agent のコンテキストに返るのは約 10,000 文字に切り詰めた版context 膨張を防ぐため)
- **スペースタスクでは、切り詰める前の全文クリーン Markdown が `source/` に保存される**
- 切り詰めが起きた場合、返却テキスト末尾に `... (truncated; full version saved to source/<file>)` が付く
- 病的に巨大なページ対策として、`source/` 保存も 2MB で打ち切る(その旨ノートを付す)
## レスポンス履歴
各 WebFetch 呼び出しは `logs/webfetch-history.jsonl` に記録される。後から「どの URL を取得したか」を振り返れる。
## スクリーンショット添付vlmEnabled 時のみ)
ワーカーが `vlm=true`(主 LLM が画像入力対応の場合、WebFetch は成功時に Playwright でファーストビュー1280×1600 viewportのスクショを撮り、LLM の文脈に `image_url` として自動添付する。天気・ダッシュボード・地図など、HTML テキスト抽出では情報が欠落しやすいサイトの理解を補う目的。
- 保存先: `logs/webfetch-screenshots/{timestamp}-{url-hash}.png`
- `logs/webfetch-history.jsonl` の各レコードに `screenshotPath` が記録される
- Playwright 未インストール・CAPTCHA・タイムアウト等で失敗しても WebFetch 本体は成功扱い(テキストだけ返る)
- 無効化: `config.yaml``tools.webfetch_screenshot: false`
- タイムアウト: `tools.webfetch_screenshot_timeout_ms`(デフォルト 15,000
## SSRF 保護
ローカル/プライベート IP127.x.x.x, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, ::1, fc00::/7 等)はデフォルトでブロックされる。社内ホストへアクセスする必要がある場合は Settings UI の「SSRF Allowed Hosts」に追加する。
## トラブルシューティング
- **本文がほぼ空**: SPA で JS レンダリングが必要 → BrowseWeb に切り替え
- **タイムアウト**: `timeout` パラメータを増やす(デフォルト 30 秒)
- **403/404**: User-Agent 制限・bot 検出の可能性 → BrowseWeb なら回避できる場合あり
- **SSRF blocked**: ローカル/プライベート IP に向いている → 設定追加またはターゲット見直し
## エラー時のフォールバック方針
WebFetch がエラーを返した場合、以下の原則で `BrowseWeb` にリトライする:
| エラー | BrowseWeb で再試行すべきか |
|---|---|
| HTTP 403 / 429 | **する** — bot 検出・レート制限。ブラウザ User-Agent で回避できる可能性 |
| HTTP 502 / 503 / 504 | **する** — CDN/upstream の一時的エラー。別の HTTP スタックで成功することがある |
| ネットワークエラー / タイムアウト | **する** — 動的ページが静的 fetch に応答しないケースが多い |
| HTTP 404 / 401 / 410 | しない — 永続的なエラー。URL を見直すべき |
| `invalid_url` | しない — URL の記述ミス |
| `ssrf_blocked` | しない — セキュリティ設定。Settings で allowed hosts を追加 |
| `pdf_blocked` | しない — `DownloadFile` + `ReadPdf` の組み合わせを使う |
| `binary_blocked` | しない — `DownloadFile` でバイナリ保存する |
| 本文が極端に短い(< 200 chars | **する** SPA の空シェルを取得した可能性が高い |
| `Just a moment...` Cloudflare challenge | **する** ブラウザで JS challenge を通過できる |
リトライ時は同じ URL `BrowseWeb({ url: "..." })` に渡すだけでよい`BrowseWeb` はジョブ内で Cookieセッションを保持するので複数回呼んでもログイン状態は引き継がれる
## バイナリの扱い
WebFetch は取得 body の先頭 8KB sniff magic byte / NUL / 不正 UTF-8 / 制御文字比率)、
バイナリと判定したら**コンテキストに展開せずブロック**するContent-Type が欠落詐称
例: `.xls` `text/plain`していても実バイトで検出するバイナリを処理したい場合は
`DownloadFile` `input/` に保存し`ReadExcel` / `ReadPdf` 等を使うテキスト body
5MB で打ち切られる末尾に `[truncated: body exceeded 5MB]`)。
## ソースライブラリへの蓄積(スペースタスク)
スペースのタスクで WebFetch がページ本文を取得すると、**クリーン抽出した全文 Markdown**agent への
返却で切り詰める前のもの `source/` に保存され出典メタURLタイトル取得日時サイズ
`source/index.jsonl` に追記される
これによりそのスペースのソース資料)」が自動で溜まり後から追加調査やグラウンディングに使える
同一 URL は重複保存しない既に index にあればスキップ)。スペース文脈でないタスク
ephemeral / gitea issue では従来どおり蓄積しない`logs/raw/` への生データ保存は従来どおり
BrowseWebブラウザ閲覧 DownloadFile`section: "source"`も同じ `source/index.jsonl` に合流する