はじめに
AIコーディングエージェント、使ってますか?
Claude Code、Codex、Cursor、Gemini...様々なAIエージェントツールが登場してるけど、こんな悩みを抱えてませんか。
筆者も最初、複数のAIエージェントを手動で切り替えるのが面倒すぎて、なんとかならないかと思ってました。
- 複数のAIエージェントを切り替えて使いたいが、それぞれUIが違って面倒
- 実行ログを一元管理したい
- AIエージェントの実行を自分のアプリケーションに組み込みたいけど、どうすればいいかわからない
- CI/CDパイプラインにAIエージェント組み込みたい
そんな悩みを解決するのが、今回紹介する Coding Agent Viewer SDK です。
この記事では実際のコードを見ながら、SDKを使うといかに簡単にAIエージェントを操作できるかをステップバイステップで解説します。初心者の方でも実装できるよう丁寧に説明していくので、ぜひ最後まで読んでください。
Coding Agent Viewer SDKとは
Coding Agent Viewerは、複数のAIコーディングエージェントを統合管理するためのSDKとツールセットです。
主な特徴
マルチエージェント対応で、Claude Code、Codex、OpenCode、Cursor、Geminiなど複数のAIエージェントを統一APIで操作できます。
3つのコアモジュールがあります:
- Execution Module: AIエージェントの実行管理
- Log Module: セッションログの収集・正規化
- API Module: REST API + SSE(Server-Sent Events)
用途に応じて4つの利用レベルで使い分けられます:
レベル | 説明 | 用途 |
---|---|---|
Level 1: Library | SDKを直接インポート | CLIツール、バッチ処理、組み込み |
Level 2: API | RESTful API + SSE | カスタムフロント、マイクロサービス |
Level 3: Full-stack | 完成されたWebアプリ | そのまま利用、カスタマイズ |
Level 4: Custom Web Chat | WebチャットUIサンプル | 既存SaaSへの組み込み・PoC |
ちなみに、筆者が個人的に好んで使っているのはLevel 1の方式です。SDKを直接使う方が最も柔軟で強力だと感じてる。
なぜこのSDKが必要なのか
通常、AIエージェントを自分のアプリケーションに組み込もうとすると、以下のような課題があります。
- 各エージェントの起動方法がバラバラ - コマンドライン引数や環境変数の設定が異なる
- ログ形式の違い - それぞれ独自のログ形式を持っており、統一的な処理が困難
- プロセス管理の複雑さ - 子プロセスの起動・監視・停止を適切に行う必要
- リアルタイム性 - ログをリアルタイムで取得・表示したい
Coding Agent Viewer SDKは、これらの課題をすべて解決してくれます。
余談だが、このSDKの開発中、LogSourceFactoryの命名については散々悩んだ。FactoryパターンかStrategyパターンか...実装的にはStrategy Patternに近いんだが、まあ、どっちでもいいと思う。本題に戻ると、SDKの使い方は驚くほど簡単です。
実際に使ってみよう - Level 1(ライブラリとして直接利用)
実際のコードを見ながら、SDKの使い方を学んでいきましょう。
インストール
まずはnpmでSDKをインストールします。
npm install @nogataka/coding-agent-viewer-sdk
たったこれだけで準備完了です。依存関係も自動的に解決されます。
基本的な使い方
1. プロジェクト一覧を取得する
まずは、AIエージェントで管理されているプロジェクトの一覧を取得してみます。
import { LogSourceFactory } from '@nogataka/coding-agent-viewer-sdk/services/logs';
// LogSourceFactoryのインスタンスを作成
const factory = new LogSourceFactory();
// Claude Codeのプロジェクト一覧を取得
// 最初これ書いたときエラーハンドリング忘れてた
const projects = await factory.getAllProjects('CLAUDE_CODE');
// プロジェクト情報を表示
projects.forEach(project => {
console.log(`プロジェクト名: ${project.name}`);
console.log(`ID: ${project.id}`);
console.log(`作成日: ${project.created_at}`);
console.log(`更新日: ${project.updated_at}`);
console.log('---');
});
LogSourceFactory
は、各AIエージェントのログを統一的に扱うためのファクトリークラスです。getAllProjects()
メソッドに、取得したいエージェントのタイプ(CLAUDE_CODE
、CURSOR
、GEMINI
など)を指定するだけで、そのエージェントで管理されているプロジェクトの一覧が取得できます。
実装の詳細はlogSourceStrategy.tsを見てもらえればわかりますが、各エージェントごとにStrategy Patternで実装を切り替えてる。
引数を省略すれば、全エージェントのプロジェクトを一度に取得することも可能です。
// 全エージェントのプロジェクトを取得
const allProjects = await factory.getAllProjects();
2. セッション一覧を取得する
次に、特定のプロジェクトのセッション(実行履歴)を取得してみましょう。
// プロジェクトIDを指定してセッション一覧を取得
const sessions = await factory.getSessionsForProject(project.id);
// セッション情報を表示
sessions.forEach(session => {
console.log(`タイトル: ${session.title}`);
console.log(`ステータス: ${session.status}`); // running, completed, failed
console.log(`作成日時: ${session.createdAt}`);
console.log(`更新日時: ${session.updatedAt}`);
console.log('---');
});
getSessionsForProject()
メソッドで、指定したプロジェクトの全セッションを取得できます。各セッションには、タイトル、ステータス(実行中、完了、失敗)、日時などの情報が含まれています。
過去にどんな作業をAIエージェントに依頼したかを一覧で確認できるので便利です。
3. AIエージェントを実行する
いよいよ、AIエージェントを実際に実行してみます。これが驚くほど簡単です。
import { ExecutionService } from '@nogataka/coding-agent-viewer-sdk/services/execution';
// ExecutionServiceのインスタンスを作成
const executor = new ExecutionService();
// 新しいチャットセッションを開始
const result = await executor.startNewChat({
profileLabel: 'claude-code', // 使用するエージェント
workspacePath: '/path/to/your/project', // 作業ディレクトリ
prompt: 'READMEファイルを作成してください' // AIへの指示
});
console.log('セッションID:', result.sessionId);
console.log('プロセスID:', result.processId);
console.log('開始時刻:', result.startedAt);
ExecutionService
は、AIエージェントの実行を管理するクラスです。startNewChat()
メソッドで新しいチャットセッションを開始します。
必要なパラメータは以下の3つだけです:
-
profileLabel
- 使用するAIエージェント(claude-code
、cursor
、gemini
など) -
workspacePath
- AIエージェントが作業するディレクトリのパス -
prompt
- AIエージェントへの指示内容
実行結果には、セッションID、プロセスID、開始時刻が含まれます。
4. ログをリアルタイムで取得する
実行中のAIエージェントのログをリアルタイムで取得してみましょう。
// セッションIDからログストリームを取得
const stream = await factory.getSessionStream(result.sessionId);
// ストリームからデータを読み取る
stream.on('data', (chunk) => {
const text = chunk.toString();
console.log('ログ:', text);
});
stream.on('end', () => {
console.log('ログストリーム終了');
});
stream.on('error', (error) => {
console.error('エラー:', error.message);
});
getSessionStream()
メソッドで、指定したセッションのログストリームを取得できます。Node.jsの標準的なReadable
ストリームとして返されるため、on('data')
でデータを受信できます。
リアルタイムでログが流れてくるので、AIエージェントが今何をしているかを即座に確認可能です。
完全な実装例 - インタラクティブCLI
ここまでの知識を組み合わせて、実際に動くインタラクティブCLIを作ってみます。
以下は、SDKのサンプルディレクトリに含まれているsimple-cli.js
の簡略版です。
import { LogSourceFactory } from '@nogataka/coding-agent-viewer-sdk/services/logs';
import { ExecutionService, getProfiles } from '@nogataka/coding-agent-viewer-sdk/services/execution';
import inquirer from 'inquirer';
import chalk from 'chalk';
import ora from 'ora';
class AgentCLI {
constructor() {
// ファクトリーとサービスのインスタンスを作成
this.factory = new LogSourceFactory();
this.executor = new ExecutionService();
// 利用可能なプロファイル(エージェント)を取得
this.profileCatalog = getProfiles().map((definition) => ({
label: definition.label,
displayName: definition.label.split('-').map(s =>
s.charAt(0).toUpperCase() + s.slice(1)
).join(' '),
variants: definition.variants?.map(v => v.label) ?? []
}));
}
async start() {
console.clear();
console.log(chalk.blue.bold('\n🤖 Coding Agent Viewer CLI\n'));
// メインメニューを表示
const { action } = await inquirer.prompt([
{
type: 'list',
name: 'action',
message: '何を行いますか?',
choices: [
{ name: '📂 プロジェクトをブラウズ', value: 'browse' },
{ name: '🚀 新しいセッションを開始', value: 'execute' },
{ name: '❌ 終了', value: 'exit' }
]
}
]);
switch (action) {
case 'browse':
await this.browseProjects();
break;
case 'execute':
await this.quickExecute();
break;
case 'exit':
console.log(chalk.blue('\n👋 さようなら!\n'));
process.exit(0);
}
}
async browseProjects() {
// エージェントを選択
const profileChoices = this.profileCatalog.map(profile => ({
name: `${profile.displayName}`,
value: profile
}));
const { selectedProfile } = await inquirer.prompt([
{
type: 'list',
name: 'selectedProfile',
message: 'エージェントを選択',
choices: profileChoices
}
]);
// プロジェクト一覧を取得
const spinner = ora(`${selectedProfile.displayName}のプロジェクトを読み込み中...`).start();
const projects = await this.factory.getAllProjects(
selectedProfile.label.toUpperCase().replace(/-/g, '_')
);
spinner.stop();
if (projects.length === 0) {
console.log(chalk.yellow(`\n⚠️ プロジェクトが見つからなかった`));
return this.start();
}
console.log(chalk.green(`\n${projects.length}件のプロジェクトが見つかった\n`));
projects.forEach((p, i) => {
console.log(`${i + 1}. ${chalk.bold(p.name)}`);
console.log(` 更新日: ${new Date(p.updated_at).toLocaleString()}`);
});
console.log();
await this.start();
}
async quickExecute() {
// エージェントを選択
const { profile } = await inquirer.prompt([
{
type: 'list',
name: 'profile',
message: 'エージェントを選択',
choices: this.profileCatalog.map(p => ({
name: p.displayName,
value: p
}))
}
]);
// ワークスペースパスを入力
const { workspace } = await inquirer.prompt([
{
type: 'input',
name: 'workspace',
message: 'ワークスペースパス',
default: process.cwd()
}
]);
// プロンプトを入力
const { prompt } = await inquirer.prompt([
{
type: 'input',
name: 'prompt',
message: 'AIへの指示を入力',
validate: (input) => input.trim().length > 0 || 'プロンプトを入力してください'
}
]);
// 実行
const spinner = ora('実行中...').start();
try {
const result = await this.executor.startNewChat({
profileLabel: profile.label,
executorType: profile.label.toUpperCase().replace(/-/g, '_'),
projectId: `${profile.label.toUpperCase().replace(/-/g, '_')}:${Buffer.from(workspace).toString('base64url')}`,
actualProjectId: Buffer.from(workspace).toString('base64url'),
workspacePath: workspace,
prompt
});
spinner.succeed('実行開始!');
console.log(chalk.green(`\n セッションID: ${result.sessionId}`));
console.log(chalk.gray(` プロセスID: ${result.processId}`));
console.log();
await this.start();
} catch (error) {
spinner.fail('実行失敗');
console.error(chalk.red(` ${error.message}`));
await this.start();
}
}
}
// CLIを起動
const cli = new AgentCLI();
cli.start().catch(error => {
console.error(chalk.red(`\n❌ エラー: ${error.message}\n`));
process.exit(1);
});
このCLIでできること:
- プロジェクトのブラウズ - 各AIエージェントで管理されているプロジェクトを一覧表示
- 新規セッションの開始 - 対話形式で簡単にAIエージェントを実行
- エラーハンドリング - エラーが発生しても適切にユーザーに通知
実装のポイントは以下です:
-
inquirer
を使用することで、ユーザーフレンドリーな対話型UIを実現 -
ora
でスピナーを表示し、処理中であることを視覚的にフィードバック -
chalk
で色付きテキストを使用し、見やすいUIを提供
筆者はこのCLIツールを毎日使っていて、複数プロジェクトでのAIエージェント管理が劇的に楽になった。特にinquirer
によるインタラクティブな選択UIが気に入ってる。
さらに高度な使い方
フォローアップメッセージの送信
すでに実行中のセッションに、追加の指示を送ることもできます。
// フォローアップメッセージを送信
const followUpResult = await executor.sendFollowUp({
profileLabel: 'claude-code',
sessionId: 'CLAUDE_CODE:...:uuid', // 既存のセッションID
workspacePath: '/path/to/your/project',
message: 'テストも追加してください'
});
console.log('フォローアップ送信完了:', followUpResult.sessionId);
sendFollowUp()
メソッドで、既存のセッションに追加の指示を送れます。セッションIDを指定することで、同じコンテキストで会話を続けられます。
ただし、CursorとGeminiのサポートはまだ開発途中で、フォローアップメッセージの挙動が不安定な部分がある。本番環境での使用は様子を見たほうが良いです。
実行中のプロセスを停止する
実行中のAIエージェントを停止することも簡単です。
// セッションを停止
const stopped = executor.stopExecution(sessionId);
if (stopped) {
console.log('セッションを停止した');
} else {
console.log('セッションが見つからないか、すでに停止している');
}
stopExecution()
メソッドで、実行中のセッションを停止できます。返り値はboolean
で、停止に成功したかどうかがわかります。
バリアント(実行モード)の指定
一部のエージェント(例:Claude Code)では、実行モードを指定できます。
// プランモードで実行
const result = await executor.startNewChat({
profileLabel: 'claude-code',
variantLabel: 'plan', // planモードを指定
workspacePath: '/path/to/your/project',
prompt: 'アーキテクチャを計画してください'
});
variantLabel
パラメータで、実行モードを指定できます。Claude Codeの場合、plan
モードでは実装前の計画フェーズに特化した動作をします。Level 4のカスタムWebチャットでこの機能を試してみたいと思ってるけど、まだ試してない。
Level 2 - APIサーバーとして使う
SDKは、REST APIサーバーとしても利用できます。これにより、フロントエンドアプリケーションや他のサービスから簡単にAIエージェントを操作できます。
サーバーのセットアップ
import express from 'express';
import { setupRoutes } from '@nogataka/coding-agent-viewer-sdk/server/routes';
const app = express();
app.use(express.json());
// ルートをセットアップ
setupRoutes(app);
// サーバー起動
const PORT = 3001;
app.listen(PORT, () => {
console.log(`サーバーが起動しました: http://localhost:${PORT}`);
});
setupRoutes()
関数を呼ぶだけで、必要なAPIエンドポイントが全て設定されます。Express以外のフレームワークでも使用可能です。
提供されるAPIエンドポイント
セットアップするだけで、以下のAPIエンドポイントが利用可能になります。
エンドポイント | メソッド | 説明 |
---|---|---|
/api/projects |
GET | プロジェクト一覧を取得 |
/api/tasks?project_id=<id> |
GET | セッション一覧を取得 |
/api/task-attempts |
POST | AIエージェントを実行 |
/api/execution-processes/:id/normalized-logs |
GET | ログをSSEでストリーミング |
詳細なAPIスキーマはroutes.tsの実装を見てもらえれば、全体像がつかめると思う。
フロントエンドからの利用例
// プロジェクト一覧を取得
const response = await fetch('http://localhost:3001/api/projects');
const projects = await response.json();
// AIエージェントを実行
const executeResponse = await fetch('http://localhost:3001/api/task-attempts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
projectId: 'CLAUDE_CODE:...',
prompt: 'READMEを作成してください',
profileLabel: 'claude-code'
})
});
const result = await executeResponse.json();
// SSEでログをリアルタイム取得
const eventSource = new EventSource(
`http://localhost:3001/api/execution-processes/${result.sessionId}/normalized-logs`
);
eventSource.addEventListener('json_patch', (event) => {
const patches = JSON.parse(event.data);
console.log('ログ更新:', patches);
});
REST APIなので、React、Vue、Angularなど、どのフロントエンドフレームワークからも利用可能です。Server-Sent Events(SSE)により、ログのリアルタイム更新ができます。モバイルアプリ(React Native、Flutter)からも利用できます。
Level 3 & 4 - すぐに使えるアプリケーション
SDKには、すぐに使える完成されたアプリケーションも付属しています。
Level 3: フルスタックアプリ
# npx経由で即起動
npx @nogataka/coding-agent-viewer
# または、リポジトリをクローンして起動
git clone https://github.com/nogataka/coding-agent-viewer
cd coding-agent-viewer
npm run install:all
npm run dev
ブラウザでhttp://localhost:3000
を開くと、以下の機能を持つWebアプリが利用できます。
- 美しいReact製のUI
- プロジェクト・セッション管理
- リアルタイムログビューア
- 複数エージェントのサポート
Level 4: カスタムWebチャット
既存のWebアプリケーションにAIエージェント機能を組み込みたい場合は、Level 4のサンプルが参考になります。
cd samples/level4-custom
pnpm install
pnpm dev
このサンプルは、REST APIとSSEを直接呼び出す最小構成のWebチャットUIです。自社のSaaSやPoCに組み込む際の参考実装として活用できます。
大規模プロジェクトでのパフォーマンスは、まだ詳しく計測できてないけど、そのうち試してみたい。
実践的なユースケース
1. CI/CDパイプラインでの自動コードレビュー
// GitHub Actionsなどから実行
import { ExecutionService } from '@nogataka/coding-agent-viewer-sdk/services/execution';
const executor = new ExecutionService();
// Pull Requestのコードレビューを自動実行
const result = await executor.startNewChat({
profileLabel: 'claude-code',
workspacePath: process.env.GITHUB_WORKSPACE,
prompt: 'このPull Requestのコードをレビューして、改善点を指摘してください'
});
console.log(`レビューセッション開始: ${result.sessionId}`);
2. Slackボットとの連携
import { App } from '@slack/bolt';
import { ExecutionService } from '@nogataka/coding-agent-viewer-sdk/services/execution';
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
const executor = new ExecutionService();
app.command('/ai-agent', async ({ command, ack, respond }) => {
await ack();
const result = await executor.startNewChat({
profileLabel: 'claude-code',
workspacePath: '/path/to/project',
prompt: command.text
});
await respond(`AIエージェントを実行しました: ${result.sessionId}`);
});
app.start(3000);
3. VS Code拡張機能
import * as vscode from 'vscode';
import { ExecutionService } from '@nogataka/coding-agent-viewer-sdk/services/execution';
export function activate(context: vscode.ExtensionContext) {
const executor = new ExecutionService();
let disposable = vscode.commands.registerCommand('extension.runAIAgent', async () => {
const prompt = await vscode.window.showInputBox({
placeHolder: 'AIエージェントへの指示を入力'
});
if (prompt) {
const workspacePath = vscode.workspace.workspaceFolders?.[0].uri.fsPath;
const result = await executor.startNewChat({
profileLabel: 'claude-code',
workspacePath: workspacePath!,
prompt
});
vscode.window.showInformationMessage(`実行開始: ${result.sessionId}`);
}
});
context.subscriptions.push(disposable);
}
パフォーマンスとベストプラクティス
メモリ管理
// ログストリームは使用後に必ずクリーンアップ
const stream = await factory.getSessionStream(sessionId);
stream.on('data', handleData);
stream.on('end', () => {
stream.destroy(); // リソースを解放
});
// エラー時も忘れずにクリーンアップ
stream.on('error', (error) => {
console.error(error);
stream.destroy();
});
ストリームのクリーンアップを忘れると、メモリリークの原因になります。筆者も最初これ忘れてて、長時間実行するとメモリが増え続ける問題に遭遇しました。
プロジェクトキャッシュの活用
class ProjectCache {
constructor() {
this.cache = new Map();
this.factory = new LogSourceFactory();
}
async getProjects(executorType, forceRefresh = false) {
if (!forceRefresh && this.cache.has(executorType)) {
return this.cache.get(executorType);
}
const projects = await this.factory.getAllProjects(executorType);
this.cache.set(executorType, projects);
return projects;
}
clear() {
this.cache.clear();
}
}
エラーハンドリング
async function safeExecute(executor, request) {
try {
const result = await executor.startNewChat(request);
return { success: true, data: result };
} catch (error) {
if (error.message.includes('Workspace path does not exist')) {
return { success: false, error: 'ワークスペースパスが存在しない' };
} else if (error.message.includes('Profile config not found')) {
return { success: false, error: 'プロファイルが見つからない' };
} else {
return { success: false, error: '予期しないエラーが発生した' };
}
}
}
まとめ
Coding Agent Viewer SDKを使えば、複雑なAIエージェントの管理が驚くほど簡単になります。
この記事で学んだこと:
- たった3行でAIエージェントを実行できる
- プロジェクトやセッションの一覧を簡単に取得できる
- ログをリアルタイムでストリーミング取得できる
- REST APIサーバーとしても利用できる
- 完成されたWebアプリもすぐに使える
SDKの魅力は以下です:
- 導入が簡単 - npm installだけで使える
- 統一API - 複数のAIエージェントを同じ方法で操作
- 柔軟な利用方法 - ライブラリ、API、完成アプリの3段階
- 実用的なサンプル - すぐに動くコード例が豊富
次のステップ:
- GitHubリポジトリをチェック
- サンプルコードを試してみる
- 自分のプロジェクトに組み込んでみる
AIエージェントを使った開発体験を、ぜひこのSDKで向上させてほしい。筆者自身も日々このSDKを使ってて、開発効率が10倍どころじゃなく上がった気がします(10倍は言い過ぎかもしれないですが・・・)。
参考リンク
- GitHub Repository
- npm: @nogataka/coding-agent-viewer-sdk
- npm: @nogataka/coding-agent-viewer
- ドキュメント
- サンプルコード (Level 1-4)
この記事が役に立てば幸いです。