OpenDots は、CopilotKit が 2026-09-29 に公開した「常駐型AIエージェントのワークスペース」を自前で建てるためのテンプレートだ。MIT、⭐858(2026-10-02時点)、バージョンは 0.1.0 で alpha バッジ付き。売りはDotごとに専用の computer を持たせられることと、チャット・音声通話・Slackをまたいで同じ会話が続くこと。製品ではなく雛形なので、鍵を1本も入れない状態でどこまで動くかを確かめた。

OpenDotsはcloneしてnpm ciすると1017パッケージで約1分、node_modulesは980MB。npm run devでVite 5173とAPI 4310が鍵なしで立ち上がり、/api/stateがconfigured falseを返して未設定であることを自己申告する。未設定のあいだSpacesとDotsとcomputerのルートは落ちるのではなくそもそも登録されない。鍵なしでもUIは起動しSpace作成とページ編集は可能でテスト156本すべて通過するが、鍵を入れるとSpacesとPagesとDotsのルート一式、Dotごとのcomputer、通話とSlackが現れる
main(最終コミット b01ac1f・2026-10-02)を clone して実行。数値はすべて当記事での実測
30秒でわかるOpenDots(2026-10-02時点)
  • ・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ごとの隔離されたブラウザとワークスペース。停止と再開をまたいでブラウザプロファイルとファイルが残る

OpenDotsのチャット画面。左にSPACESとCONVERSATIONS、中央にDotとの会話、通話終了のレシートや参照元リンクがタイムラインに並ぶ。右上にSELF-HOSTEDのバッジとPause、下部にScheduled and activityとMemoriesとSettings and setup
リポジトリ同梱のスクリーンショット(docs/images/chat-layout.png・MIT)。右上の SELF-HOSTED バッジと、タイムラインに残る通話レシートが特徴

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は10259行でserverが3903行、通過したテストは156本で34ファイル10.00秒、npm ci後のnode_modulesは980MB、enginesの要求はNode 24で手元は22で警告つき起動
いずれも当記事の実行結果。行数は src 配下の .ts と .tsx の合計

コード量は src 配下のTypeScriptが 10,259行、うちサーバ側が3,903行。公開4日目の雛形としては、薄すぎず厚すぎない規模だ。

APIの門番を9通り叩く

app.ts のミドルウェアを読んでいて、ローカル専用アプリとしては珍しく門番が多いことに気づいた。書いてあるだけなのか実際に効くのか、全部叩いて確かめた。

OpenDotsのAPIの門番。Host詐称と別Originとcross-siteは403で許可ホストはlocalhostと127.0.0.1と[::1]とAPP_ORIGINだけ、Content-TypeなしのPOSTは415でGETとHEAD以外はapplication/jsonを要求、1MBを超える本文は413でbodyLimitは1000000バイト、OWNER_TOKEN不一致は401で長さ比較とtimingSafeEqualを使い正しいトークンでは200
素のGETが200を返すことを陽性対照に、9リクエストを実行して全件コードを確認した

実行したのはこれだけだ。

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なのはファイル添付が同梱されていないことと整合している。雛形として配る範囲を小さく切り、その範囲に合わせて上限を引いてある。

何が繋がっていて、何がまだ繋がっていないか

アーキテクチャは「自作部分より繋ぎ先が多い」構成になっている。

OpenDotsの構成。UIとエージェントの橋はAG-UIがメッセージとツール呼び出しと状態を運び、会話の永続化はCopilotKit IntelligenceのThreadsでページごとに別会話、Dotの手足はOpenBotのコンテナ管理とcomputerサービス。ほかにTanStack AIとChannels SDKとOpenAI互換プロバイダを使い鍵はすべてサーバ側に置く
READMEのアーキテクチャ節と、src/server のルート定義を突き合わせて整理

AG-UI がバックエンドと CopilotKit のReactコンポーネントのあいだで、ストリームされるメッセージ・ツール呼び出し・エージェントの状態を運ぶ。computer の作業内容がチャット内にインラインで出るのも、承認を待つ human-in-the-loop のカードでツール呼び出しが一時停止するのも、この層の仕事だ。会話の永続化は CopilotKit Intelligence の Threads が持ち、ページごと・スペシャリストごとに別の会話になる。モデル配信は TanStack AI、Slackは Channels SDK。

flowchart TB Web["Webアプリ
ページ・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が検証済みと未検証を日付つきで分けて書いている。

ローカルで検証済みと書かれているのはIntelligenceとモデル応答とページ文脈チャットが2026-09-29、OpenBotでのブラウズとファイル作成とシェル確認、停止と再開をまたぐファイル永続、Realtime音声と通話操作とレシート保存が2026-09-30。接続先での検証が要ると書かれているのはSlack連携と音声からのcompute委譲とAutomatic Learningのクラウド実行と配信で、複数人運用と共同編集とファイル添付は未同梱
README の Features 節の記述を整理。日付と検証範囲が本文に明記されている

「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 は少ない。当記事も同じ流儀で、確かめた範囲を最後に表で出す。

OpenDotsのSpaceワークスペース画面。左サイドバーにSpacesとページのツリー、中央にページ本文のエディタ、入れ子のサブページとして文書を整理できる
Space のワークスペース(docs/images/spaces-workspace.png・MIT)。ページは入れ子のサブページとして整理でき、鍵なしでも手で書ける

同じ 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