48 KiB
TAKTデータフロー解析
このドキュメントでは、TAKTにおけるデータフロー、特にインタラクティブモードからワークフロー実行に至るまでのデータの流れを説明します。
目次
概要
TAKTのデータフローは以下の7つの主要なレイヤーで構成されています:
- CLI Layer - ユーザー入力の受付
- Interactive Layer - タスクの対話的な明確化
- Execution Orchestration Layer - ワークフロー選択とworktree管理
- Workflow Execution Layer - セッション管理とイベント処理
- Engine Layer - ステートマシンによるステップ実行
- Instruction Building Layer - プロンプト生成
- Provider Layer - AIプロバイダーとの通信
全体フロー図
┌─────────────────────────────────────────────────────────────────┐
│ 1. CLI Layer (src/app/cli/index.ts) │
│ ユーザー入力 → 引数パース → コマンド振り分け │
└────────────────────────────┬────────────────────────────────────┘
│
┌────────────┴──────────────┐
│ │
Direct Task Input Short Input / No Args
│ │
│ ▼
│ ┌─────────────────────────────────┐
│ │ 2. Interactive Layer │
│ │ (interactive.ts) │
│ │ │
│ │ ┌─────────────────────┐ │
│ │ │ User Conversation │ │
│ │ │ - Clarification │ │
│ │ │ - Codebase Search │ │
│ │ │ - AI Response │ │
│ │ └──────┬──────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ User confirms with /go │
│ │ │ │
│ │ ▼ │
│ │ buildTaskFromHistory() │
│ │ (会話履歴 → タスク文字列) │
│ └─────────┬───────────────────────┘
│ │
└────────────────────────┘
│
│ task: string
▼
┌─────────────────────────────────────────────────────────────────┐
│ 3. Execution Orchestration Layer │
│ (selectAndExecute.ts) │
│ │
│ ┌──────────────────────┐ │
│ │ determineWorkflow() │ ← workflow選択 (interactive/override) │
│ └─────────┬────────────┘ │
│ │ workflowIdentifier: string │
│ ▼ │
│ ┌──────────────────────────────────┐ │
│ │ confirmAndCreateWorktree() │ │
│ │ - AI branchname generation │ │
│ │ - createSharedClone() │ │
│ └─────────┬────────────────────────┘ │
│ │ { execCwd, isWorktree, branch } │
│ ▼ │
│ ┌──────────────────────────────────┐ │
│ │ executeTask() │ │
│ │ - task: string │ │
│ │ - cwd: string (実行ディレクトリ) │ │
│ │ - workflowIdentifier: string │ │
│ │ - projectCwd: string (.takt/在処) │ │
│ └─────────┬────────────────────────┘ │
└────────────┼────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 4. Workflow Execution Layer │
│ (workflowExecution.ts, taskExecution.ts) │
│ │
│ ┌────────────────────────────────┐ │
│ │ loadWorkflowByIdentifier() │ │
│ │ → WorkflowConfig │ │
│ └────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────┐ │
│ │ Session Management │ │
│ │ - loadAgentSessions() │ ← projectCwd or cwd │
│ │ - generateSessionId() │ │
│ │ - createSessionLog() │ │
│ │ - initNdjsonLog() │ │
│ └────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────┐ │
│ │ WorkflowEngine initialization │ │
│ │ │ │
│ │ new WorkflowEngine( │ │
│ │ config: WorkflowConfig, │ │
│ │ cwd: string, │ │
│ │ task: string, │ │
│ │ options: { │ │
│ │ onStream, │ ← StreamDisplay handler │
│ │ initialSessions, │ ← 保存済みセッションID │
│ │ onSessionUpdate, │ ← セッション更新callback │
│ │ projectCwd, │ │
│ │ language, │ │
│ │ provider, │ │
│ │ model │ │
│ │ } │ │
│ │ ) │ │
│ └────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────┐ │
│ │ Event Subscription │ │
│ │ - step:start │ │
│ │ - step:complete │ │
│ │ - step:report │ │
│ │ - workflow:complete │ │
│ │ - workflow:abort │ │
│ └────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────┐ │
│ │ engine.run() │ │
│ └────────┬───────────────────────┘ │
└───────────┼─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 5. Engine Layer (WorkflowEngine.ts) │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ State Machine Loop │ │
│ │ │ │
│ │ while (state.status === 'running') { │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 1. Iteration & Loop Check │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 2. Get Current Step │ │ │
│ │ │ step = getStep( │ │ │
│ │ │ state.currentStep │ │ │
│ │ │ ) │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 3. Build Instruction │ │ ← InstructionBuilder
│ │ │ (if not parallel) │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 4. Emit step:start │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 5. runStep() │ │ │
│ │ │ ├─ Normal: StepExecutor │ │ ← 3-phase execution
│ │ │ └─ Parallel: ParallelRunner │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ │ { response, instruction } │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 6. Emit step:complete │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 7. Handle Blocked │ │ │
│ │ │ (if status === 'blocked') │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 8. Rule Evaluation │ │ ← RuleEvaluator │
│ │ │ resolveNextStep() │ │ │
│ │ └────────────┬───────────────────┘ │ │
│ │ │ │ │
│ │ │ nextStep: string │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ 9. Transition │ │ │
│ │ │ - COMPLETE → break │ │ │
│ │ │ - ABORT → break │ │ │
│ │ │ - other → update state │ │ │
│ │ └────────────────────────────────┘ │ │
│ │ } │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼ (from runStep)
┌─────────────────────────────────────────────────────────────────┐
│ 6. Instruction Building & Step Execution Layer │
│ │
│ ┌────────────────────────────────────────────────────────────┐│
│ │ StepExecutor.runNormalStep() ││
│ │ ││
│ │ ┌──────────────────────────────────────────────────────┐ ││
│ │ │ Phase 1: Main Execution │ ││
│ │ │ │ ││
│ │ │ InstructionBuilder.build() │ ││
│ │ │ ├─ Execution Context (cwd, permission) │ ││
│ │ │ ├─ Workflow Context (iteration, step, report) │ ││
│ │ │ ├─ User Request ({task}) │ ││
│ │ │ ├─ Previous Response ({previous_response}) │ ││
│ │ │ ├─ Additional User Inputs ({user_inputs}) │ ││
│ │ │ ├─ Instructions (instruction_template) │ ││
│ │ │ └─ Status Output Rules (tag-based) │ ││
│ │ │ │ ││
│ │ │ → instruction: string │ ││
│ │ │ │ ││
│ │ │ runAgent(agent, instruction, options) │ ││
│ │ │ → response: AgentResponse │ ││
│ │ └──────────────────────┬───────────────────────────────┘ ││
│ │ │ ││
│ │ ▼ ││
│ │ ┌──────────────────────────────────────────────────────┐ ││
│ │ │ Phase 2: Report Output (if step.report defined) │ ││
│ │ │ │ ││
│ │ │ runReportPhase() │ ││
│ │ │ - Resume session │ ││
│ │ │ - Write-only tools │ ││
│ │ │ - ReportInstructionBuilder │ ││
│ │ └──────────────────────┬───────────────────────────────┘ ││
│ │ │ ││
│ │ ▼ ││
│ │ ┌──────────────────────────────────────────────────────┐ ││
│ │ │ Phase 3: Status Judgment (if tag-based rules) │ ││
│ │ │ │ ││
│ │ │ runStatusJudgmentPhase() │ ││
│ │ │ - Resume session │ ││
│ │ │ - No tools (judgment only) │ ││
│ │ │ - StatusJudgmentBuilder │ ││
│ │ │ → tagContent: string │ ││
│ │ └──────────────────────┬───────────────────────────────┘ ││
│ │ │ ││
│ │ ▼ ││
│ │ ┌──────────────────────────────────────────────────────┐ ││
│ │ │ Rule Evaluation │ ││
│ │ │ │ ││
│ │ │ detectMatchedRule(step, content, tagContent) │ ││
│ │ │ 1. Aggregate (all()/any()) │ ││
│ │ │ 2. Phase 3 tag ([STEP:N]) │ ││
│ │ │ 3. Phase 1 tag (fallback) │ ││
│ │ │ 4. AI judge (ai("...")) │ ││
│ │ │ 5. AI judge fallback (all conditions) │ ││
│ │ │ → { index, method } │ ││
│ │ └──────────────────────┬───────────────────────────────┘ ││
│ │ │ ││
│ │ ▼ ││
│ │ response with matchedRuleIndex & matchedRuleMethod ││
│ └────────────────────────────────────────────────────────────┘│
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 7. Provider Layer (agents/runner.ts → providers/) │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ runAgent() │ │
│ │ - Resolve agent spec │ │
│ │ - Get provider │ │
│ │ - Call provider.call() │ │
│ └────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────┐ │
│ │ Provider.call() │ │
│ │ (ClaudeProvider / CodexProvider) │ │
│ │ │ │
│ │ - Build system prompt │ │
│ │ - Call SDK (callClaude / callCodex) │ │
│ │ - Stream handling (onStream callback) │ │
│ │ - Error propagation │ │
│ │ │ │
│ │ → { status, content, sessionId, ... } │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
各レイヤーの詳細
1. CLI Layer (src/app/cli/index.ts)
役割: ユーザー入力の受付とコマンド振り分け
主要な処理:
- コマンドライン引数のパース
- 入力タイプの判定:
isDirectTask(): 複数単語またはissue参照 → 直接実行- 短い単語または引数なし → インタラクティブモード
- グローバル設定の初期化 (
initGlobalDirs,initProjectDirs) - パイプラインモード vs 通常モードの判定
データ入力:
- CLI引数:
task,--workflow,--issue, など
データ出力:
task: string(タスク記述)workflow: string | undefined(ワークフロー名またはパス)createWorktree: boolean | undefined- その他オプション
2. Interactive Layer (src/features/interactive/interactive.ts)
役割: タスクの対話的な明確化
主要な処理:
-
会話ループ:
readLine(): ユーザー入力を1行ずつ読み込みcallAI(): AIプロバイダーを呼び出し- 履歴管理:
ConversationMessage[]
-
セッション管理:
loadAgentSessions(): 過去のセッションを復元updateAgentSession(): セッションIDを更新・保存
-
スラッシュコマンド:
/go: タスク確定、実行へ進む/cancel: キャンセルCtrl+D: EOF、キャンセル
-
タスク組み立て:
buildTaskFromHistory(): 会話履歴を結合してタスク文字列を生成
データ入力:
initialInput?: string(CLI引数から)- ユーザーの対話入力
データ出力:
InteractiveModeResult:confirmed: booleantask: string(会話履歴全体を結合した文字列)
3. Execution Orchestration Layer (src/features/tasks/execute/selectAndExecute.ts)
役割: ワークフロー選択とworktree管理
主要な処理:
-
ワークフロー決定 (
determineWorkflow()):- オーバーライド指定がある場合:
- パス形式 → そのまま使用
- 名前形式 → バリデーション
- オーバーライドなし → インタラクティブ選択 (
selectWorkflow())
- オーバーライド指定がある場合:
-
Worktree作成 (
confirmAndCreateWorktree()):- ユーザー確認 (または
--create-worktreeフラグ) - ブランチ名生成 (
summarizeTaskName()- AIでタスクから英語スラグ生成) createSharedClone(): git clone --shared で軽量クローン作成
- ユーザー確認 (または
-
タスク実行開始 (
selectAndExecuteTask()):executeTask()を呼び出し- 成功時: Auto-commit & Push
- PR作成 (オプション)
データ入力:
task: stringoptions?: SelectAndExecuteOptions:workflow?: stringcreateWorktree?: booleanautoPr?: boolean
agentOverrides?: TaskExecutionOptions
データ出力:
{ execCwd, isWorktree, branch }- タスク実行成功/失敗
4. Workflow Execution Layer
4.1 Task Execution (src/features/tasks/execute/taskExecution.ts)
役割: ワークフロー読み込みと実行の橋渡し
主要な処理:
loadWorkflowByIdentifier(): YAMLまたは名前からワークフロー設定を読み込みexecuteWorkflow()を呼び出し
データ入力:
ExecuteTaskOptions:task: stringcwd: string(実行ディレクトリ、cloneまたはプロジェクトルート)workflowIdentifier: stringprojectCwd: string(.takt/がある場所)agentOverrides?: TaskExecutionOptions
データ出力:
boolean(成功/失敗)
4.2 Workflow Execution (src/features/tasks/execute/workflowExecution.ts)
役割: セッション管理、イベント購読、ログ記録
主要な処理:
-
セッション管理:
generateSessionId(): ワークフローセッションID生成loadAgentSessions()/loadWorktreeSessions(): エージェントセッション復元updateAgentSession()/updateWorktreeSession(): セッション保存
-
ログ初期化:
createSessionLog(): セッションログオブジェクト作成initNdjsonLog(): NDJSON形式のログファイル初期化updateLatestPointer():latest.jsonポインタ更新
-
WorkflowEngine初期化:
new WorkflowEngine(workflowConfig, cwd, task, { onStream: streamHandler, // UI表示用ストリームハンドラ initialSessions: savedSessions, // 保存済みセッションID onSessionUpdate: sessionUpdateHandler, onIterationLimit: iterationLimitHandler, projectCwd, language, provider, model }) -
イベント購読:
step:start: ステップ開始 → UI表示、NDJSON記録step:complete: ステップ完了 → UI表示、NDJSON記録、セッション更新step:report: レポートファイル出力workflow:complete: ワークフロー完了 → 通知workflow:abort: ワークフロー中断 → エラー通知
-
SIGINT処理:
- 1回目: Graceful abort (
engine.abort()) - 2回目: 強制終了
- 1回目: Graceful abort (
データ入力:
WorkflowConfigtask: stringcwd: stringWorkflowExecutionOptions
データ出力:
WorkflowExecutionResult:success: booleanreason?: string
5. Engine Layer (src/core/workflow/engine/WorkflowEngine.ts)
役割: ステートマシンによるワークフロー実行制御
主要な構成要素:
-
State管理 (
WorkflowState):status: 'running' | 'completed' | 'aborted'currentStep: 現在実行中のステップ名iteration: ワークフロー全体のイテレーション数stepIterations: Map<stepName, count> (ステップごとの実行回数)agentSessions: Map<agent, sessionId> (エージェントごとのセッションID)stepOutputs: Map<stepName, AgentResponse> (各ステップの出力)userInputs: string[] (blocked時のユーザー追加入力)
-
コンポーネント:
OptionsBuilder: エージェント実行オプション構築StepExecutor: 通常ステップの3フェーズ実行ParallelRunner: 並列ステップの実行
-
主要メソッド:
run(): メインループwhile (state.status === 'running') { // 1. Abort & Iteration チェック if (abortRequested) { ... } if (iteration >= maxIterations) { ... } // 2. ステップ取得 const step = getStep(state.currentStep); // 3. ループ検出 const loopCheck = loopDetector.check(step.name); // 4. インストラクション構築 (非並列の場合) const instruction = stepExecutor.buildInstruction(...); // 5. イベント発行 emit('step:start', step, iteration, instruction); // 6. ステップ実行 const { response, instruction } = await runStep(step, instruction); // 7. イベント発行 emit('step:complete', step, response, instruction); // 8. Blocked処理 if (response.status === 'blocked') { ... } // 9. ルール評価 const nextStep = resolveNextStep(step, response); // 10. 遷移 if (nextStep === COMPLETE_STEP) { break; } if (nextStep === ABORT_STEP) { break; } state.currentStep = nextStep; }runStep(): ステップ実行の委譲- 並列ステップ →
ParallelRunner.runParallelStep() - 通常ステップ →
StepExecutor.runNormalStep()
resolveNextStep(): ルール評価によるステップ遷移決定response.matchedRuleIndexを使用determineNextStepByRules()で次ステップ名を取得
- 並列ステップ →
データ入力:
WorkflowConfigcwd: stringtask: stringWorkflowEngineOptions
データ出力:
WorkflowState(最終状態)- イベント発行 (各ステップの進捗)
6. Instruction Building & Step Execution Layer
6.1 Step Execution (src/core/workflow/engine/StepExecutor.ts)
役割: 3フェーズモデルによるステップ実行
3フェーズの詳細:
Phase 1: Main Execution
- 目的: エージェントのメインタスク実行
- Tools: ステップで指定されたツール (ただし
step.reportがある場合は Write を除外) - インストラクション:
InstructionBuilder.build()
Phase 2: Report Output (オプション、step.report がある場合のみ)
- 目的: レポートファイルへの出力
- Tools: Writeのみ
- インストラクション:
ReportInstructionBuilder.build() - セッション: Phase 1と同じセッションを継続 (resume)
Phase 3: Status Judgment (オプション、tag-based rulesがある場合のみ)
- 目的: ステータスタグの出力
- Tools: なし (判断のみ)
- インストラクション:
StatusJudgmentBuilder.build() - セッション: Phase 1と同じセッションを継続 (resume)
- 出力:
[STEP:N]形式のタグ
主要メソッド:
runNormalStep():
// Phase 1
const response = await runAgent(step.agent, instruction, options);
updateAgentSession(step.agent, response.sessionId);
// Phase 2 (if step.report)
if (step.report) {
await runReportPhase(step, stepIteration, context);
}
// Phase 3 (if tag-based rules)
let tagContent = '';
if (needsStatusJudgmentPhase(step)) {
tagContent = await runStatusJudgmentPhase(step, context);
}
// Rule evaluation
const match = await detectMatchedRule(step, response.content, tagContent, {...});
buildInstruction():
InstructionBuilderを使用してインストラクション文字列を生成- コンテキスト情報を渡す
6.2 Instruction Building (src/core/workflow/instruction/InstructionBuilder.ts)
役割: Phase 1用のインストラクション文字列生成
自動注入セクション:
-
Execution Context (実行環境メタデータ):
- Working directory
- Permission rules (edit mode)
-
Workflow Context:
- Iteration (workflow-wide)
- Step Iteration (per-step)
- Step name
- Report Directory/File info
-
User Request (タスク本文):
{task}プレースホルダーがテンプレートにない場合のみ自動注入
-
Previous Response (前ステップの出力):
step.passPreviousResponse === trueかつ{previous_response}プレースホルダーがテンプレートにない場合のみ自動注入
-
Additional User Inputs (blocked時の追加入力):
{user_inputs}プレースホルダーがテンプレートにない場合のみ自動注入
-
Instructions (ステップ固有のテンプレート):
step.instructionTemplateの内容- プレースホルダー置換:
{task},{previous_response},{iteration}, など
-
Status Output Rules (tag-based rules用):
hasTagBasedRules(step)の場合のみgenerateStatusRulesFromRules()で生成
プレースホルダー置換:
{task}: ユーザーリクエスト{previous_response}: 前ステップの出力{user_inputs}: 追加ユーザー入力{iteration}: ワークフロー全体のイテレーション{max_iterations}: 最大イテレーション{step_iteration}: ステップのイテレーション{report_dir}: レポートディレクトリ
ロケール対応:
language: 'en' | 'ja'- セクション見出しや説明文が言語に応じて切り替わる
7. Provider Layer
7.1 Agent Runner (src/agents/runner.ts)
役割: エージェント仕様の解決とプロバイダー呼び出し
主要な処理:
-
エージェント仕様解決:
- ビルトインエージェント (
coder,architect, など) - カスタムエージェント (
.takt/agents.yaml) - プロンプトファイル (
.md)
- ビルトインエージェント (
-
プロバイダー取得:
getProvider(providerType): ClaudeProvider / CodexProvider / MockProvider
-
エージェント呼び出し:
provider.call(agentName, instruction, options)
データ入力:
agent: string(エージェント名またはパス)instruction: string(構築済みインストラクション)AgentRunOptions:cwd: stringsessionId?: stringallowedTools?: string[]provider?: ProviderTypemodel?: stringonStream?: StreamHandler
データ出力:
AgentResponse:agent: stringstatus: 'success' | 'blocked'content: stringsessionId?: stringerror?: stringtimestamp: Date
7.2 Provider (src/infra/providers/)
役割: AIプロバイダー(Claude, Codex)とのSDK通信
主要なプロバイダー:
ClaudeProvider: Claude Code SDK (@anthropic-ai/claude-agent-sdk)CodexProvider: Codex APIMockProvider: テスト用
主要メソッド:
call():
async call(
agentName: string,
instruction: string,
options: ProviderCallOptions
): Promise<AgentResponse>
処理内容:
- システムプロンプト構築
- SDK呼び出し (
callClaude()/callCodex()) - ストリーミング処理 (
onStreamcallback) - エラーハンドリング
- レスポンス変換
データ入力:
agentName: stringinstruction: stringProviderCallOptions:cwd: stringsessionId?: stringsystemPrompt?: stringallowedTools?: string[]model?: stringonStream?: StreamHandler
データ出力:
AgentResponse(上記と同じ)
データフローの段階
ステージ1: タスク入力
入力方法:
- 直接タスク:
takt "Fix the login bug" - Issue参照:
takt #123 - インタラクティブモード:
taktまたはtakt a
データ変換:
- インタラクティブモード:
ConversationMessage[]→task: stringbuildTaskFromHistory(): 会話履歴を結合
出力: task: string
ステージ2: 実行環境準備
ワークフロー選択:
--workflowフラグ → 検証- なし → インタラクティブ選択 (
selectWorkflow())
Worktree作成 (オプション):
confirmAndCreateWorktree():- ユーザー確認または
--create-worktreeフラグ summarizeTaskName(): タスク → 英語スラグ (AI呼び出し)createSharedClone(): git clone --shared
- ユーザー確認または
データ:
workflowIdentifier: string{ execCwd, isWorktree, branch }
ステージ3: ワークフロー実行初期化
セッション管理:
loadAgentSessions(): 保存済みセッション復元generateSessionId(): ワークフローセッションID生成initNdjsonLog(): NDJSON ログファイル作成
WorkflowEngine作成:
new WorkflowEngine(workflowConfig, cwd, task, {
onStream,
initialSessions,
onSessionUpdate,
projectCwd,
language,
provider,
model
})
データ:
WorkflowState: 初期状態currentStep = config.initialStepiteration = 0agentSessions = initialSessions
ステージ4: ステップ実行ループ
各イテレーション:
- ステップ取得:
getStep(state.currentStep) - インストラクション構築:
InstructionBuilder.build() - ステップ実行: 3フェーズ実行
- ルール評価:
detectMatchedRule() - ステップ遷移:
resolveNextStep()→ 次のステップ名
データ変換:
task + context→instruction: stringinstruction→AgentResponse(via Provider)AgentResponse + rules→matchedRuleIndexmatchedRuleIndex→nextStep: string
ステージ5: インストラクション生成
InstructionBuilder処理:
-
コンテキスト収集:
task: 元のユーザーリクエストiteration,maxIterations: イテレーション情報stepIteration: ステップごとの実行回数cwd,projectCwd: ディレクトリ情報userInputs: blocked時の追加入力previousOutput: 前ステップの出力reportDir: レポートディレクトリ
-
セクション組み立て:
- 自動注入セクション (上記7つ)
- プレースホルダー置換
-
出力: 完全なインストラクション文字列
ステージ6: エージェント実行
Phase 1: Main Execution:
runAgent()→provider.call()- ストリーミング →
onStreamcallback → UI表示 - 結果:
AgentResponse
Phase 2: Report Output (オプション):
- 同じセッションを継続 (resume)
- Write-only ツール
- レポートファイル出力
Phase 3: Status Judgment (オプション):
- 同じセッションを継続 (resume)
- ツールなし
[STEP:N]タグ出力
ステージ7: ルール評価と遷移
ルール評価 (detectMatchedRule()):
5段階のフォールバック:
- Aggregate (
all()/any()) - 並列ステップ用 - Phase 3 tag -
[STEP:N]from status judgment - Phase 1 tag -
[STEP:N]from main output (fallback) - AI judge -
ai("condition text")rules - AI judge fallback - すべての条件をAIで評価
出力: { index: number, method: RuleMatchMethod }
遷移:
determineNextStepByRules():rules[index].nextを取得- 特殊ステップ:
COMPLETE: ワークフロー完了ABORT: ワークフロー中断
- 通常ステップ:
state.currentStep = nextStep
重要な変換ポイント
1. 会話履歴 → タスク文字列
場所: src/features/interactive/interactive.ts
function buildTaskFromHistory(history: ConversationMessage[]): string {
return history
.map((msg) => `${msg.role === 'user' ? 'User' : 'Assistant'}: ${msg.content}`)
.join('\n\n');
}
重要性: インタラクティブモードで蓄積された会話全体が、後続のワークフロー実行で単一の task 文字列として扱われる。
2. タスク → ブランチスラグ (AI生成)
場所: src/infra/task/summarize.ts (呼び出し: selectAndExecute.ts, taskExecution.ts)
await summarizeTaskName(task, { cwd })
処理:
- タスク文字列をAIに渡す
- 英語の短いスラグに要約 (例:
fix-login-bug) - ブランチ名として使用
重要性: ユーザーが日本語でタスクを書いても、Git-friendlyなブランチ名が自動生成される。
3. ワークフロー設定 → WorkflowState
場所: src/core/workflow/engine/state-manager.ts
function createInitialState(
config: WorkflowConfig,
options: WorkflowEngineOptions
): WorkflowState {
return {
status: 'running',
currentStep: config.initialStep,
iteration: 0,
stepIterations: new Map(),
agentSessions: new Map(Object.entries(options.initialSessions ?? {})),
stepOutputs: new Map(),
userInputs: [],
};
}
重要性: YAMLで定義された静的な設定が、実行時のミュータブルな状態に変換される。
4. コンテキスト → インストラクション文字列
場所: src/core/workflow/instruction/InstructionBuilder.ts
入力:
step: WorkflowStepcontext: InstructionContext(task, iteration, previousOutput, userInputs, など)
処理:
- 7つのセクションを組み立て
- プレースホルダー置換
- ロケール対応
出力: 完全なMarkdown形式のインストラクション文字列
重要性: 散在するコンテキスト情報が、エージェントが理解できる単一の文字列に統合される。
5. AgentResponse → ルールマッチ
場所: src/core/workflow/evaluation/RuleEvaluator.ts
入力:
step: WorkflowStepcontent: string(Phase 1 output)tagContent: string(Phase 3 output)state: WorkflowState
処理:
- タグ検出 (
[STEP:0],[STEP:1], ...) - AI判断 (
ai("condition")ルール) - 集約評価 (
all(),any())
出力: { index: number, method: RuleMatchMethod } | null
重要性: 自然言語の出力が、構造化されたステップ遷移決定に変換される。
6. ルールマッチ → 次ステップ名
場所: src/core/workflow/engine/transitions.ts
function determineNextStepByRules(
step: WorkflowStep,
matchedRuleIndex: number
): string | null {
const rule = step.rules?.[matchedRuleIndex];
return rule?.next ?? null;
}
重要性: インデックス番号が、実際に実行すべきステップ名に変換される。
7. Provider Response → AgentResponse
場所: src/infra/providers/claude.ts, src/infra/providers/codex.ts
入力: SDKレスポンス (ClaudeResult)
処理:
status変換content抽出error伝播 (重要!)sessionId保存
出力: AgentResponse (統一インターフェース)
重要性: 異なるプロバイダーのレスポンスが統一形式に正規化される。
まとめ
TAKTのデータフローは、7つのレイヤーを通じて、ユーザーの自然な入力を段階的に変換し、最終的にAIエージェントの協調的な実行に変えていきます。
主要な設計原則:
- Progressive Transformation: データは各レイヤーで少しずつ変換され、次のレイヤーに渡される
- Context Accumulation: タスク、イテレーション、ユーザー入力などのコンテキストが蓄積される
- Session Continuity: エージェントセッションIDが保存・復元され、会話の継続性を保つ
- Event-Driven Architecture: WorkflowEngineがイベントを発行し、UI、ログ、通知が連携
- 3-Phase Execution: メイン実行、レポート出力、ステータス判断の3段階で、明確な責任分離
- Rule-Based Routing: ルール評価の5段階フォールバックで、柔軟かつ予測可能な遷移
このアーキテクチャにより、TAKTは複雑な多エージェント協調を、ユーザーには透明で、開発者には拡張可能な形で実現しています。