エンジニア選書 作って学ぶAIエージェント ──TypeScriptとLLMで切り拓くAI時代のエンジニアリング
- laiso 著
- 定価
- 3,520円(本体3,200円+税10%)
- 発売日
- 2026.4.20
- 判型
- B5変形
- 頁数
- 304ページ
- ISBN
- 978-4-297-15565-0
サポート情報
概要
ソフトウェア開発の世界では「AIエージェント主導のコーディング」が主流になろうとしています。エージェントはコードを生成するだけでなく、ファイルを読み、コマンドを実行し、テストを実行し、結果を確認し、必要に応じて修正を繰り返します。
本書は、こうしたAIエージェントのしくみを「使う」のではなく「作る」ための実践的なガイドです。最終的にはGitHubのIssueを起点に、コードの修正からプルリクエストの作成までを自動化するコーディングエージェントを実装します。扱う技術はTypeScriptとBunを中心にし、GitHubへの統合までを扱います。
ここでは、エージェントの動作原理、つまり思考のしくみを自ら実装し、挙動の予測と制御、目的に合わせたカスタマイズを扱います。
実装するAIエージェントは、筆者が「Nano Code」と名付けたものです。LLM APIとの接続、ファイルやコマンドを扱うツール、思考ループ、Git操作、実用環境への統合といったレイヤーを章ごとに積み上げ、最終的に実用的な自動化まで進みます。章を追って段階的に構築し、コーディングエージェントとして機能する流れを整理します。
対象読者は、TypeScriptでアプリケーションやコマンドラインツールを作った経験があり、AIエージェント開発やLLM活用に関心があるエンジニアです。TypeScriptとLLMを軸に、AI時代のエンジニアリングの実践手法を解説します。
こんな方にオススメ
- TypeScriptを使ったことのあるWebエンジニア
- AIエージェント開発やLLM活用に興味があるエンジニア
- 新しい技術や開発手法を学びたいエンジニア
目次
第1部 AIエージェント開発の全体像をつかむ
第1章 AIエージェントが拓く新しい開発スタイル
1.1 AIエージェントの台頭と開発手法の変化
1.2 AIエージェントを学ぶ意義
- コードベース理解の困難さ
- 定型作業の繰り返し
- 手動作業の積み重ね
- AIエージェントの具体的な効果
- LLMのブラックボックス性
- Nano Codeの実例
- AIエージェントが「エージェント」を作ることの利点
1.3 本書のゴール──3つのコンポーネントで作るAIエージェント
- nano-code-core──Nano CodeのLLM APIへの接続レイヤー
- nano-code-cli──Nano Codeのローカル実行環境
- nano-code-action──Nano CodeのGitHub Actions統合
- ゴール設定の理由
1.4 本書の学習アプローチ
- 本書を読むための前提知識
- 使用する技術スタック
- 自分で作ることで得られる理解
- 自作する目的──ブラックボックス問題への回答
1.5 AIエージェントの構成要素──ツールと思考ループ
- ツール──AIエージェントの「手足」
- LLM API──推論の基盤
- 思考ループ──AIエージェントの「頭脳」
- AIエージェント設計の基本原則──すべては会話
- 潜在的な課題
1.6 本書の学習ロードマップ
1.7 この章のまとめと次のステップ
第2章 開発環境とLLM APIの基礎
2.1 TypeScriptを採用する理由
- Web開発者にとっての親しみやすさ
- 型安全性による開発体験の向上
- 非同期処理のサポート
2.2 Bunを採用する理由
- オールインワン・ツールキット
- TypeScriptのネイティブサポート
- CI/CDとの統合
- AIエージェント開発との親和性
2.3 Dev Containerを採用する理由
- Dev Containerの概要
- AIエージェント開発における安全性
2.4 LLM APIの基礎
- 各プロバイダーのAPI名称
- Chat Completions互換APIのデファクトスタンダード化
- OpenAIの新しいResponses API
- Chat Completions APIのしくみ
- 会話履歴全体を送信する
- メッセージ配列形式
- AIエージェント開発におけるシンプルさの価値
2.5 開発環境のセットアップ
- すぐ始めたい場合
- ステップ1:Dockerのインストール確認
- ステップ2:プロジェクトディレクトリの作成
- ステップ3:Dockerfileの作成
- ステップ4:devcontainer.jsonの作成
- ステップ5:コンテナの起動
- VS Codeから起動する(推奨)
- VS Codeを使わない場合
- ステップ6:プロジェクトの初期化と必要なパッケージのインストール
- ステップ7:APIキーの設定
- セットアップ時のトラブルシューティング
- Docker関連
- Dev Container起動関連
- Dev Containerのリセットと削除
- VS Code使用時──Dev Containerのリセット
- コマンドラインから削除──Dev Containerの削除
- APIキー関連
2.6 本書で使用するモデル
- 軽量モデルと高性能モデル
- 本書のハンズオンでは軽量モデルで十分
- モデルIDの確認
2.7 ハンズオン(1):最初のAPIコール
- なぜ最初にfetchで呼び出すのか
- ファイルの作成
- 最小限のAPIコール
- APIレスポンスの構造
- 最終的なディレクトリ構造
2.8 この章のまとめと次のステップ
第2部 AIエージェントの「身体」を作る
第3章 LLM APIへの抽象化レイヤーを実装する
3.0 これまでの振り返りと、この章で作るもの
- LLM APIを扱う3つの選択肢
- 公式SDKを使いつつ、抽象化レイヤーを自作する
- API仕様の変更頻度
- この章で実装するもの
- 抽象化が必要となる背景
- SDKと抽象化レイヤーの役割分担
3.1 抽象化レイヤーの必要性
- SDKを使っても消えない差異
- メッセージ構造の差異
- システムメッセージの扱い
- Function Calling──LLMがツールを呼び出すしくみ
- ツール呼び出しの形式
- 抽象化レイヤーの役割
- nano-code-coreの構成
- Factoryパターンを採用する理由
- ストリーミングへの対応
- なぜ非ストリーミングから始めるのか
3.2 型定義──統一インタフェースの設計
- 型定義のポイント
- 抽象化の範囲
3.3 プロバイダー層の実装
- 依存パッケージのインストール
- 実装するプロバイダー
- プロバイダーの構造
- プロバイダーの設計
- OpenAIプロバイダーの実装
- 変換関数の役割
- Anthropicプロバイダーの実装の差分
- システムメッセージの分離
- ツール実行結果の形式
- 終了理由のマッピング
- Googleプロバイダーの実装の差分
- contentsとparts構造
- modelロール
- ツール定義の形式
- toolCallIdの生成
- 終了理由のマッピング
- 各プロバイダーの完全なソースコード
- Anthropicプロバイダー
- Googleプロバイダー
3.4 ハンズオン(2):generateText関数の実装
3.5 ハンズオン(3):マルチプロバイダー対応のテスト
3.6 プロバイダー間の差異吸収の整理
- SDKを使っても残る変換処理
- 配列構造のレスポンス処理
3.7 この章のまとめと次のステップ
第4章 Nano Codeの「手足」となるツールを実装する
4.0 これまでの振り返りと、この章で作るもの
- この章で実装する4つのツール
- ツールを構成する3つの要素
4.1 ローカル環境でのコマンド実行の危険性
4.2 ツールが必要となる背景
- LLMの制約とコンテキストウィンドウ
- Function Callingとの関連
4.3 ツールの基本構造
- 定義(JSON Schema)──LLMへの説明書
- 処理(TypeScript関数)──実際の処理
- サンドボックス──安全なワークスペースの設計
- ツールの枠組みの完成形──定義・処理・サンドボックスの統合
- ツール定義の型を柔軟に設計する
4.4 ハンズオン(4):ファイルの読み書きツール(readFile、writeFile、editFile)の実装
- ファイル読み込みツール(readFile)の実装
- ステップで基本を実装
- 各ステップの詳細
- ツール定義の作成──LLMが理解できる形式
- descriptionの役割──ツール選択の基準
- 実装のテスト
- ファイル書き込みツール(writeFile)の実装
- writeFileで考慮すべき点
- writeFileの実装
- ファイル編集ツール(editFile)の実装
- ファイル書き込みツール(writeFile)とファイル編集ツール(editFile)の使い分け
4.5 ハンズオン(5):コマンド実行ツール(execCommand)の実装
- 脆弱性の理解
- コマンドインジェクション
- ディレクトリトラバーサル
- 環境変数の悪用
- 防御策の設計
- コマンド実行ツール(execCommand)の実装
- execCommandの設計
- parseCommand──コマンド文字列の解析
- execCommand──安全なコマンド実行
- ツール定義
- 多層防御による安全性確保
- spawn vs exec──spawnの安全性
- 実装の限界と注意点
- execCommandの完全なソースコード
4.6 ツールの統合
- ツール配列の構築
- ツールの動作確認
- LLM APIレイヤーとの接続
4.7 補足:さらなる安全性強化へ──アプリケーションとOSによる二層の防御
4.8 この章のまとめと次のステップ
第5章 Nano Codeの「頭脳」となる思考ループと承認ポリシーを実装する
5.0 これまでの振り返りと、この章で作るもの
5.1 なぜ思考ループが必要なのか
- ワークフロー vs エージェント
5.2 最小のエージェント──1往復の会話
5.3 繰り返しを追加する──会話のループ
- 思考ループの基本──1サイクルの動作
5.4 ハンズオン(6):ツール実行を統合する
- ツール対応の思考ループ
- 複数ステップの自律実行
5.5 承認ポリシー──ツール実行前の確認機構
- 承認を求めるフラグの追加と設定
- 承認プロンプトの実装
- 思考ループへの統合
- 承認ポリシーの動作例
- 承認拒否時のメッセージ設計
- CI/CD環境での対応──承認関数の差し替え
5.6 エラーハンドリング──executeToolの内部拡張
5.7 その他の安全性の考慮
- 無限ループの防止──ステップ数の制限
- モデル品質による無限ループの原因
- その他の無限ループの原因
- 最大ステップ数による基本的な防御
- 承認ポリシーとの組み合わせ
- ツールの実行制限
- コスト管理
5.8 Agentクラス(再利用可能な設計)
- この節で行うこと
- 各節の成果がどこに入るか
- Agentクラスの設計
- generate()メソッドの実装
- ステップ1:会話ループの開始(5.3節)
- ステップ2:ツール実行(5.4節、5.6節)
- ステップ3:承認チェック(5.5節)
- ステップ4:制限チェック(5.7節)
- Agentクラスの完全なソースコード
- toolsパラメータ──エージェントにツールを渡す
- toolsパラメータの形式
- ループの終了条件
- ツール未使用で終了するケースへの対処
- 対処法1:プロンプトで明示的にツール使用を促す
- 対処法2:ツール未使用を検出して再試行する
- 対処法3:verboseモードでデバッグする
- 実践的な推奨事項
5.9 デバッグとテスト
- 個別機能のテスト
5.10 この章のまとめと次のステップ
第3部 AIエージェントを完成させ、実用化する
第6章 Nano Codeを組み立てる
6.0 これまでの振り返りと、この章で作るもの
6.1 Nano Codeに明確な指示を与える
- TODOリスト方式の導入
- instructions(システムプロンプト)の設計
6.2 ハンズオン(7):CLIで動くNano Codeの実装
- プロジェクト構成
- どのLLMでも動作するエージェントへ
- modelFactoryの実装
- 起動時の初期化フロー
- ベースプロンプト(core/prompt.md)
- プロジェクト固有の指示(AGENTS.md)
- 起動時の読み込み処理
- CLIインタフェースを作る
- maxStepsのチューニング
- 実行方法
6.3 実行例と出力
- サンプルファイルの作成
- テストの追加
- 期待される出力
6.4 思考過程の可視化
6.5 ハンズオン(8):コンテキスト管理の実装
- 優先度付き履歴圧縮の設計
- manageContextメソッドの実装
- generateメソッドへの組み込み
- この設計のメリット
6.6 この章のまとめと次のステップ
第7章 GitHub Actionsで開発ワークフローを自動化する
7.0 これまでの振り返りと、この章で作るもの
- ブラウザGUIではなくCLI+APIによる構成パターン
- Dev Container環境でのGitHub CLIインストール
7.1 ハンズオン(9):最小構成で動かす
- 5行のワークフローから始める
- ワークフローを実行する
- 最小構成で確認できたこと
7.2 Secretsと権限
- 操作ごとの権限設定
- SecretsとVariablesの登録
- モデルの選択基準
- 自動承認モード(--yolo)の実装
7.3 Git操作ツール
- createBranch → commit → push の流れ
- Issue番号ベースの固定ブランチ名
7.4 GitHub CLIによるプルリクエスト作成
- ghコマンドを選ぶ理由
- 最小のプルリクエスト作成例
7.5 cli.tsへのツール組み込み
7.6 手動トリガーでの動作確認
- CLIで環境変数を読む
- Nano Code Action向けシステムプロンプト
- Nano Code Action向けの権限緩和
- ワークフローにinputsを追加する
- 手動実行でテストする
7.7 Issueイベントへの接続
- 自動トリガーの追加
- 入力ソースのハイブリッド化
- 権限と環境変数の追加
- 完成版のワークフローファイル
- Issueを作成して動作確認
7.8 状況を認識して行動を変える──再実行への対応
- Issue番号ベースの固定ブランチ名
- 空コミットの防止
- プルリクエストの更新と新規作成
- 固定ブランチ名とプルリクエスト更新の整合性
7.9 完全なソースコード
- Gitツール
- GitHubツール
7.10 この章のまとめと次のステップ
第4部 より賢く、安全なAIエージェントへ
第8章 Nano Codeの性能と安全性を高めるサンドボックス
8.0 これまでの振り返りと、この章で作るもの
8.1 なぜ多層防御が必要なのか
- 多層防御(Defense in Depth)の考え方
- Layer 1:基盤インフラ(Docker/GitHub Actions)
- Layer 2:プロセス隔離(bubblewrap)
- Layer 3:アプリケーション制御(TypeScript)
- なぜDockerの中でさらにbubblewrapが必要なのか
- ツールと防御層の対応
- 境界が性能を向上させる理由
8.2 ハンズオン(10):アプリケーション制御を実装する
- 設定の定義
- webFetchツールの実装
8.3 ハンズオン(11):プロセス隔離を実装する
- bubblewrapとは
- 準備1:Dockerfileにbubblewrapを追加
- 準備2:この章専用のコンテナを起動
- Sandboxクラスの実装
- 実装のポイント
- コマンド実行ツール(execCommand)の拡張
- ネットワーク制御の設計
- 補足:制御付きネットワークの実現方式
- 補足:macOS(Seatbelt)
8.4 攻撃が無力化されることを確認する
- シナリオ1:ファイルシステムへの攻撃
- シナリオ2:ネットワークへの攻撃
- シナリオ3:破壊的コマンド
8.5 この章のまとめと次のステップ
第9章 AIエージェント開発のこれから
9.1 本書の振り返りと到達点
- 3つのスキル
- 原理理解の価値
9.2 Nano Codeの拡張可能性
- メモリ機能の追加
- コードベース理解の強化
- より高度なツールの実装
9.3 開発の前提が書き換わる
9.4 エンジニアの役割の変化
- 作業量の拡張と判断の負荷
- コンテキスト設計の役割
- 権限と環境設計という責任
- 学習プロセスの変化
- 定型作業からの解放
9.5 チームとプロセスの再設計
- AIのチームメンバー化
- 開発プロセス自体の見直し
- モデル選択が開発スタイルに与える影響
- コストという新しい指標
9.6 トレードオフとエンジニアの責任
- 自律性と制御のトレードオフ
- 安全性は環境設計で決まる
- 無人化の境界線を引く
9.7 技術変化への対応
- 原理理解の有効性
- 注目される技術の方向性
- 実験と検証の必要性
9.8 実装から運用へ
Appendix A ストリーミングAPIへの対応
A.1 なぜストリーミングが必要か──設計視点から
A.2 抽象化の設計原則
- SDKと抽象化レイヤーの役割分担
A.3 StreamChunk型──中間言語としての設計
- イベントの状態は3つに集約
- なぜこの3状態で統一できるか
- finishReasonの正規化
A.4 LanguageModelインタフェースの拡張
A.5 OpenAIプロバイダーのストリーミング実装
A.6 Anthropicプロバイダーのストリーミング実装
A.7 Googleプロバイダーのストリーミング実装
A.8 統一関数──generateStreamText
A.9 ストリーミングと非ストリーミングの統一──collectStreamResult
A.10 Nano Codeへの組み込み
- Agentクラスでの統合
A.11 設計のまとめ
Appendix B Responses APIへの対応
B.1 Responses APIの設計
- なぜResponses APIが登場したか
- Chat Completions APIとResponses APIの違い
- レスポンス構造の変化
- 関数定義の変化
B.2 抽象化レイヤーによる変更の局所化
- アダプターパターンの適用
B.3 createOpenAIResponsesの実装
- 入力のアダプター
- 関数定義のアダプター
- statusとfinishReasonの対応
- 出力のアダプター
- プロバイダー関数の実装
- ストリーミング実装
B.4 Reasoningの扱い
- nano-code-coreでの扱い
B.5 Responses APIへの移行
- 抽象化の価値
Appendix C 参考にしたプロジェクト
C.1 コーディングエージェントCLI
- Claude Code
- Claude Code Action
- Codex CLI
- Gemini CLI
- Groq Code CLI
C.2 エージェントフレームワーク・ライブラリ
- Vercel AI SDK
- Mastra
- LangChain
C.3 セキュリティ・サンドボックス
- sandbox-runtime
プロフィール
laiso
2008年、国内におけるiPhoneアプリ開発の黎明期にエンジニアとしてのキャリアをスタート。以来、複数の事業会社にてモバイルアプリからWebフロントエンド、サーバーサイドまで、プラットフォームを横断したプロダクトの設計・開発に従事する。
長年にわたるブログでの発信活動を通じ、常に最新の技術トレンドを追いながら、開発プロセスの最適化に関する知見を継続的に公開。現在はLLMを活用したAIエージェント技術に注力し、AIと人間が協働する次世代の開発スタイルの探求と実践に力を注いでいる。
X:@laiso
GitHub:https://github.com/laiso
Blog:https://blog.lai.so/