OpenDots は、CopilotKit が 2026-09-29 に公開した「常駐型AIエージェントのワークスペース」を自前で建てるためのテンプレートだ。MIT、⭐858(2026-10-02時点)、バージョンは 0.1.0 で alpha バッジ付き。売りはDotごとに専用の computer を持たせられることと、チャット・音声通話・Slackをまたいで同じ会話が続くこと。製品ではなく雛形なので、鍵を1本も入れない状態でどこまで動くかを確かめた。
- ・CopilotKit が公開した**常駐エージェントのテンプレート**。MIT・⭐858・公開から4日
- ・**鍵なしで起動する**。`/api/state` が `configured: false` を返し、未設定であることをAPIが自己申告
- ・未設定のあいだ Spaces・Dots・computer のルートは**そもそも登録されない**(`if (platform)` で分岐)
- ・**APIの門番9点を陰陽対照つきで実測**(403×3・415・413・401×2・200×2)
- ・テストは **34ファイル156本が10.00秒で通過**。通信も鍵も不要
- ・`engines` は **Node 24以上**。`npm ci` 後の `node_modules` は **980MB**
エージェント基盤の全体像や他フレームワークとの比較はAIエージェントフレームワーク比較2026|LangGraph・CrewAI・Dify等9種をStar数・実コードで検証にまとめてある。本記事はその枝として、「雛形を1つ落としてきて起動するまで」に何が起きるかを見る。
OpenDotsとは:製品ではなくテンプレート
READMEの1行目に「A template, not a hosted product.」と書いてある。clone して自分の Dot を定義し、サービスを繋ぎ、UIとツールを自分の用途に合わせて作り替える——その出発点として配られている。中心にある概念は3つだ。
・Space:作業中のドキュメントの置き場。検索できるライブラリ、スラッシュコマンド付きのエディタ、自動保存とリビジョン検査を持つ
・Specialist Dot:名前・役割・指示・許可ツールを与えたエージェント。調査担当と執筆担当を分ける、といった使い方を想定している
・Dot computer:Dotごとの隔離されたブラウザとワークスペース。停止と再開をまたいでブラウザプロファイルとファイルが残る
3つ目が、このテンプレートの一番わかりやすい差別化だ。Dot に computer を与える部分は OpenBot のコンテナ監督と computer サービスを使っていて、当サイトではCopilotKit OpenBotとは|AIエージェントに1台ずつPCを与えるAG-UI基盤の使い方と起動条件で別途扱っている。同じ「エージェントにPCを渡す」という発想はCloudflare Computerとは:AIエージェントにDurable Object上の仮想FSと実行環境を与えるOSSにもあるが、あちらが実行基盤そのものなのに対し、OpenDots はその上に乗せる作業場のUIと会話の器を配っている。
READMEで好感が持てたのは、できていないことを先に書いている点だった。alpha バッジ、「単一オーナー向けの出発点」という断り、そして共同編集・招待・ファイル添付・対話的なページ埋め込みが同梱されていないという明記。後述するが、検証状況まで日付つきで分けて書いてある。
鍵なしで起動する:clone から npm run dev まで
READMEの手順どおりにやった。要求は Node 24 と npm。
git clone https://github.com/CopilotKit/OpenDots.git
cd OpenDots
npm ci
cp .env.example .env # 中身は空のまま(鍵を入れない)
npm run dev
手元の環境は Node v22.22.2 だったので npm ci は警告を出した。
npm warn EBADENGINE Unsupported engine {
npm warn EBADENGINE package: '[email protected]',
npm warn EBADENGINE required: { node: '>=24.0.0' },
npm warn EBADENGINE current: { node: 'v22.22.2', npm: '10.9.7' }
npm warn EBADENGINE }
added 1017 packages, and audited 1018 packages in 1m
found 0 vulnerabilities
警告は出たが、この先すべて動いた。インストールは1,017パッケージで約1分、node_modules は 980MB。脆弱性の報告は0件。npm run typecheck(tsc --noEmit)も無言で通過した。Node 24を要求しているのは、おそらく node:sqlite を使っているためで、実行時に ExperimentalWarning: SQLite is an experimental feature が繰り返し出る。
npm run dev を叩くと、concurrently がAPIサーバと Vite を同時に起こす。
[1] VITE v8.3.1 ready in 689 ms
[1] ➜ Local: http://127.0.0.1:5173/
[0] serveStatic: root path './dist/client' is not found, are you sure it's correct?
[0] OpenDots template listening on http://127.0.0.1:4310
鍵が1本も無くても起動する。5173 は200を返し、UIが開く。ではAPIは何と言うのか。
curl -s http://127.0.0.1:4310/api/state
# {"settings":{"name":"Dot","paused":false,"researchAllowed":true,"memoryAllowed":true},
# "tasks":[],"memories":[],"mode":"live","configured":false}
configured: false。未設定であることをAPI自身が申告する。ここが気に入った点で、「繋いでみて初めてエラーで気づく」のではなく、状態として最初から取れる。
一方で /api/spaces や /api/dots は {"error":"Not found."} を返す。落ちているのではない。src/server/app.ts を読むと理由が分かる。
if (platform) app.route('/api', computerRoutes(platform.computers));
const voice = platform ? new VoiceService(platform) : undefined;
if (platform && voice) app.route('/api', workspaceRoutes(platform, voice));
プラットフォーム(Intelligence)が未設定なら、ルート自体を登録しない。半端に生きているエンドポイントが残らないので、「設定したつもりで動いていた」という事故が起きにくい。
テストも通した。npm test(vitest)は 34ファイル・156テストが10.00秒で全通過。通信もAPIキーも不要で、サービス側はフィクスチャに差し替えられている。
コード量は src 配下のTypeScriptが 10,259行、うちサーバ側が3,903行。公開4日目の雛形としては、薄すぎず厚すぎない規模だ。
APIの門番を9通り叩く
app.ts のミドルウェアを読んでいて、ローカル専用アプリとしては珍しく門番が多いことに気づいた。書いてあるだけなのか実際に効くのか、全部叩いて確かめた。
実行したのはこれだけだ。
B=http://127.0.0.1:4310/api/state
curl -s -o /dev/null -w '%{http_code}\n' $B # 200(陽性対照)
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: evil.example' $B # 403
curl -s -o /dev/null -w '%{http_code}\n' -H 'Origin: https://evil.example' $B # 403
curl -s -o /dev/null -w '%{http_code}\n' -H 'Sec-Fetch-Site: cross-site' $B # 403
curl -s -o /dev/null -w '%{http_code}\n' -X POST $B # 415
head -c 1200000 /dev/zero | tr '\0' 'a' | \
curl -s -o /dev/null -w '%{http_code}\n' -X POST \
-H 'Content-Type: application/json' --data-binary @- $B # 413
6通りとも、コードに書いてあるとおりのコードが返った。許可ホストは localhost / 127.0.0.1 / [::1] と APP_ORIGIN だけで、それ以外のHostヘッダは Unrecognized host. で弾かれる。レスポンスヘッダにも cache-control: no-store と x-content-type-options: nosniff が毎回付いていた。
次に OWNER_TOKEN を設定して再起動し、3回叩いた。
echo 'OWNER_TOKEN=opendots-owner-token-123456789' >> .env && npm run dev
curl -s -o /dev/null -w '%{http_code}\n' $B # 401
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $TOK" $B # 200(陽性対照)
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer ${TOK}X" $B # 401
# {"error":"Enter your owner access token to unlock OpenDots."}
正しいトークンだけが200、1文字多いだけで401。コードは長さを先に比べてから timingSafeEqual を使っており、タイミング攻撃への配慮もある。ローカルの雛形でここまでやっているものは多くない。外部ホストにバインドする場合は24文字以上の OWNER_TOKEN が必須、という設計も .env.example に明記されていた。
ついでに言うと、本文サイズの上限が1MBなのはファイル添付が同梱されていないことと整合している。雛形として配る範囲を小さく切り、その範囲に合わせて上限を引いてある。
何が繋がっていて、何がまだ繋がっていないか
アーキテクチャは「自作部分より繋ぎ先が多い」構成になっている。
AG-UI がバックエンドと CopilotKit のReactコンポーネントのあいだで、ストリームされるメッセージ・ツール呼び出し・エージェントの状態を運ぶ。computer の作業内容がチャット内にインラインで出るのも、承認を待つ human-in-the-loop のカードでツール呼び出しが一時停止するのも、この層の仕事だ。会話の永続化は CopilotKit Intelligence の Threads が持ち、ページごと・スペシャリストごとに別の会話になる。モデル配信は TanStack AI、Slackは Channels SDK。
ページ・Space・Dot・チャット"] -->|"AG-UI"| RT["CopilotKit ランタイム"] Slack["Slack"] <--> CH["Channels SDK"] CH --> AG["スペシャリストのcompute agent"] RT --> AG AG --> TA["TanStack AI"] TA --> P["OpenAI互換プロバイダ"] RT <--> INT["Intelligence / Threads"] CH <--> INT Web <--> SP["リアルタイム音声"] SP --> AG AG --> CTL["ツール権限"] CTL --> COMP["隔離ブラウザ / ワークスペース"] RT --> META[("ページ・Space・Dot・作業メタデータ")]
そして、ここが当サイトとして一番評価したい点だ。READMEが検証済みと未検証を日付つきで分けて書いている。
「Live Intelligence, model responses, and page-context chat were verified on September 29, 2026.」「Slack and spoken compute delegation still need connected-service verification.」——何をいつ確かめ、何がまだかを自分で書くREADME は少ない。当記事も同じ流儀で、確かめた範囲を最後に表で出す。
同じ CopilotKit 系ではCopilotKitとは|ReactアプリにAIコパイロットを埋め込むOSSの使い方と実装パターンでフロント側のSDKを扱っている。OpenDots はその上に「常駐する同僚」という体裁と、computer・通話・Slackの配線を足したもの、と位置づけると分かりやすい。
最後に、当記事で確かめた範囲を整理しておく。
| 項目 | 確認方法 | 状態 |
|---|---|---|
npm ci と依存規模(1,017・980MB) |
実行 | 実測 |
npm run typecheck |
実行(無言で通過) | 実測 |
| テスト156本・10.00秒 | npm test を実行 |
実測 |
鍵なしでの起動と configured: false |
npm run dev + /api/state |
実測 |
| 未設定時にルートが登録されないこと | 404を確認し app.ts の分岐で裏取り |
実測 |
| APIの門番9点 | curl 9本(陽性対照つき) | 実測 |
| Node 24要求と22での動作 | EBADENGINE警告つきで全工程通過 | 実測 |
| Dot computer の実動作 | Intelligence と OpenBot 未設定のため未実行 | 未検証 |
| 音声通話・Slack連携 | プロバイダ未設定のため未実行 | 未検証 |
| Automatic Learning | 同上 | 未検証 |
| 複数人での運用 | 同梱されていない(READMEに明記) | 対象外 |
公開4日目のテンプレートとしては、配る範囲を小さく切って、その範囲の中は丁寧に作ってあるという印象だった。繋がないと評価できない部分は多いが、繋ぐ前に分かることがここまで分かる雛形は扱いやすい。
参照ソース
・CopilotKit/OpenDots — GitHubリポジトリ(main・最終コミット b01ac1f・2026-10-02 を clone して実行): https://github.com/CopilotKit/OpenDots
・OpenDots docs/SETUP.md — 設定・Slack・通話・ブラウザサービスの手順: https://github.com/CopilotKit/OpenDots/blob/main/docs/SETUP.md
・AG-UI ドキュメント — UIとエージェントのあいだを運ぶ層: https://docs.ag-ui.com/introduction
・CopilotKit/OpenBot — Dot の computer を支えるコンテナ監督: https://github.com/CopilotKit/OpenBot