AIエージェント

AI社員で会社を運営する仕組みを作った話

一人会社の運営そのものをリポジトリに載せて、AIエージェントに役割を割り当てました。作った仕組みと、実際に踏んだ失敗4つの記録です。

  • #AIエージェント
  • #Claude Code
  • #自動化
  • #一人会社
  • #Codex

どうも、アスラです。

前に「核は手放さない」という記事で、本職を軸にAIで事業を広げていく話を書きました。

今回はその続きというか、実際にやってみた話です。

会社の運営そのものを、ひとつのリポジトリに載せました。

社員はAIエージェントです。企画を分解する人、記事を書く人、レビューする人、朝の状況を整理する秘書、記帳をする経理。人間は僕ひとりで、承認だけをやります。

この記事では、どういう設計にしたのかと、実際に踏んだ失敗を4つ書きます。うまくいった話より、こっちのほうが役に立つはずです。4つ目は、この記事のレビューで見つかったものです。

そもそも何を作ったのか

co-asrai という名前のリポジトリを1つ用意しました。ここが本社です。

製品やクライアント案件のコードは、それぞれのリポジトリに置いたままにします。本社が持つのは、会社の事実と、誰が何をやるかと、いま案件がどこまで進んだかだけです。

設計の柱にしたのは、次の3つを別々の場所に置くことでした。

  • 責任: 誰がやるか(エージェントの定義)
  • 手順: どう進めるか(スキル)
  • 状態: どこまで進んだか(案件ごとのファイル)

この3つを混ぜると、あとで自分が困ると考えています。手順書のなかに「今回はここまで終わった」と書き込みたくなるのですが、それをやると次の案件でコピーが増えていきます。

実際のディレクトリは、だいたいこんな形です。

co-asrai/
├── CLAUDE.md # 会社憲法。26行。全AI社員が毎回読む
├── company/ # 会社の事実(屋号・トーン・リポ台帳・承認ルール)
├── agent-docs/ # 役割ごとの絶対ルール(planner / reviewer / secretary / accountant)
├── .claude/
│ ├── settings.json # 権限。禁止から先に書く
│ ├── agents/ # 横断役の薄い契約
│ └── skills/ # 手順(朝の状況整理・記帳・記事制作)
├── business/ # 事業部(コンテンツ発信・LP販売・受託・自社プロダクト)
├── work/ # 案件の状態。全社で1か所
└── finance/ # 経理。AIは起案まで

会社憲法にあたるルートの CLAUDE.md は26行に収めました。長いと後半が読まれなくなる、という話をあちこちで見たからです。細かい規約は company/policies/ に逃がして、憲法には承認ゲートと禁止事項だけを書いています。

案件は work/2026-08-18-content-ai-company-build/ のように日付と事業部で1ディレクトリを作り、依頼の正本を request.yaml、進行状態を state.yaml に置きます。ちなみにこの記事も、その形式で発注されたものです。

決めごとで大事だったこと

設計のなかで、あとから効いてきたルールが3つあります。

司令塔は作業をしない。 分解と発注と統合だけをやります。自分で書き始めると、その瞬間に全体を見る人がいなくなります。

作ったAIは自分を評価しない。 レビューは別のセッション、できれば別のベンダーに出します。うちではレビューをCodexに投げていて、記事を書くのはClaude、判定はCodexという役割分担です。少なくとも僕が試した範囲では、同じモデルに自己採点をさせると、たいてい通ってしまいました。

不可逆な操作は人間で止める。 公開・送信・課金・契約・本番反映・確定記帳は、状態を awaiting_approval にして機械的に停止させます。プロンプトに「事前に聞いてね」と書くだけにはしません。書いただけのお願いが守られないことは、このあと自分で証明してしまいました。

さて、ここからが本題です。ここまでの話はきれいに聞こえますが、作っている最中はけっこう転びました。

失敗その1: 事業部に置いたスキルが、ルートから見えなかった

最初の設計では、事業部固有の手順は事業部の下に置くつもりでした。

コンテンツ発信事業部の記事制作フローなら business/content/.claude/skills/content-pipeline/ に置く、という具合です。会社の横断ルールはルート、事業部のことは事業部の下、というきれいな2階層になるはずでした。

実際に試したら、こうなりました。

  • business/content に移動してから起動したセッション: 認識される
  • リポジトリのルートで起動したセッション: 認識されない

これは困ります。司令塔もサブエージェントも、基本はルートで起動するからです。つまり実運用でいちばん使う経路から、その手順が見えていませんでした。

なぜルートから見えなかったのかは、仕様として裏を取れていません。推測ですが、スキルの探索範囲が起動時の作業ディレクトリを基準にしているのだと思います。ここは確認できていないので、断定しないでおきます。

対応は素直にフォールバックです。事業部固有の手順もルートの .claude/skills/ に置き、代わりに説明文へ事業部名を明記して区別するようにしました。設計書には「こうなるはずだった」ではなく、実測の結果とその日付を残しています。

きれいな階層を先に決めても、ツールがそう読んでくれるとは限りません。設計の受け入れ条件に「実機で認識されること」を入れておいてよかった、というのがここでの学びです。書いた時点では通ると思っていました。

失敗その2: 全角の閉じ括弧でシェルスクリプトが落ちた

役割ごとの絶対ルールは、プロンプトのお願いにせず、起動時に自動で読み込ませることにしました。

bin/hire secretary のように役割名を渡して起動すると、SessionStart のフックが agent-docs/secretary.md を読んでセッションに流し込みます。そのフックはシェルスクリプトで書きました。

そこでこう書いてしまいました。

Terminal window
set -eu
doc="$root/agent-docs/$CO_ASRAI_ROLE.md"
echo "以下は agent-docs(正本: $doc)。必ず全文に従うこと。"

読み込みは動かず、こういうエラーが出ます。

inject-role.sh: line 4: doc?: unbound variable

エラーメッセージの変数名が doc ではなく doc プラス何か、になっているのがポイントです。

日本語の文章として自然に閉じ括弧を書いたつもりが、シェルからは $doc) がひとつの変数名に見えていました。全角文字は複数バイトで表現されるので、その先頭のバイトまで変数名として食われます。結果として doc とは別の名前になり、set -u が「定義されていない変数だ」と判断して止まる、という流れです。

手元で最小のスクリプトを書いて再現も確認しました。原因はこれで確定です。

直し方は簡単で、変数を波括弧で囲って範囲をはっきりさせるだけです。

Terminal window
echo "以下は agent-docs(正本: ${doc} )。必ず全文に従うこと。"

日本語で説明文を書くエージェントが、日本語まじりのシェルスクリプトを書くと、この事故は普通に起きます。日本語を含む文字列のなかで変数を展開するときは、必ず波括弧で囲む。 単純ですが、うちのハマりどころとしては上位でした。

失敗その3: 秘書が初日に、台帳の登録漏れを自分で見つけた

3つ目は、失敗というより「AIに見つけられた失敗」です。

秘書役には朝の状況整理をやらせています。案件の状態を全部読んで、承認待ち・進行中・昨日完了・リスクの4つに整理し、さらに当日の予定と受信メールを確認して報告する、という手順です。メールとカレンダーは読み取りだけで、返信も予定作成もさせません。

これを初めて通しで動かした日に、報告のリスク欄でこう指摘されました。会社のリポジトリ台帳に、登録されていないリポジトリがある、と。

きっかけは受信メールの確認でした。届いていた通知に出てくるリポジトリ名が、台帳に載っていなかったのです。実際に開発が動いているのに、本社側の台帳には存在しない状態でした。指摘どおり roblox-game を追加して、台帳の抜けはその日のうちに埋まりました。

ついでにもう1つ指摘が出ました。経理の確定待ち件数を数える手順が、grepstatus: draft という行を拾っていて、スキーマ説明のコメント行まで件数に入れていたのです。こちらもYAMLとして読んでから数えるように直しました。

この2件は、正直うれしかったです。

台帳の抜けも件数の誤検知も、人間が毎朝ぼんやり見ていたら、まず気づきません。AIに毎朝同じ手順を機械的に踏ませると、人間が飛ばしている確認が漏れなく実行される。 手順を1回きちんと書いておく価値は、ここにあると思っています。

設計として、秘書には報告だけをさせて、台帳やファイルの書き換えは禁止しています。見つけた人がそのまま直すと、間違いに気づける人がいなくなるからです。

ただ、この「見つけたあと誰が直すのか」のところで、僕はもう1つやらかしていました。

失敗その4: 承認ゲートを作った本人が、そのゲートを素通りした

これは、この記事を書いている最中に見つかった失敗です。

さっきの台帳の話には続きがあります。この記事の最初の原稿で、僕はこう書いていました。指摘を反映したのは人間の承認を経てからです、と。

レビューを担当したCodexは、そこで止めました。承認を経たという裏が取れない、という指摘です。

確認したら、そのとおりでした。会社のルールでは、台帳を含む company/ 配下の変更は人間承認が必要で、しかも誰がいつ何を承認したかを案件の記録に残すことになっています。ところが、その記録はどこにもありませんでした。台帳への追加は、AIが見つけてAIがそのまま書き換え、AIがコミットしていました。

そのあとで僕自身が同じファイルを触っているので、結果としては追認された形になっています。ただ、承認そのものは記録に残っていません。承認は、記録がなければ後から確かめようがない。つまり無かったのと同じです。

自分で決めたルールを、自分の作ったAIが、その日のうちに素通りしていたわけです。しかも書いた本人は気づかないまま、「承認を経てから反映した」と記事に書いていました。

原因ははっきりしています。承認ゲートを、ルール文書に書いただけで済ませていたからです。

権限設定のほうで機械的に止めていたのは、メール送信やパッケージ公開のようなコマンドだけでした。統治文書の書き換えはただのファイル編集なので、コマンドの禁止リストには引っかかりません。設計原則には「プロンプトで書くだけにしない」と自分で書いていたのに、そこが抜けていました。

対応は2つです。1つは、この違反をそのまま案件の記録に残したこと。隠すと同じことが起きます。もう1つは、company/ 配下の変更を実行の直前で機械的に止める仕組みを、次のフェーズの宿題として積んだことです。

ルールは、破れる状態のまま書いてあれば破られます。 今回は別ベンダーにレビューさせていたので見つかりました。同じセッションの自分に確認させていたら、そのまま通っていた気がします。

いまの運用ループ

まとめると、うちの回し方はこうなりました。

  1. Plan: 司令塔が依頼を request.yaml に固定する。目的・入力・完了条件を先に書く
  2. Do: 実行者は会話履歴を見ずに、そのファイルと入力だけを読んで作業する
  3. Review: 別のセッションで完了条件を検査し、判定を記録に残す
  4. Approve: 公開や送信の手前で止めて、人間が承認する

3のレビューで直しが必要になったら、往復は最大2回までと決めています。それを超えたら人間に上げます。自分の感覚では、AI同士で往復を重ねても、ある回数から先はあまり良くなりません。

完了の判定は、メッセージではなく成果物で決めます。「できました」ではなく、ファイルが実在するか、スキーマに合っているか、検査が通ったか。この記事も同じで、frontmatter の検証と日本語の校正ツールが通って、レビューの判定が記録されて、最後に僕が公開を承認して終わりです。

やってみて思うこと

最初は「AI組織図を作るぞ」と意気込んでいたのですが、途中で考えが変わりました。

大事なのは肩書きではなく、業務の単位で切ることです。「AI営業部長」より「商談後のフォローメールを作る業務」のほうが、何をどこまでやるかがはっきりします。人格をつけるのは楽しいのですが、品質はそこからは出てきません。

いま動いているのはコンテンツ発信の1ラインだけです。次はLP制作販売のラインを立ち上げます。昇格の条件は決めていて、いまのラインが人間の手直しなしで3回連続で通ること。この記事が、その1回目の挑戦でした。ただ、初回のレビューは一発でFAILだったので、カウントは仕切り直しです。

一人でやっていると、抜けや先送りに気づけません。仕組みにして毎朝走らせると、代わりに気づいてくれるものができます。そこが、いちばん体感が変わったところでした。

続きはまた書きます。それでは、また。