AIエージェントを1体動かす話と、20体を同時に動かして破産しない話は、まったく別の問題だ。前者はプロンプトとツール定義の話に収束するが、後者は「誰がどのタスクを持っているか」「いくら使ったか」「勝手に進めていい範囲はどこまでか」という、要するに組織運営の話になる。2026年3月に公開されたpaperclipai/paperclip(以下Paperclip)は、この後者を正面から扱うMITライセンスのTypeScript製OSSで、公開から約5か月でGitHubスター7.6万を集めている。READMEの言い方を借りれば「OpenClawが従業員なら、Paperclipは会社」だ。
エージェント基盤全体の見取り図はAIエージェントフレームワーク比較2026|LangGraph・CrewAI・Dify等9種をStar数・実コードで検証で整理している。本記事はそこから外れた位置にある「エージェントを作らず、走らせて管理する側」を扱う。しかも紹介に留めず、Paperclipの売り文句のうち実務で本当に効く部分——予算・排他ロック・承認ゲート——が、どの順序で効き、どこで効かないのかをソースコードと実測から確定させる。
・何ができるか:Claude Code・Codex・Cursor・OpenClawなど手持ちのエージェントに役職と上司を与え、タスク・予算・承認つきで24時間走らせる
・何を解決するか:ターミナルを20枚開いて誰が何をしているか分からなくなる問題と、暴走ループで請求が跳ねる問題
・何を代替できるか:エージェント用に自前で作りかけたチケット管理・コスト集計・承認フロー。エージェント本体は代替しない
・効き方の実際:予算のハードストップは「ランが1本終わった後」に効く。走行中を切る仕組みではない
・日本での落とし穴:月次・日次の予算ウィンドウはUTC基準。JSTでは毎日・毎月09:00がリセット時刻になる
・READMEが並べる機能の中で、実装を読むと挙動が想像とずれるのは「予算がいつ効くか」と「排他ロックがどこまで効くか」の2点
・同梱アダプタはREADMEのロゴ列(6つ)より広く、型定義には13種が並ぶ。しかも型は文字列で拡張できる
・「会社」の初期値は控えめで、同梱テンプレは4チーム・エージェント定義8本
Paperclipとは——タスク管理ツールの見た目をした組織レイヤー
Paperclipは、Node.jsサーバー(API)とReact製UIからなる自ホスト型のエージェント運用基盤だ。エージェントそのものは同梱しない。既にあるコーディングエージェントやチャットボットを「アダプタ」経由で呼び出し、それらに役職・レポートライン・予算・承認フローを与える。
画面はタスク管理ツールにしか見えない。だが1件のタスクを開くと、担当者の欄に人間ではなくCEOという役職のエージェントが入っており、レビュアー・承認者・ブロッカー・サブタスクが人間向けのそれと同じ形で並ぶ。
リポジトリの実測値
2026年8月9日(UTC)時点でGitHub APIとnpmレジストリから取得した実測値は次のとおり。
| 項目 | 実測値 |
|---|---|
| リポジトリ | paperclipai/paperclip |
| ライセンス | MIT |
| スター / フォーク | 76,086 / 14,163 |
| オープンIssue | 5,059件 |
| コントリビューター | 184人(匿名含む) |
| コミット数 | 3,515 |
| 主言語 | TypeScript(41,336,792バイト) |
| リポジトリ作成日 | 2026-03-02(org作成は2026-02-27) |
| 最新リリース | v2026.722.0(2026-07-22) |
| npm公開バージョン数 | 1,031 |
| npm週間ダウンロード | 30,199(2026-08-02〜08-08) |
| 動作要件 | Node.js 20以上 / pnpm 9.15以上 |
フォーク14,163はスター数に対して比率が高い。テンプレート的に自分の会社を立てて使う性質のリポジトリであることを反映していると読める。オープンIssueが5,059件ある点は、公開5か月・コミット3,515という速度と合わせて見るべきで、成熟した製品というより高速に動いている最中のプロジェクトだ。
「4本柱」という自己説明
READMEはPaperclipの守備範囲を4つの柱として説明している。日々使うタスク管理、管理者向けの組織図、育成側のスキル・評価、そしてIT側のランタイムとガバナンスだ。
この4本柱のうち、導入検討で最初に確かめるべきは4本目のガバナンス側だ。エージェントを24時間走らせる構成では、機能の多さより「止まるべきときに止まるか」が先に効いてくる。以下、その実装を順に読む。
Paperclipのインストールと初回起動——実測した手順と既定値
配布経路は3つある。公式インストーラ、npmパッケージ、リポジトリのクローンだ。ここでは実際に走らせて確認できた範囲を書く。
公式インストーラとチェックサム
READMEが案内する手順は、スクリプト本体とSHA-256のチェックサムを別々に落として照合してから実行する形になっている。実際に照合すると通る。
# インストーラとチェックサムを取得して照合する
curl -fsSLO https://paperclip.ing/install.sh
curl -fsSLO https://paperclip.ing/install.sh.sha256
shasum -a 256 -c install.sh.sha256
# => install.sh: OK
# 中身を確認してから実行する(367行のシェルスクリプト)
less install.sh
bash install.sh
ここで注意したいのは、READMEが自分でこの検証の限界を書いている点だ。チェックサムはスクリプトと同じオリジンから配信されるため、転送や公開の事故は検出できるが、配信元そのものが差し替えられた場合の防御にはならない。独立した検証が要るならリリースタグやコミットに固定したGitHub上のコピーを使え、とREADME自身が述べている。導入手順を書く側としては、この但し書きを省略しないほうが誠実だろう。
npmから直接動かす
インストーラを介さず、CLIだけを試すこともできる。実際に固定バージョンで実行した結果は次のとおり。
# バージョン確認(公開レジストリを明示するとプライベートレジストリ環境でも通る)
npx --registry https://registry.npmjs.org [email protected] --version
# => 2026.722.0
# 初回セットアップウィザード(既定はループバック信頼モード)
npx --registry https://registry.npmjs.org paperclipai onboard --yes
# LANやTailscale経由で触るなら明示的にプリセットを指定する
npx --registry https://registry.npmjs.org paperclipai onboard --yes --bind lan
CLIは単なる起動用ラッパーではない。--help を叩くと company / issue / agent / goal / budget / approval / org / cost / workspace など30を超えるコマンド群が並び、UIでできる操作の多くがコマンドラインからも触れるようになっている。
既定値で押さえておくべき3点
初回起動の既定値には、後の挙動を左右するものが混ざっている。ソースで確認できた範囲では次の3つだ。
・接続範囲:--bind を省略したクイックスタートは loopback プリセットで、deploymentMode は local_trusted になる。lan / tailnet を選ぶと authenticated へ切り替わる
・ハートビート:エージェントを定期的に起こす仕組みは既定で無効(enabled の既定値が false)。有効化して初めて自走が始まる
・日次上限:1日あたりの実行回数上限(maxDailyRuns)とコスト上限(maxDailyCostCents)はどちらも既定 null、つまり未設定。明示的に入れるまで日次の歯止めは無い
3つ目は特に重要だ。前掲のダッシュボードでも、Month Spend の下に「Unlimited budget」と表示されている。予算は自分で入れるまで効かない。
Unlimited budget、Pending Approvals の下に Awaiting board review と出る(出典: paperclipai/paperclip 同梱スクリーンショット)予算のハードストップはいつ効くのか——停止の順序をソースで追う
READMEは「タスクのチェックアウトと予算の強制はアトミックなので、二重作業も暴走支出も起きない」と書いている。この一文が実務でどう効くかは、コストがいつ記録されるかで決まる。順に追う。
コストイベントは「ラン1本ごと」に1件
予算判定の入口は evaluateCostEvent で、コストイベントが1件書かれるたびに走る。ではそのコストイベントはどこで書かれるか。server/src/services/costs.ts の createEvent が唯一の挿入経路で、これを呼ぶのは server/src/services/heartbeat.ts の updateRuntimeState だ。そして updateRuntimeState の呼び出しは、アダプタ実行が終わってランが確定した後(if (finalizedRun) の中)に置かれている。
つまりトークン使用量とコストは、1回のランが終わってから、その総量として1件書かれる。ラン中に逐次書かれるわけではない。したがって予算の評価も、ランが1本終わるまで走らない。
上限に到達したとき何が起きるか
evaluateCostEvent の中身は素直だ。対象ポリシーごとに窓内の実績を集計し、observedAmount >= policy.amount かつハードストップが有効なら、未解決のソフトインシデントを解決し、ハードインシデントを起票し、pauseAndCancelScopeForBudget でスコープを一時停止したうえでキュー済みの作業を取り消す。さらにハードの場合は budget_override_required という種別の承認をpending状態で自動生成する。人間が判断するまで再開しない設計だ。
そして次回以降のアダプタ呼び出しは、呼び出し前に getInvocationBlock で弾かれる。
server/src/services/budgets.ts / heartbeat.ts を読んで作図)読者が受け取るべき結論
この構造から言えることは3つある。
・1本目のランは超過してから止まる。上限を1ドルに設定していても、1回のランが5ドル使えば、そのランは完走し、記録され、その後に停止がかかる。想定される最大の1ラン分は常に超過しうる
・逆に言えば、暴走が「継続」することは防げる。ループが100本走るような事故は、2本目以降がブロックされて止まる。README言うところの「runaway loops」対策としては機能する
・上限は1ラン分のマージンを見て設定する。日次コスト上限(maxDailyCostCents)を併用すると、月次より短い周期で歯止めがかかる。ただしこちらも既定は未設定なので、自分で入れる必要がある
# 会社全体の予算状況を確認する
paperclipai budget overview --company-id <COMPANY_ID>
# 予算ポリシーを作成・更新する(JSONペイロードで渡す)
paperclipai budget policy:upsert --company-id <COMPANY_ID> \
--payload-json '{"scopeType":"agent","scopeId":"<AGENT_ID>","amount":5000,"warnPercent":80,"hardStopEnabled":true}'
# ハードストップで起票された承認を確認する
paperclipai approval --help
amount の単位はセントだ。既定のメトリクスは billed_cents で、warnPercent の割合を超えた時点で警告インシデントが立ち、100%到達でハードストップが走る。
止まったあと、誰が再開させるのか
エージェントの予算管理で厄介なのは、止めることより「止まったままにしておくこと」のほうだ。上限に達したエージェントが翌朝には勝手に動き出していた、という事故を防ぐ必要がある。
Paperclipはここを承認テーブルで処理する。ハードストップのインシデントが起票されるとき、同時に approvals テーブルへ budget_override_required 種別のレコードが pending 状態で挿入される。ペイロードには対象スコープ名・上限額・実測額・ウィンドウの開始と終了、そして対処方針を示す一文(予算を引き上げてスコープを再開するか、停止したままにするか)が入る。この承認が解決されるまで、当該スコープは一時停止のままだ。
インシデントを解決すると、紐づく承認も同時に approved もしくは rejected へ更新され、誰がいつ決めたかが記録される。一方、ソフトしきい値(warnPercent 到達)のほうは承認を生成せず、インシデントだけを立てる。そしてハードしきい値に到達した時点で、未解決のソフトインシデントは自動的に解決済みへ移される。警告と停止で扱いをはっきり分けている。
・ソフト(警告):インシデントのみ。承認は生成されない。ハード到達時に自動で解決済みになる
・ハード(停止):インシデント+承認を起票。スコープ一時停止とキュー取消を伴い、人間の決定まで再開しない
なお、インシデントはポリシー・ウィンドウ開始時刻・しきい値種別の組で重複が弾かれる。同じ月に同じエージェントが何度上限へ触れても、同種のインシデントが積み上がって通知が溢れることはない。
この非対称は、24時間走らせる構成では効いてくる。夜間に警告が出ただけなら朝まで走り続け、上限に達した場合だけ人間待ちで止まる、という挙動になる。逆に言えば、承認を裁く人がいない時間帯に上限へ達すると、その間の作業は完全に止まる。バッファをどこに置くかは運用側の設計判断になる。
「今月」と「今日」はUTC基準——JST運用では9時間ずれる
日本から運用する場合に最も踏みやすい落とし穴がここだ。
予算ウィンドウの解決は resolveWindow が担当し、lifetime 以外は currentUtcMonthWindow を返す。この関数は Date.UTC(year, month, 1, 0, 0, 0, 0) を月初として使う。つまり月次予算の境界はUTCの月初であり、日本時間では毎月1日の09:00がリセット時刻になる。
日次上限も同じ設計だ。ハートビートの日次キャップは currentUtcDayWindow を使い、Date.UTC(...getUTCDate(), 0,0,0,0) を1日の起点にする。日本時間では毎日09:00が境界だ。
budgets.ts / heartbeat.ts / constants.ts を読んで作図)回避策があるかというと、設定では無い。BUDGET_WINDOW_KINDS の定義は calendar_month_utc と lifetime の2値のみで、ローカルタイムゾーンの月を選ぶ選択肢はそもそも用意されていない。スコープ別の既定値は次のとおりだ。
| スコープ | 既定ウィンドウ | 実際の境界(JST) |
|---|---|---|
| 会社(company) | calendar_month_utc |
毎月1日 09:00 |
| エージェント(agent) | calendar_month_utc |
毎月1日 09:00 |
| プロジェクト(project) | lifetime |
境界なし(累計) |
| ハートビート日次キャップ | UTC暦日 | 毎日 09:00 |
プロジェクトだけ既定が lifetime、つまり累計になっている点も押さえておきたい。プロジェクト予算は「今月いくら」ではなく「このプロジェクトに合計いくらまで」という意味になる。月次のつもりで設定すると、翌月に戻らないまま止まったように見える。
運用上は、月次レポートを日本時間の月初に締めている組織ほどズレが効いてくる。8月1日の朝8時に見た「今月の使用額」には7月31日の日本時間夕方以降の消費が含まれていない、といった食い違いが起きる。ダッシュボードの数字と経理側の月次を突き合わせるときは、この9時間を意識しておく必要がある。
排他ロックは2種類ある——DBのCAS更新とプロセス内Map
「二重作業が起きない」という主張も、実装を見ると2つの別々の機構に分かれている。保証の強さが違うので、分けて理解しておきたい。
タスクの実行ロック:PostgreSQL上の条件付きUPDATE
Issueテーブルには execution_run_id / execution_agent_name_key / execution_locked_at という列がある。ランがクレームされた時点で、この列を条件付きUPDATEで書きに行く。条件は「そのIssueであること」「同じ会社であること」「現在の担当エージェントであること」、そして決定的なのが execution_run_id IS NULL または自分自身のID という条項だ。
これは典型的なコンペア・アンド・スワップで、DB側が直列化してくれる。複数のプロセスやリクエストが同時に同じIssueを取りに来ても、勝つのは1つだけになる。加えて、孤立したロックを掃除する定期処理(stale lockのsweep、orphanのcleanup)がテスト付きで用意されている。ここはREADMEの主張どおりだと言ってよい。
なお、ロックを打つタイミングはキュー投入時ではなく「実際に走り始めたとき」に寄せられている。ソースのコメントにも「lazy locking」と明記されており、キューに積んだだけのランがIssueを占有しないようになっている。
エージェント起動の直列化:モジュール内のMap
もう一方は毛色が違う。server/src/services/agent-start-lock.ts は、モジュールスコープの Map にエージェントIDごとの進行中Promiseを持ち、次の起動をその完了まで待たせる仕組みだ。
問題は待ち方にある。定数 AGENT_START_LOCK_STALE_MS は30秒で、経過するとロックはstale扱いになる。このときコードは処理を止めず、警告ログを出してそのまま起動を続行する。タイムアウト側も同様に警告を出して先へ進む。
AGENT_START_LOCK_STALE_MS = 30_000
→ 30秒経過: logger.warn("agent start lock stale; continuing queued-run start")
→ タイムアウト: logger.warn("agent start lock timed out; continuing queued-run start")
つまりこれは正しさを守るロックというより、通常時に起動が重ならないようにするための直列化だ。しかもプロセス内の変数なので、サーバーを複数プロセス・複数インスタンスで動かした場合には互いを認識しない。
2つを並べると、こう整理できる。
| 機構 | 実体 | 複数プロセスで有効か | 期限切れの挙動 |
|---|---|---|---|
| Issueの実行ロック | Postgresの条件付きUPDATE | 有効(DBが直列化) | sweep処理で解放 |
| エージェント起動ロック | プロセス内の Map |
無効(プロセスごとに独立) | 30秒で警告のうえ続行 |
シングルプロセスの自ホスト運用(想定される大多数の使い方)ではどちらも問題にならない。ただしスケールアウトを検討する段階では、後者が前提にしていない領域だと理解しておく必要がある。
Paperclipのアダプタとチームテンプレート——「会社」の初期値
ここまでが止める側の話だ。動かす側の初期値も見ておく。
アダプタ型は13種、しかも文字列で拡張できる
READMEのロゴ列にはOpenClaw・Claude Code・Codex・Cursor・Bash・HTTPの6つが並ぶ。だが型定義 AGENT_ADAPTER_TYPES(packages/shared/src/constants.ts)には13の識別子が入っている。数え方の違いを明示しておくと、これは「型定義に列挙された識別子の数」であり、うち process と http は特定製品ではなく汎用のトランスポート、cursor と cursor_cloud、hermes_local と hermes_gateway はそれぞれ同じ製品の2経路だ。
packages/adapters/ 配下には対応する実装パッケージが置かれている(出典: paperclipai/paperclip の packages/shared/src/constants.ts を読んで作図)型の定義は (typeof AGENT_ADAPTER_TYPES)[number] | (string & {}) という形になっていて、列挙外の任意の文字列も受け付ける。プラグイン機構から独自アダプタを足せるということで、README の「ハートビートを受け取れるなら雇える」という言い回しは、型レベルでも裏づけがある。
なお、Hermesについては当サイトでもHermes Agent 使い方|Telegram・Discord・Slack対応、LLM300+種切替で本体を扱っている。OpenClaw側はOpenClaw完全ガイド2026|GitHub35万★AIアシスタントOSSのインストールから運用までにまとめてあり、どちらもPaperclipから見れば「雇われる側」に当たる。
役職は12種、同梱チームは4件
エージェントに与えられる役職(AGENT_ROLES)はCEO・CTO・CMO・CFO・security・engineer・designer・pm・qa・devops・researcher・generalの12種だ。役職はUI上のラベルであると同時に、テンプレートやガバナンス設定の単位になる。
一方、すぐ使えるチームテンプレートは控えめだ。packages/teams-catalog に入っているのは4チームで、内訳は次のとおり。
| チーム | 区分 | 同梱エージェント定義 |
|---|---|---|
| Core Exec Team | bundled | CEO / CTO / QA |
| Product Engineering | bundled | CTO / QA / Senior Coder |
| Product Design | bundled | UX Designer |
| Content Machine | optional | Content Lead |
合計8本のエージェント定義(AGENTS.md)と、それぞれのプロジェクト定義・定期タスク定義が付く。READMEの「CEO、CTO、エンジニア、デザイナー、マーケター——どのボットでも、どのプロバイダでも」という表現から想像するほど、既製の組織が丸ごと入っているわけではない。実際には自分で役職とプロンプトを組み立てる作業が要る。同梱スキルも5本(paperclip、paperclip-board、paperclip-converting-plans-to-tasks、paperclip-create-agent、para-memory-files)で、土台に近い。
1タスクが実行されるまでの全体像
ここまでの機構をまとめると、1件のタスクがアダプタ呼び出しに至るまでに通るゲートは次のようになる。
既定は false"} B -->|"無効"| Z["自走しない"] B -->|"有効"| C["ウェイクアップキューに積む"] C --> D{"日次キャップ
maxDailyRuns / maxDailyCostCents"} D -->|"到達"| Y["キュー済みランを cancelled に"] D -->|"未設定または範囲内"| E{"getInvocationBlock
会社・エージェントの一時停止判定"} E -->|"ブロック"| Y E -->|"通過"| F["Issue の実行ロックを条件付きUPDATE
execution_run_id が NULL のときだけ勝つ"] F --> G["アダプタ呼び出し
Claude Code / Codex / OpenClaw ほか"] G --> H["ラン確定 finalizedRun"] H --> I["コストイベントを1件記録 createEvent"] I --> J{"実績が上限に到達したか"} J -->|"未到達"| K["次のタスクへ"] J -->|"到達"| L["スコープを一時停止+キューを取消
承認 budget_override_required を自動起票"]
止める側のゲートが3段(日次キャップ・スコープの一時停止判定・実行ロック)あり、そのすべてがアダプタ呼び出しの前に置かれている。一方で予算の実績評価だけが呼び出しの後にある。この非対称が、前述した「1本目は超過してから止まる」の正体だ。
類似ツールとの比較——何を代替し、何を代替しないか
マルチエージェントのオーケストレーションと言っても、その語が指す層は一つではない。エージェント同士の会話を設計する層、実行環境を用意する層、そして誰がどの仕事を持ちいくら使ったかを管理する層は別物だ。Paperclipは3番目に立つ。隣接するカテゴリと並べると立ち位置が分かりやすい。
| 観点 | Paperclip | 単体エージェント(Claude Code等) | エージェントフレームワーク(LangGraph等) | 汎用タスク管理+ボット |
|---|---|---|---|---|
| 主な役割 | 複数エージェントの運用・統制 | 実作業の遂行 | エージェントの実装 | 人間のタスク管理 |
| エージェントを作るか | 作らない(外部を呼ぶ) | 自身がエージェント | 作るためのSDK | 作らない |
| 役職・レポートライン | 12役職+組織図を持つ | 無し | 実装次第 | 人間向けのみ |
| コスト集計と上限 | 会社/エージェント/プロジェクト単位で保持 | ツール個別 | 実装次第 | 無し |
| 承認ゲート | 標準機能(承認まで再開しない) | 個別の許可プロンプト | 実装次第 | 人間の運用ルール |
| タスクの排他制御 | DBの条件付きUPDATE | 無し | 実装次第 | 人間の合意 |
| 導入コスト | サーバー運用が必要 | 低い | 開発工数が必要 | 低い |
READMEの「Paperclipではないもの」リストは、この表とおおむね一致する。チャットボットではない、エージェントフレームワークではない、ワークフロービルダーではない、プロンプト管理ツールではない、単体エージェント向けではない、コードレビューツールではない——と自ら線を引いている。
現実的な判断基準は、README自身が書いている一文が最も正確だ。エージェントが1体なら要らない、20体なら要る。より具体的には、次のいずれかに当てはまるなら検討する価値がある。
・同時並行のエージェントが常時5体を超え、どれが何を持っているか把握できなくなっている
・コストが「気づいたら」増えており、エージェント単位・プロジェクト単位の内訳が欲しい
・定期実行の作業がある(レポート生成、サポート一次対応など)が、手動で起動している
・成果物を人間が承認してから先へ進める運用を、口頭ルールではなく仕組みで担保したい
逆に、単発のコーディング作業をエージェントに任せているだけなら、サーバー1本とPostgreSQLを抱える見返りは小さい。既存のチケット管理を持ち込みたい場合も、現時点では対象外だ。READMEのFAQは、既存チケットシステムの持ち込み対応をロードマップ項目として挙げており、AsanaやTrelloを台帳のまま使う構成は将来の話になっている。
導入前に確認したい5点
最後に、実際に立てる前にソースから確認しておいた事項をまとめる。
・接続範囲を最初に決める。既定のクイックスタートは local_trusted(ループバック・認証前提なし)。外から触るなら --bind lan または --bind tailnet を明示し、authenticated モードで立てる
・予算は自分で入れるまで効かない。会社とエージェントの両方にポリシーを置き、hardStopEnabled を有効にする。warnPercent を80%程度にして予兆を拾う
・上限は1ラン分のマージンを見る。停止はコスト記録の後に効くので、想定される最大の1ラン分は超過しうる
・リセット時刻はJSTの09:00。月次も日次もUTC基準で、ローカル月を選ぶ設定は存在しない
・スケールアウトは慎重に。Issueの実行ロックはDBレベルで成立するが、エージェント起動の直列化はプロセス内のMapで、30秒で警告のうえ続行する
そのうえで、Paperclipを試す価値が最も高いのは「もう20枚のターミナルを閉じたい」と思っている状況だ。README風に言えば、エージェントを増やすほど必要になるのは賢いプロンプトではなく、誰が何をしていていくら使ったかを答えられる台帳のほうだ、ということになる。
参照ソース
・paperclipai/paperclip — GitHub公式リポジトリ(README、server/src/services/budgets.ts、server/src/services/heartbeat.ts、server/src/services/costs.ts、server/src/services/agent-start-lock.ts、packages/shared/src/constants.ts、packages/db/src/schema/issues.ts、packages/teams-catalog/、cli/src/config/server-bind.ts を参照)
・Paperclip 公式ドキュメント
・paperclipai — npm レジストリ(バージョン・公開日・ダウンロード数の実測)
・Paperclip 公式サイト(インストーラ install.sh および install.sh.sha256 の配信元)