# 機能設計書 1-Build エージェント

## 概要

本ドキュメントは、OpenCodeシステムにおけるBuild エージェントの機能設計を記述する。Build エージェントは、OpenCodeのデフォルトのフルアクセスエージェントであり、設定された権限に基づいてツールを実行し、開発作業全般を行う中核的なエージェントである。

### 本機能の処理概要

Build エージェントは、OpenCodeにおける主要なエージェントとして、ユーザーからの開発タスク指示を受け取り、利用可能なツール群（Bash、Edit、Write、Read、Grep、Glob等）を活用して、ファイル編集、コマンド実行、コード検索などの開発作業を自動的に遂行する。

**業務上の目的・背景**：開発者が日常的に行うコーディング、デバッグ、リファクタリング、テスト実行などの作業を、AI支援により効率化することが目的である。従来は開発者が手動で行っていたファイル編集やコマンド実行を、自然言語による指示で自動化することで、開発生産性を大幅に向上させる。

**機能の利用シーン**：新機能の実装、バグ修正、コードリファクタリング、テストコードの作成、ドキュメント更新など、日常的な開発作業全般で利用される。ユーザーは「このファイルにログ出力を追加して」「テストを実行して」などの自然言語指示を与えることで、エージェントが適切なツールを選択して作業を遂行する。

**主要な処理内容**：
1. ユーザーメッセージの受信と意図解析
2. 適切なツールの選択と実行計画の立案
3. 権限チェックと必要に応じたユーザー確認要求
4. ツール実行（Bash、Edit、Write、Read、Grep、Glob、Task等）
5. 実行結果の解析と次アクションの決定
6. ユーザーへの結果報告

**関連システム・外部連携**：Language Server Protocol（LSP）との連携によりコード診断情報を取得し、エラーの検出と修正を支援する。また、MCPサーバーとの連携により外部ツールの実行も可能。

**権限による制御**：Build エージェントは、設定ファイル（opencode.json）で定義された権限ルールセットに基づいて動作する。デフォルトでは、ほとんどの操作が許可されるが、.envファイルの読み取りや外部ディレクトリへのアクセスは確認を求める設定となっている。`question`権限と`plan_enter`権限がデフォルトで許可されており、質問機能とPlanモードへの遷移が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | セッション | 主画面 | デフォルトエージェントによる開発作業実行 |

## 機能種別

AI駆動型タスク実行 / ツールオーケストレーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | エージェント名（"build"固定） | 文字列型 |
| description | string | No | エージェントの説明 | 任意の文字列 |
| mode | "subagent" \| "primary" \| "all" | Yes | エージェントのモード（"primary"） | enum値 |
| native | boolean | No | ネイティブエージェントかどうか（true） | boolean型 |
| hidden | boolean | No | 非表示フラグ | boolean型 |
| topP | number | No | トップPサンプリング値 | 0〜1の数値 |
| temperature | number | No | 温度パラメータ | 0〜2の数値 |
| permission | PermissionNext.Ruleset | Yes | 権限ルールセット | 有効なルールセット配列 |
| model | {modelID, providerID} | No | 使用するモデル指定 | 有効なモデル/プロバイダーID |
| variant | string | No | モデルバリアント | 任意の文字列 |
| prompt | string | No | カスタムシステムプロンプト | 任意の文字列 |
| options | Record<string, any> | No | 追加オプション | オブジェクト型 |
| steps | number | No | 最大ステップ数 | 正の整数 |

### 入力データソース

- ユーザーからのセッションメッセージ
- 設定ファイル（opencode.json/opencode.jsonc）
- 環境変数による認証情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| assistantMessage | MessageV2.Assistant | エージェントの応答メッセージ |
| parts | MessageV2.Part[] | テキスト、ツール実行結果、推論などのパーツ |
| tokens | TokenUsage | 使用したトークン数（input/output/cache） |
| cost | number | API呼び出しコスト |
| finish | string | 終了理由（"end_turn"、"tool_use"等） |

### 出力先

- セッションデータベース（SQLite）
- UIへのリアルタイムストリーミング（SSE/WebSocket）

## 処理フロー

### 処理シーケンス

```
1. セッション開始とエージェント選択
   └─ Agent.get("build")でエージェント設定を取得
2. ユーザーメッセージの受信
   └─ MessageV2.Userとしてメッセージを保存
3. システムプロンプトの構築
   └─ SystemPrompt.provider()とエージェント固有プロンプトをマージ
4. LLMストリーミング開始
   └─ LLM.stream()でAIモデルに問い合わせ
5. ツール呼び出し処理
   └─ 権限チェック → ツール実行 → 結果処理
6. 応答テキストの生成
   └─ テキストパーツの作成と更新
7. ステップ完了処理
   └─ トークン使用量の記録、スナップショット保存
8. 継続判定
   └─ "continue"/"stop"/"compact"に基づく次アクション決定
```

### フローチャート

```mermaid
flowchart TD
    A[セッション開始] --> B[エージェント設定取得]
    B --> C[ユーザーメッセージ受信]
    C --> D[システムプロンプト構築]
    D --> E[LLMストリーミング開始]
    E --> F{ストリームイベント種別}
    F -->|tool-call| G[権限チェック]
    G -->|許可| H[ツール実行]
    G -->|拒否| I[エラー処理]
    H --> J[結果処理]
    F -->|text-delta| K[テキスト出力更新]
    F -->|finish-step| L[ステップ完了処理]
    J --> F
    K --> F
    L --> M{継続判定}
    M -->|continue| E
    M -->|compact| N[コンパクション処理]
    M -->|stop| O[セッション完了]
    I --> O
    N --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトエージェント | Buildエージェントはデフォルトのプライマリエージェントとして動作 | default_agentが未設定の場合 |
| BR-02 | ツール権限制御 | 各ツールは権限ルールセットに基づいて実行可否を判定 | ツール呼び出し時 |
| BR-03 | 質問許可 | questionパーミッションがallowに設定されユーザーへの質問が可能 | エージェント実行中 |
| BR-04 | Planモード遷移 | plan_enterパーミッションがallowでPlanモードへ遷移可能 | エージェント実行中 |
| BR-05 | Doomループ検出 | 同一ツールが同一パラメータで3回連続呼び出されると確認要求 | ツール呼び出し時 |

### 計算ロジック

- トークン使用量：input + output + cache.read + cache.write
- コスト計算：モデル固有のトークン単価に基づく

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| セッション更新 | session | UPDATE | セッションのサマリー情報更新 |
| メッセージ保存 | message | INSERT/UPDATE | アシスタントメッセージの保存 |
| パーツ保存 | message_part | INSERT/UPDATE | ツール結果・テキストパーツの保存 |
| 権限保存 | permission | SELECT/INSERT | 権限ルールの読み込みと保存 |

### テーブル別操作詳細

#### message

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | Identifier.ascending("message") | 昇順ID生成 |
| INSERT | role | "assistant" | 固定値 |
| INSERT | sessionID | 現在のセッションID | 外部キー |
| UPDATE | tokens | 使用トークン数 | ステップ完了時 |
| UPDATE | cost | APIコスト | ステップ完了時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RejectedError | ユーザーがツール実行を拒否 | 処理を停止 |
| - | CorrectedError | ユーザーがフィードバック付きで拒否 | フィードバックに基づき再試行 |
| - | DeniedError | 権限ルールにより自動拒否 | エラーメッセージ表示 |
| - | ContextOverflowError | コンテキスト長超過 | コンパクション処理 |
| - | APIError | API呼び出しエラー | リトライ処理 |

### リトライ仕様

- APIエラー発生時、SessionRetry.retryable()で再試行可否を判定
- 再試行間隔はSessionRetry.delay()で計算（指数バックオフ）
- 最大リトライ回数は設定により制御

## トランザクション仕様

- 各メッセージ・パーツの保存は個別のトランザクションで実行
- ファイル編集操作はFileTime.withLock()でファイルロックを取得

## パフォーマンス要件

- ストリーミングによりリアルタイム応答を実現
- トークン使用量に応じた自動コンパクションでコンテキスト長を管理
- 大量出力は自動截断（Truncate.MAX_LINES / Truncate.MAX_BYTES）

## セキュリティ考慮事項

- .envファイルなど機密ファイルへのアクセスは確認要求
- 外部ディレクトリへのアクセスは権限チェック
- プロジェクト外へのファイル操作は明示的な許可が必要

## 備考

Build エージェントは、OpenCodeの中心的なエージェントであり、Plan エージェントとの切り替えや、General/Exploreサブエージェントへのタスク委譲が可能。

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、エージェントの設定情報とメッセージのデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | agent.ts | `packages/opencode/src/agent/agent.ts` | Agent.Info型定義（24-49行目）でエージェントの設定スキーマを理解 |
| 1-2 | message-v2.ts | `packages/opencode/src/session/message-v2.ts` | MessageV2.User、MessageV2.Assistant、MessageV2.Part型でメッセージ構造を理解 |
| 1-3 | next.ts | `packages/opencode/src/permission/next.ts` | PermissionNext.Rule、PermissionNext.Ruleset型で権限ルール構造を理解 |

**読解のコツ**: zodスキーマによる型定義とTypeScript型推論（z.infer）の関係を把握すること。

#### Step 2: エントリーポイントを理解する

処理の起点となるエージェント初期化と取得処理を把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | agent.ts | `packages/opencode/src/agent/agent.ts` | state関数（51-251行目）でエージェント設定の初期化ロジックを理解 |

**主要処理フロー**:
1. **51-73行目**: デフォルト権限ルールセットの構築（whitelistedDirs、defaults）
2. **76-91行目**: buildエージェントの設定定義（name、description、permission、mode）
3. **253-255行目**: Agent.get()でエージェント設定を取得
4. **257-264行目**: Agent.list()でエージェント一覧を取得（デフォルトエージェント優先ソート）

#### Step 3: LLMストリーミング処理を理解する

AIモデルへの問い合わせとストリーミング処理の流れを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | llm.ts | `packages/opencode/src/session/llm.ts` | LLM.stream()（46-256行目）でストリーミング処理を理解 |

**主要処理フロー**:
- **59-64行目**: モデル設定、設定ファイル、プロバイダー、認証情報の取得
- **67-93行目**: システムプロンプトの構築とプラグイン変換
- **114-131行目**: LLMパラメータの設定（temperature、topP等）
- **172-256行目**: streamText()によるストリーミング開始

#### Step 4: セッションプロセッサを理解する

ストリームイベントの処理とツール実行の流れを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | processor.ts | `packages/opencode/src/session/processor.ts` | SessionProcessor.create()とprocess()メソッドの理解 |

**主要処理フロー**:
- **26-35行目**: プロセッサの状態初期化（toolcalls、snapshot、blocked等）
- **45-416行目**: process()メソッドでストリームイベントを処理
- **55-347行目**: fullStreamからのイベント処理ループ
- **134-179行目**: tool-callイベント処理とDoomループ検出
- **180-202行目**: tool-resultイベント処理
- **244-285行目**: finish-stepイベント処理（トークン記録、スナップショット、コンパクション判定）

#### Step 5: 権限管理を理解する

権限チェックと承認フローを把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | next.ts | `packages/opencode/src/permission/next.ts` | PermissionNext.ask()、evaluate()、reply()の理解 |

**主要処理フロー**:
- **131-161行目**: ask()で権限要求を行い、必要に応じてユーザー確認
- **163-234行目**: reply()でユーザーからの応答を処理
- **236-243行目**: evaluate()で権限ルールを評価

### プログラム呼び出し階層図

```
Session.chat() [index.ts]
    │
    ├─ Agent.get("build") [agent.ts]
    │      └─ state() → Buildエージェント設定取得
    │
    ├─ SessionProcessor.create() [processor.ts]
    │      └─ プロセッサ初期化
    │
    └─ processor.process() [processor.ts]
           │
           ├─ LLM.stream() [llm.ts]
           │      ├─ Provider.getLanguage()
           │      ├─ SystemPrompt.provider()
           │      └─ streamText() → AI SDK
           │
           ├─ イベント処理ループ
           │      ├─ tool-call → PermissionNext.ask()
           │      │                 └─ ツール実行
           │      ├─ text-delta → テキスト更新
           │      └─ finish-step → 使用量記録
           │
           └─ SessionCompaction.isOverflow()
                  └─ コンパクション判定
```

### データフロー図

```
[入力]                    [処理]                         [出力]

ユーザーメッセージ ───▶ Session.chat()
                              │
                              ├──▶ Agent.get() ───▶ エージェント設定
                              │
                              ├──▶ LLM.stream() ───▶ AIストリーム
                              │
                              └──▶ processor.process()
                                        │
                              ┌─────────┴─────────┐
                              ▼                   ▼
                        ツール実行           テキスト生成
                              │                   │
                              ▼                   ▼
                        tool結果パーツ      textパーツ ───▶ セッションDB
                              │                   │
                              └───────┬───────────┘
                                      ▼
                                アシスタントメッセージ ───▶ UI表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| agent.ts | `packages/opencode/src/agent/agent.ts` | ソース | エージェント定義と管理 |
| llm.ts | `packages/opencode/src/session/llm.ts` | ソース | LLMストリーミング処理 |
| processor.ts | `packages/opencode/src/session/processor.ts` | ソース | ストリームイベント処理 |
| next.ts | `packages/opencode/src/permission/next.ts` | ソース | 権限管理 |
| message-v2.ts | `packages/opencode/src/session/message-v2.ts` | ソース | メッセージデータ構造 |
| index.ts | `packages/opencode/src/session/index.ts` | ソース | セッション管理エントリーポイント |
| system.ts | `packages/opencode/src/session/system.ts` | ソース | システムプロンプト生成 |
| tool.ts | `packages/opencode/src/tool/tool.ts` | ソース | ツール基盤定義 |
| config.ts | `packages/opencode/src/config/config.ts` | ソース | 設定ファイル管理 |
