- 個人ポートフォリオサイトにIRCベースのAIエージェントを接続し、訪問者が実際のGitHubリポジトリのコード分析結果に基づいて質問への回答を得られる構成
- 単なる履歴書要約型チャットボットではなく、リポジトリの複製・テスト件数の計算・コード検証を行う実行型エージェントとして設計
- システムは公開用のnullclawと非公開のironclawの2つのエージェントに分離され、Tailscaleネットワークを通じて安全に通信
- IRCプロトコルを転送レイヤーとして採用し、セルフホスティング・標準化・低コストを同時に実現し、Haiku 4.5とSonnet 4.6モデルを役割別に分けてコストを1日2ドルに制限
- システム全体が10MB未満のバイナリ・5MB未満のメモリで動作し、セキュリティ・コスト・透明性をすべて確保した軽量AIインフラの事例として示されている
デジタルドアマンの構築
- 月額7ドルのVPSにAIエージェントを配置し、個人用IRCサーバーを転送レイヤーとして使ってGitHubリポジトリと接続した構成
- 訪問者はポートフォリオサイトでAIに質問を投げかけ、実際のコードに基づく回答を受け取れる
- 単なる履歴書要約型チャットボットではなく、コード分析による具体的な応答を提供
「履歴書を尋ねるチャットボット」の限界
- 大半のポートフォリオチャットボットは、履歴書の内容をモデルに注入して再構成するレベルにとどまっている
- この方式では新しい情報を提供できず、単なる形式的な会話に過ぎない
- 「テストカバレッジをどう管理しているか?」のような質問には、リポジトリを複製してテスト数を計算するような具体的な応答が必要
- そのため、直接コードにアクセスして分析できるインフラを構築した
システムアーキテクチャ
- 2つのエージェント、2台のサーバー、2つのセキュリティ境界で構成
- nullclaw: 公開用ドアマン。678KBのZigバイナリで、約1MBのRAMを使用
- 訪問者へのあいさつ、プロジェクト関連の質問応答、GitHubリポジトリの複製およびコードベースの検証を実行
- ironclaw: 非公開バックエンドエージェント。別システム上で動作
- メール、予定、個人コンテキストにアクセス可能
- nullclawからの複雑な要求を**#backoffice** IRCチャンネル経由で受け取る
- 2つのシステムはTailscaleで接続されており、公開サーバーは個人データにアクセスできない
IRCを選んだ理由
- 美学的一貫性: ポートフォリオサイトがターミナルUIベースのため、IRCクライアントが自然に馴染む
- 完全なセルフホスティング: Ergo IRCサーバー、gamja Webクライアント、nullclawのすべてを自前インフラで運用
- シンプルで標準化されたプロトコル: 30年の歴史を持つIRCはベンダーロックインがなく、API変更リスクもない
- 同じエージェントがWebクライアントだけでなく、irssiターミナルクライアントでも同様に動作
モデル選定と設計
- 大型モデルの使用は非効率であり、役割に応じてモデルを分けている
-
Haiku 4.5**: 会話と簡単な問い合わせを処理し、**超低遅延で応答
- Sonnet 4.6: コード分析や複雑な推論が必要な場合にのみ使用
- コスト上限: 1日2ドル、月30ドルに制限
- 悪意ある利用や過剰な会話によるコスト暴走を防止
- 階層型推論構造により、速度とコスト効率を両立
セキュリティ設計
- SSH: rootログイン無効化、鍵認証のみ許可、非標準ポートを使用
- ファイアウォール: SSH、IRC(TLS)、HTTPS(WebSocket)のみ開放
- Cloudflareプロキシ: TLS終端、レート制限、ボットフィルタリングを実施
- エージェントサンドボックス: 読み取り専用ツールのみ許可、1時間あたり10回のアクションに制限
- コスト制御: 1日2ドル、月30ドルのハードキャップ
- 監査ログと自動更新を有効化
- 攻撃面の最小化: ergoとnullclawの2サービスのみを実行し、Webコンテンツは直接配信しない
- 侵害が発生しても、被害範囲は1日2ドル上限のIRCボットに限定される
通信スタック構成
- すべての構成要素は小型・セルフホスト・交換可能な形
- Ergo: IRCサーバー、単一のGoバイナリ、2.7MB RAM
- gamja: Web IRCクライアント、152KBの静的ページ、Cloudflareの背後で提供
- nullclaw: AIエージェントランタイム、4MBのZigバイナリ、約1MBのメモリを使用
- システム全体は10MB未満のバイナリ、5MB未満のアイドル時メモリで動作
- 最安のVPSティアでも十分に運用可能
nully(公開エージェント)の実際の機能
- プログラミング言語の把握: 事前に読み込んだコンテキストとリポジトリ検証を通じて確認
- テスト構造の分析: リポジトリを複製した後、テストファイルを直接読み取って結果を報告
- プロジェクト説明: たとえば Fracture プロジェクトの詳細をコードベースで応答
- 連絡先案内: 正確な連絡先情報のみを提供し、虚偽情報は生成しない
- 予定予約リクエスト: Google A2Aプロトコルを通じてironclawに転送し、結果を構造化して返す
- 訪問者はバックエンド切り替えの過程を意識しない
A2A実装
- Google A2Aプロトコル(v0.3.0) をサポートし、JSON-RPCベースのジョブ状態管理を実行
a2a_call ツールはリモートエージェントにメッセージを送信し、**ジョブ状態(完了/失敗/進行中)**を解析
- HTTPSを強制しつつ、Tailscale内部ネットワークではデバッグのためにHTTPを許可
-
ironclaw側の構成
- nullclawインスタンスは独自のAPIキーを持たず、ironclawのLLMゲートウェイをプロキシとして使用
- 1つのAPIキーと支払い関係だけを維持
- ironclawがすべての推論リクエストを処理し、コストを負担
ハンドオフのセキュリティ
- A2Aエンドポイントにはプロンプトインジェクションのリスクがあるため、厳しい制限を適用
- ironclawに転送可能な要求は予定、連絡先、空き状況関連に限定
- 任意コマンドの転送は拒否
- ironclawのA2AエンドポイントはTailscale専用ファイアウォールで保護
- 両エージェントとも監視モードと制限付きコマンド許可リストで実行
- nullyが要求を昇格させるかどうかを判断し、無差別なコマンド実行を防ぐ
構築過程で得た教訓
- モデル選定はシステム設計の一部であり、コスト・遅延・体験に直接影響する
- エージェント自体よりも通信・セキュリティ・インフラ構成に多くの時間を要した
- IRCのシンプルさと開放性はAIエージェントの転送レイヤーとして理想的
- nullclaw–ironclaw分離構造がセキュリティモデルの核心
- A2AプロトコルとIRCログチャンネルの併用により、構造化通信とリアルタイム可視性を確保
- 認証情報の重複防止: ironclawのゲートウェイをプロキシとして使い、単一APIキー・単一の支払い関係を維持
体験方法
- georgelarson.me/chat にアクセスするか、ホームページのターミナルで
irc と入力
- IRCクライアント使用時:
irc.georgelarson.me、ポート 6697(TLS)、チャンネル #lobby
- nully が待機しており、訪問者とリアルタイムで会話できる
1件のコメント
Hacker Newsのコメント
メールや個人データにアクセスできるOpenClawエージェントがもし侵害された場合、被害範囲は非常に大きくなり得る
単なるIRCボットのレベルではなく、攻撃者がパスワードをリセットしてAPI制限を解除したり、さらには違法コンテンツ共有ハブとして悪用したりする危険もある
なぜHaiku/Sonnetを選んだのか気になった。OpenRouterにはもっと安いモデルがたくさんある
例えばHaiku 4.5は入力100万トークンあたり$1、出力$5だが、MiniMax M2.7は入力$0.30、出力$1.20、Kimi K2.5は入力$0.45、出力$2.20程度だ
私の経験では、M2.7とK2.5もHaikuと同等かそれ以上の性能を見せる
私も最近エージェントを作りながらAnthropicモデルを使っている理由がまさにそれだ。Haikuはユーザーが変な要求を投げても制御がうまく、感情的な会話も安定して処理する
IRCは伝送層としては良いが、配信保証(delivery guarantee) がない。接続が切れると、その間のメッセージは失われる
リアルタイムチャットには問題ないが、実際の作業を処理するエージェントならat-least-once配信が必要だ
SSE(Server-Sent Events) は中間案として悪くない。持続接続が可能で、再送ロジックを追加できる
東京から大阪へ向かう電車の中で、似たアイデアのボットを作ったことがある
web-support-claw.oncanine.run — GitHubリポジトリを読んでWebサイト向けのインターコムボットを作るプロジェクトだった
訪問者の質問に答えてくれるので、別途ナレッジベースを作る必要がない
今後はHaikuインスタンスを1つ監視用に置くことを勧める。ntfyで通知を受け取ることもできる
今のチャットルームは完全に制御不能な状態だ
「インタラクティブ履歴書」が目的なら、不特定多数との相互作用は不要だ
私たちのチームも似た構成を使っている。FastAPI + SQLiteベースのメッセージボードで4つのエージェント(営業、ソーシャル、財務、戦略)が通信している
1日の予算制限の代わりに、ガバナンス層でコスト上限を管理している
IRCのpub/sub構造はマルチエージェント通信に向いているが、私たちはHTTPポーリング + 重複排除方式を使っている。優雅さには欠けるが、エージェントが頻繁にクラッシュしても復旧しやすい
私もコーディングエージェントでIRCをインターフェースとして使っている
部屋を切り替えながらプロンプトを切り替え、リモートでプロジェクトを制御する
「公開ボックスは個人データにアクセスしない」と言っていたが、それをCTFチャレンジにしてみると面白そうだ
非公開ボックスにフラグを隠しておいて、誰かがアクセスして取れたら50ドル払う、という形で
nullyの態度は少し荒っぽいが、全体的なシステム構成は気に入っている
私も階層構造を使っていて、最下層はQwenローカルボットだ
HaikuからOpusへのエスカレーションロジックが気になる
このアイデアは本当に興味深い。採用プロセスを自動化するボットを作りたくなる
候補者の志向をインタビューで把握し、それに合った求人を探して応募まで自動で処理する
企業側のボットも同じ方式で候補者を評価すれば、お互いの好みに合わせてマッチングできる
完全なオープンソースのセルフホスティングで実装でき、履歴書よりはるかに良いシグナルを与えられる