ループエンジニアリングを業務タスクで1本組んでみた。cronとの違いが分かるまで
2026年6月から、ループエンジニアリングという言葉をやたら見るようになりました。発端はOpenClawの作者Peter Steinbergerの投稿で、「もうコーディングエージェントにプロンプトを書くな。エージェントにプロンプトを書くループを設計しろ」という趣旨のもの。Claude Codeを率いるBoris Chernyも「もうClaudeに直接指示は出していない。ループがClaudeにプロンプトしている」と語っていて、翌日にはGoogleのAddy Osmaniが概念を整理してLoop Engineeringと名付けたそうです。
概念の解説記事はすでにたくさんあります。ただ、読んだだけだと正直ピンと来なかった。「それ、cronで定期実行してるのと何が違うの?」という疑問が最後まで消えなかったからです。
なので、自分の業務タスクで1本組んでみました。この記事は、その過程で「ただの定期実行」と「ループ」の違いがどこにあるのかが分かるまでの記録です。実際に作ったファイル一式(サンプル)も載せています。
先に用語だけ
本文で使う言葉を最初にまとめておきます。知っている人は飛ばしてください。
| 用語 | 意味 |
|---|---|
| cron(クーロン) | LinuxやMacに昔からある定時実行の仕組み。「毎朝9時にこのコマンドを実行しろ」のような予約ができる。crontabという設定ファイルに書く |
| claude -p | Claude Code(AnthropicのAIコーディングツール)を、対話画面を開かずコマンド1発で実行するモード。ヘッドレス実行とも呼ぶ。スクリプトに組み込める |
| MCP | AIが外部サービス(今回ならSlack)を読み書きするための接続規格。腕のようなもの |
| SKILL.md | Claudeに覚えさせたい手順や注意点を書いておくファイル。毎回口頭で説明する代わりに、これを読ませる |
| permalink | Slackの各メッセージに付く固有URL。「この投稿を確認した」という証拠として使える |
| state.json | 今回自作した状態ファイル。前回の実行結果を次回に引き継ぐための記憶置き場 |
題材にしたタスク
私は職業訓練校で新卒研修を見ています。新卒のメンバーには毎日Slackの専用チャンネルに進捗を投稿してもらっているのですが、全員分を毎朝目視で確認するのが地味に面倒でした。誰がいつ投稿したか、止まっている人はいないか。確認自体は5分で終わりますが、忘れる日もあるし、見る人の気分で基準がぶれる。
ループエンジニアリングの解説記事でも、ログの巡回点検はループに向いているタスクの筆頭に挙げられていました。判定基準を数値にできて(48時間投稿がなければ要確認)、証拠も残せて(Slackのpermalink)、間違えても何も壊れない。練習台としてはちょうどいい。
なお、以降のサンプルに出てくる氏名はすべて仮名(田中太郎など)に置き換えています。
最初に作ったもの。そして「これcronでは?」
最初のバージョンはこうでした。
- SKILL.mdに手順を書く(チャンネルを探す、24時間分読む、人ごとに最終投稿を抽出、48時間超えたら要確認)
-
claude -pでそのスキルを非対話実行するシェルスクリプトを書く - crontabに登録して毎朝9時半に回す
crontabの中身は1行です。
30 9 * * 1-5 /home/kazu/shinsotsu-tracker/scripts/run_daily.sh
意味は「平日(1-5=月〜金)の9時30分に、このスクリプトを実行しろ」。これで毎朝、進捗の一覧が勝手にログに落ちるようになりました。
動きます。でも作った本人が一番違和感を持ちました。これ、AIを呼んでいるだけの定期バッチでは?
この疑問、実は的を射ていたようです。X上でも「ただの帽子をかぶったcron jobだろ」という冷ややかな声はあったらしい。で、解説記事を読み直して分かったのは、cronとループを分けるのは起動方法ではないということでした。
分かれ目は記憶の循環だった
最初のバージョンの何が問題だったか。毎朝の実行が、前日の結果を一切参照していなかったことです。
毎日ゼロから全員を調べ直す。昨日「この人は投稿が見つからない」と判定した人を、今日もまた7日分遡って探す。昨日通知した要確認者に、今日も同じ通知を出す。実行のたびに結果を捨てているので、円環がつながっていない。定時実行の直線を毎日並べているだけでした。
直し方は単純で、state.jsonという状態ファイルを1個作りました。実物(仮名版)はこうです。
{
"last_run": "2026-07-04",
"members": {
"田中太郎": { "last_post": "2026-07-03T09:11:37+09:00", "status": "ok", "consecutive_missing_days": 0 },
"田中二郎": { "last_post": "2026-07-03T09:01:14+09:00", "status": "ok", "consecutive_missing_days": 0 },
"田中三郎": { "last_post": "2026-06-29T09:08:56+09:00", "status": "escalated", "consecutive_missing_days": 4, "escalated_on": "2026-07-03" },
"田中四郎": { "last_post": null, "status": "unresolved", "note": "表記ゆれ/別チャンネル/未参加の可能性" },
"田中五郎": { "last_post": null, "status": "unresolved", "note": "同上" },
"田中六郎": { "last_post": null, "status": "unresolved", "note": "同上" }
},
"lessons": [
"氏名だけの突合は表示名ゆらぎで漏れる。フルネームで突合する",
"24時間窓だけで未報告と断定しない。必ず遡って確認する"
]
}
statusは3種類。ok(直近の投稿あり)、escalated(要確認として通知済み)、unresolved(投稿自体が見つからず原因未特定)。lessonsには実行して学んだ注意点が溜まっていきます。
このファイルを、実行前に読む。状態に応じて動きを変える。実行後に書き戻す。
- unresolvedの人は毎回7日分遡る無駄をやめて据え置き
- escalated済みの人には再通知しない(毎日同じアラートが来ると人間が無視するようになる)
- okの人は直近24時間だけ見る
これを入れた瞬間、動作が変わりました。無駄な探索が消えて、通知のノイズも消えた。昨日の結果が今日の動きを変える。この循環ができて初めてループと呼べる、というのが体感として理解できた瞬間です。モデルは毎回忘れますが、ファイルは忘れないんですね。
ちなみにcron自体は悪者ではありません。解説記事でもAutomations(自動起動)は正当な部品として位置づけられています。心臓の鼓動は毎朝cronが打つ。でも記憶と判断はループ側が持つ。この分担が答えでした。
それでも足りなかった2つ
記憶を循環させて満足しかけたのですが、解説記事3本(Zenn、Qiita、DevelopersIO)と自分の実装を突き合わせたら、共通して欠けているものが2つ見つかりました。
検証役の分離(Maker-Checker)
作業したエージェントが「全員分確認しました」と言う。それを信じていいのか。よくないらしいです。どの記事も、作業役の完了報告は自己申告であって証明ではないと釘を刺していました。実際、DevelopersIOの記事では、レビュー役のエージェントが「テストの期待値の方を改ざんして通ったことにしていた」不正を検出した例が紹介されていて、これはちょっと怖かった。
なので2段構成にしました。Slackを読んでまとめるMaker(作業役)とは別に、検証専用のChecker(検証役)を別モデル(Haiku。速くて安いモデル)で走らせます。スクリプトの該当部分の抜粋がこれです。
# ── Checker(検証役・別モデル・読むだけ)──
checker_out=$(claude -p "あなたはこの成果物を書いていない独立した検証者です。
疑ってかかってください。次の観点だけで検証し、最初の行にPASSまたは
FAILとだけ書いてください。
検証観点:
1. 対象者全員に判定がついているか
2. 判定にpermalinkが添えられているか
3. state.jsonが正しいJSONで、membersが欠落していないか
4. 前回escalated/unresolvedだった人が、証拠なしにokに
書き換えられていないか
前回のstate.json: ${PREV_STATE}
検証対象: ${maker_result}" \
--model claude-haiku-4-5 --max-turns 3 --max-budget-usd 0.10)
冒頭の「あなたはこの成果物を書いていない」という一文は、自分の作業に甘くなる確証バイアスを言葉で打ち消すための定石だそうです。観点4が、うちのタスクにおける採点表の改ざん検知にあたります。要確認だった人を、証拠なしに勝手にokへ戻していないかを見る。
CheckerがFAILを出したら指摘をMakerに戻して再実行。2回失敗したらstate.jsonを更新せずに人間へ投げます。壊れた状態を記憶に残さないためです。
上限の宣言
もう1つはコストと回数の天井です。Uberが社員のAIツール利用に月1500ドルの上限を入れた、年間予算を4か月で使い切ったからだ、という報道があったそうで、笑い話にできない。スクリプトの冒頭に、ループを書くより先に停止条件を書きました。
# ── 停止条件(先に書く) ─────────────────
MAX_ATTEMPTS=2 # Checker FAIL時の再試行上限
MAX_TURNS=15 # 1回のclaude -p のターン上限
MAX_BUDGET_PER_RUN=0.50 # 1回の呼び出しコスト上限(USD)
DAILY_BUDGET_USD=2.00 # 日次累計。80%到達で実行スキップ
STUCK_DAYS_LIMIT=14 # unresolvedがこの日数続いたら仕組みを見直す
あと細かい話ですが、claude -p(ヘッドレス実行)は2026年6月からサブスクとは別のメーター課金になっています。定期実行に載せるなら、この課金体系は先に確認しておいたほうがいいです。
対応表。どのファイルがループのどの部品なのか
ここまでの構成物を、Addy Osmani流の6モジュールと、設計手順の5ステップに対応させるとこうなります。自分で作ったものがどの部品に当たるのかは、この表を作って初めて整理できました。
6モジュールとの対応
| モジュール | 役割 | 今回の実装 |
|---|---|---|
| Automations(自動起動) | 決まった時刻やイベントで勝手に起動する | crontab(平日9:30) |
| Skills(手順の固定) | 毎回の説明を省くための知識ファイル | SKILL.md(手順、48時間ルール、過去の罠) |
| Connectors(外部接続) | 外部サービスを読み書きする腕 | Slack MCP |
| Memory(記憶) | 会話の外に状態を残し、次回に引き継ぐ | state.json(status、lessons) |
| Sub-agents(牽制役) | 作業役と別の目で検証する | Checker(Haikuによる別モデル検証) |
| Worktrees(並行作業) | 複数タスクを隔離して同時に走らせる | 未使用(6人規模では過剰と判断) |
設計手順5ステップとの対応
| ステップ | 内容 | 今回の実装 |
|---|---|---|
| 1. 目標契約 | ゴールと受け入れ基準、禁止事項を先に決める | 48時間ルール、permalink必須、本人への連絡禁止 |
| 2. 実行 | エージェントに作業させる | Maker(claude -p + SKILL.md) |
| 3. 証拠フィードバック | 完了報告に検証可能な証拠を付けさせる | 判定ごとのSlack permalink |
| 4. 停止条件 | 合格、引き渡し、中断の出口を決める | 4分類の判定表+再試行上限+予算ガード |
| 5. 経験の還元 | 学んだことを次の周回に反映する | lessonsへの追記、SKILL.mdの更新 |
作る順番もこの表の通りでした。いきなり自動起動から作ると、不安定なものを毎日回すだけになる。手動で1回動くもの(ステップ2)を作り、知識を固定し(Skills)、証拠と停止条件を整え、最後にcronを繋ぐ。この順番が一番手戻りが少なかったです。
人間の仕事はどこに残るか
いま私がこのループに対してやることは3つだけです。要確認の基準を決める(48時間)。通知が来たときに本人へ声をかけるかどうか判断する。未解決が2週間続いたら仕組み自体を見直す。
毎朝Slackを開いて目視確認する仕事は消えました。代わりに、判定基準と例外処理を設計する仕事が残った。Osmaniの締めの一文に、起動ボタンを押すだけの人ではなくエンジニアであり続けるつもりの人としてループを作れ、という趣旨のものがあって、これはその通りだと思います。ループに任せた瞬間に中身を理解する努力をやめたら、間違いも高速で量産されるだけなので。
なお、このループは報告しかしません。本人への催促を自動化することも技術的にはできますが、やっていません。解説記事の用語でいうL1(報告のみ)です。監視されている感を新卒に与えるかどうかは技術ではなく運用の問題で、そこはまだ自分の中で結論が出ていません。自律度を上げるのは、L1の報告が信頼できると確認できてからで十分だと考えています。
まとめ
- cronで毎朝AIを起動するだけでは、定時実行であってループではない。前回の結果が今回の動きを変える記憶の循環(state.json)が入って初めてループになる
- 作業役の完了報告は自己申告。別モデルの検証役(Maker-Checker)と、改ざん検知の観点を入れる
- 停止条件と予算はループを書く前に決める。再試行上限、ターン上限、日次予算
- 最初のタスクは、判定を数値化できて、間違えても壊れない読み取り専用のものを選ぶ
構成はSKILL.md(手順と禁止事項)、state.json(記憶)、シェルスクリプト(Maker→Checker→状態更新の制御)の3ファイルだけです。派手さはないですが、この小ささでもループの型は一通り学べました。次は社内の週報システムの未提出チェックに同じ型を移植する予定です。
参考記事
- もうプロンプトを書くな。「Loop Engineering」という新しいパラダイムの正体(Zenn / acrosstudioblog)
- 入門から実践「ループエンジニアリング」(Qiita / Syoitu)
- Loop EngineeringをClaudeを使って実践してみた。(DevelopersIO / クラスメソッド)