ループエンジニアリングのための「カンバン」と「ツール」を作る

ループエンジニアリングというのが、数カ月前から勃興しだした。
3月ごろには、「AI Agent組織」を作っていたが、どうやら今のトレンドはとってかわった様子。

しかし、複数のエージェントでメッセージをまたぐのか、それとも持ち回りながらエージェントが参照するのか。で実行主体の数が異なるだけのように感じる点もある。

今回は、ループエンジニアリングのためのカンバンを作ったので共有する。

実装物

実装

基本方針として、ループエンジニアリングをさせるための前提としては、ralph-loopを前提とする。

  • 1回の実行当たりのコンテキストを小さく保ち、
  • 実行の都度でClaude事態を立ち上げ直す。

ただし、テストの成否や完了トークンのようなものは無く、やったらチェックし、全体の実行計画の中で何度も検証させる方針を取ることにする。

基本的に実装については、手での操作はほぼ0で進めた。
全体方針と利用技術、エンドポイント構成など、上流工程の要素のみをChatGPTと相談して大枠を確定。
その会話内容をCopilotに渡して、実装計画を策定させ実装した。

利用技術は、以下の通り。

  • Deno
  • Hono
  • SQlite

これを基本として、Webサーバ及びMCPサーバーを構築した。
また、これを扱うための、Clientやskillも構築した。
Clientはさておき、Claudeに使わせるためのskill構築は、Copilotにやらせるのはうまくいかず、これはClaudeに作り直しをさせている。

データべ―ス構造

テーブルは4テーブル構成。

tasks

カラム名 制約 説明
id INTEGER PRIMARY KEY AUTOINCREMENT タスクID
title TEXT NOT NULL タイトル
description TEXT NOT NULL, DEFAULT ‘’ 説明
status TEXT NOT NULL ステータス
priority INTEGER NOT NULL, DEFAULT 0 優先度
created_at TEXT NOT NULL 作成日時
updated_at TEXT NOT NULL 更新日時

todos

カラム名 制約 説明
id INTEGER PRIMARY KEY AUTOINCREMENT TodoID
task_id INTEGER NOT NULL 親タスクID
type TEXT NOT NULL 種別
title TEXT NOT NULL タイトル
status TEXT NOT NULL ステータス
priority INTEGER NOT NULL, DEFAULT 0 優先度
order_no INTEGER NOT NULL, DEFAULT 0 表示順
created_at TEXT NOT NULL 作成日時
updated_at TEXT NOT NULL 更新日時

questions

カラム名 制約 説明
id INTEGER PRIMARY KEY AUTOINCREMENT 質問ID
todo_id INTEGER NOT NULL 親TodoID
context TEXT NOT NULL コンテキスト
question TEXT NOT NULL 質問内容
answer TEXT 回答内容
status TEXT NOT NULL ステータス
created_at TEXT NOT NULL 作成日時
answered_at TEXT 回答日時

todo_logs

カラム名 制約 説明
id INTEGER PRIMARY KEY AUTOINCREMENT ログID
todo_id INTEGER NOT NULL 親TodoID
message TEXT NOT NULL ログメッセージ
created_at TEXT NOT NULL 作成日時

このテーブルにタスクと、タスクを分解したtodoを列挙し、逐次呼び出し続け作業させる。

ループツール

先の通り、基本的には、ralph-loopを前提としている。
そのため、claude cliを定期的に呼び出し続けることが必要になる。

一番有名なのは次の1行のshell。

1
while :; do cat PROMPT.md | claude-code ; done

作業を無限に繰り返し続ける。
これをDeno的には、以下のように記述できる。

1
2
3
4
5
6
7
8
9
10
while (true) {
const child = new Deno.Command("claude", {
args: ["--dangerously-skip-permissions", "-p", prompt],
stdin: "inherit",
stdout: "inherit",
stderr: "inherit",
}).spawn();

await child.status;
}

これに加え、私はMAXプランに契約したりはしていないので、ループさせつつ抑制のために、基本的には1分に1回の実行するようにしている。

そのうえで、以下を考慮しインターバルを長くとることにしている。

  • 先のサーバーアプリにタスクの登録状況を問い合わせてなければ 10分待機
  • Claudeの利用率80%を越えたら10分待機
  • Claudeの利用率90%を越えたら30分待機

何ができたのか

Claudeとの対話で作った実装計画、またはWEB画面でのタスク登録によりTODOアプリを作成した。

とりあえずTODOアプリであるが、
環境構築から、スタイリング・画像の登録や複数枚プレビューまで、直接のソース編集無しで構築できた。

開発途上での質問

実装計画を立てたもの、ツールを介して起動したClaudeが問題を解決できないことがある。
これは、カンバンのtodoとして人に答えさせる質問を登録する形にした。
そしてその質問と回答のペアを次のループで返して実行させることで解決させることができた。

しかし、質問に答えてもコンテキストを細かく切っている弊害か、質問の基になったtodoを解決できずに質問を繰り返すケースもあったので、これは改善の余地がある。


今回プロトタイプとして、作ってみてかなり所感をつかめた。
今回の実装では、ブランチの拘束もしていないかなり自由度を持たせた呼び出しをしているが、拘束を強めることをしていけば、より安定して動作するようになるのではないかと考えている。

では。