この記事の出発点はかなり衝撃的です。著者が以前使った AI の OSINT(Open Source Intelligence)ツールは、調査結果としてこんなものを出したそうです。

でも、全部ウソだった。
対象の Twitter ハンドルではないし、GitHub の URL はリポジトリそのもの、IP も SSH バナーも組織名も捏造。しかも、見た目がきれいだから余計にたちが悪い。
ここがこの記事の核心です。
LLM(大規模言語モデル、要するに ChatGPT のような「文章を作るのが上手いAI」)は、自然な文章や、いかにもありそうなフォーマットを作るのが得意です。ところが OSINT やセキュリティの世界では、「それっぽい」ではダメで、実在する情報だけが必要です。
私はここ、かなり重要だと思いました。
AI の失敗って、単に「知らない」と言ってくれればまだマシなんです。でも、セキュリティでは“見た目だけ正しい誤情報”が一番危ない。人間はつい信じてしまうからです。
著者は最初、よくある ReAct loop を試します。
ReAct は Reasoning + Acting の略で、ざっくり言うと「AIに考えさせ、必要ならツールを呼ばせ、結果を見て次を考えさせる」方式です。
イメージとしてはこんな感じです。
一見すると正しそうですが、問題はモデルがツール結果を“予測”してしまうこと。
つまり、ツールを呼ぶ前から「たぶんこんな結果だろう」と勝手に物語を作ってしまい、実際の結果が返ってきても、その物語に引っ張られてしまうんです。
著者は次のような指示も試したそうですが、うまくいかなかったとのこと。
それでもモデルは、要約したり、文脈を足したり、挙げ句の果てに存在しない結果まで並べたりした。
つまり、AIが「OSINT analyst を演じている」状態であって、実際に調査しているわけではなかった、というわけです。
これ、AIアプリ全般に通じる話だと思います。
「会話として自然」なことと、「道具として正確」なことは、かなり違うんですよね。
著者がたどり着いた答えは、Anthropic の native tool use API です。
これは、モデルに「ツールを使いたい」とテキストで言わせるのではなく、構造化された tool call として扱う仕組みです。
ポイントはここです。
stop_reason: "tool_use" で止まるtool_result としてモデルへ返すつまり、モデルが勝手に「こういう結果が返るはず」と作文する余地を減らしているんですね。
著者はこれを「幻覚(hallucination)が構造的に起きにくい」と表現しています。
この設計、かなり賢いと思います。
AIに“頭の中でそれっぽくやらせる”のではなく、システム側で現実を強制的に差し込む。セキュリティ用途では、こういう強い制約のほうが向いています。
この考え方を実装したのが、著者の OpenOSINT です。
ターミナルから OSINT 調査を実行できる、オープンソースの AI エージェントです。
構成は大きく 3 層に分かれています。
LLM の種類を抽象化する層です。
Anthropic、OpenAI、Ollama などを同じインターフェースで扱えるようにしています。
つまり、裏側のモデルを変えても、アプリの他の部分はあまり触らなくていい。これは地味ですがかなり便利です。
OSINT 用のツールを登録する層です。
@register_tool のような decorator(関数に付ける印のようなもの)で、ツールを追加できます。
例としては、メールアドレスから関連アカウントを探す search_email があり、内部では holehe を使っています。
holehe は、メールアドレスがどんなサービスで使われていそうかを調べるツールです。
実際に「モデルが考える → ツールを呼ぶ → 結果を見る」を回すループです。
ここで先ほどの native tool use API を使います。
著者の設計思想はかなり明快で、新しいツールを追加するにはファイル1つと decorator 1つで済むようにしているそうです。
こういう「増やしやすさ」は、実際の運用でかなり効きます。
OpenOSINT には、次のようなツールが含まれています。
search_email — メールに紐づくSNSアカウントを探すsearch_username — ユーザー名で 300以上のプラットフォームを調べるsearch_domain — サブドメイン列挙search_breach — データ漏洩に含まれているか確認search_whois — ドメインの登録者情報を調べるsearch_ip — IP の位置情報や ASN などを調べるgenerate_dorks — Google dork 用の検索URLを作るsearch_paste — Pastebin 系の流出情報を探すsearch_phone — 電話番号のキャリアや国などを調べる専門用語を少しかみ砕くと、
こうして見ると、AIが何でもやるというより、既存の調査ツールをうまく束ねる司令塔として働いているのがわかります。

ここ、記事の中でも特に納得感がありました。
単純な方法としては、毎回決まった順番でツールを回すやり方があります。
たとえば、
holehesherlockHaveIBeenPwned
みたいに固定するやり方です。
これはシンプルで再現性もありますが、問題は対象によって必要な調査が違うこと。
たとえば、
holehe と漏洩確認が有効という具合です。
特に面白いのは、著者がこんな流れを挙げているところです。
名前しかない人に対して、いきなり search_username("John Doe") を回してもあまり意味がない。むしろ generate_dorks で検索し、そこから @johndoe_dev のような実際のハンドルを見つけ、その後に search_username("johndoe_dev") を実行する。
この順番の判断を、エージェントが自分でできるわけです。

これは「自動化」というより、文脈を読んで次の一手を選ぶのが価値なんだ、という話です。
個人的にはここがいちばん本質だと思いました。AIエージェントは、全部を置き換える存在というより、調査の分岐をうまく選ぶ補助輪に近いのではないかと感じます。
記事では、実際に john.doe@example.com を調査した例が示されています。
実行内容のイメージはこんな感じです。

generate_dorks → 10個の検索URLを生成search_email → Spotify, WordPress, Gravatar, Office365 を発見search_breach → LinkedIn(2016)、Adobe(2013)の漏洩にヒットsearch_paste → 結果なしそしてレポートには、
がまとめられます。
著者は「レポートに書かれた内容はすべて実際のツール出力から来ていて、捏造はない」と強調しています。
これはOSINTではめちゃくちゃ大事です。
“見つけた風”ではなく、証拠に基づくレポートになっているからです。

率直に言うと、この記事は「AIがすごい」という話だけではありません。
むしろ、「AIにやらせてはいけないことをちゃんと分けた」のが良いのだと思います。
特に良いと感じた点は3つです。
LLM に自由作文をさせず、ツール結果はツール結果として扱う。
これは安全性の面でかなり大きいです。
OSINT は相手によって正解ルートが違うので、エージェント型のほうが自然です。

provider 抽象化、decorator でのツール登録、CLI ベースの利用など、ちゃんと使うことを考えて作られている。
研究デモで終わっていないのがいいですね。
著者自身も「こうしたい」として挙げている改善点があります。
search_email と search_breach は同時に走らせてもよさそう。今は順番に実行している。
confidence scoring
「ツールの直接結果なのか」「推論で得たのか」を分けて信頼度をつけたい。
streaming output
結果を最後まで待たず、途中から表示したい。
ここは、すごく現実的な改善案だと思います。
AIシステムって、正しさだけじゃなくて、速さ・見やすさ・追跡しやすさも重要なんですよね。
この記事のメッセージはかなり明快です。
AIをセキュリティ調査に使うなら、「賢そうに話す」ことより「現実のツール結果に縛る」ことが重要だ、という話です。

そして、そのためにはただプロンプトを工夫するだけでは足りない。
モデルのふるまいを変えるのではなく、アーキテクチャで幻覚を起こしにくくする必要がある、というのが著者の結論です。
私はこれ、AIエージェント設計のかなり良い教科書だと思いました。
特にセキュリティのように「嘘が致命傷になる分野」では、かなり説得力があります。
AIは万能の調査員ではない。でも、正しい枠組みで使えば、かなり強力な“調査補助”になる。この記事はその境界線をとても上手く示していました。
参考: Why Every AI+Security Tool I Tried Was Lying to Me (And What I Built Instead)