• Projects
  • Service
  • About
  • branding.bz
  • Podcast
  • Tips
  • FAQ
  • Recruit
  • Download
  • Contact
  • branding.bz(ブランド構築SaaS)
  • DESIGN NOW(デザインメディア)
  • X
  • LinkedIn
  • Spotify
  • Facebook

213-0011 神奈川県川崎市高津区久本3-6-7-303

© 2026 ID INC. All rights reserved

claude-skills/スキル
SKILLOfficialdevelopment

output-dev-agent-class

プラグイン
outputai
ソース
GitHub で見る ↗
説明

Agent クラスを使用する場合: 複数ステップのツール処理ループ、会話履歴、処理進捗の配信(リアルタイム表示)、再利用可能なLLMエージェント(言語モデルを活用した自動実行プログラム)を必要とするとき。スキルを持つエージェントの構築、出力形式の指定、状態を保つ会話機能、またはコールバック(処理完了時に実行される関数)を通じた進捗通知が必要な場合に適しています。

原文を表示

Use the Agent class for multi-step tool loops, conversation history, streaming progress, and reusable LLM agents. Use when building agents with skills, structured output, stateful conversations, or streaming callbacks.

ユースケース
  • 複数ステップのツール処理ループが必要なとき
  • 会話履歴を保持する必要があるとき
  • 処理進捗をリアルタイム表示したいとき
  • 再利用可能なLLMエージェントを構築するとき
  • コールバックで進捗通知を行いたいとき
本文(日本語訳)

Agent クラスの使用方法

概要

Agent クラスは、出力プロンプトファイルとスキルシステムを通じて、内部の AI SDK である ToolLoopAgent を組み合わせて使用します。ToolLoopAgent から継承するのではなく、組み合わせる方式です。複数ステップのツール実行、会話履歴、または再利用可能なエージェントインスタンスが必要な場合に使用してください。ツールを使わない単発の LLM 呼び出しであれば、generateText の方がシンプルです。

使用する場面

  • ループ内でツールを呼び出す複数ステップのエージェントを構築する
  • スキル(遅延読み込み方式の指示文)をエージェントで使用する
  • aiSdk.Output.object() を通じて構造化出力を持つエージェントを作成する
  • messageStore で状態を保つ会話を実装する
  • onChunk でエージェントの進行状況をストリーミング表示する
  • Agent と generateText の使い分けを判断する

インポートパターン

import { Agent, aiSdk } from '@outputai/llm';
import type { MessageStore } from '@outputai/llm';
import { z } from '@outputai/core';

Agent は @outputai/llm から取得します。構造化出力には aiSdk.Output を使用してください。z は @outputai/core からインポートしてください(zod から直接インポートしないでください)。MessageStore はプラグイン式の getMessages / addMessages ストアの型であり、自分で実装する必要があります。

構築方法

プロンプトファイルは構築時に読み込まれレンダリングされます。変数とツールは構築時に固定されます。スキルと maxSteps はプロンプトファイルから取得されます。エージェントは generate()、generateWithStreaming()、または stream() をすぐに呼び出せる状態になります。

const agent = new Agent( {
  prompt: 'writing_assistant@v1',
  variables: {
    content_type: input.contentType,
    focus: input.focus,
    content: input.content
  },
  output: aiSdk.Output.object( { schema: reviewSchema } )
} );

コンストラクタオプション

オプション 型 デフォルト 説明
prompt string (必須) プロンプトファイル名(例:'writing_assistant@v1')
promptDir string - スタック解決されたプロンプトディレクトリをオーバーライド
variables PromptVariables - 構築時にレンダリングされるテンプレート変数
tools AI SDK ツール - 呼び出し側のツール。プロンプト YAML のツールとマージされる(load_skill が最後)
stopWhen 関数または関数配列 - カスタム停止条件(ツール存在時はプロンプト maxSteps をオーバーライド)
output aiSdk.Output - 構造化出力仕様(例:aiSdk.Output.object({ schema }))
messageStore MessageStore - 複数ターンの履歴用プラグイン式ストア

generate()

エージェントを実行して完了時に戻ります:

const result = await agent.generate();
console.log( result.text );   // 生成されたテキスト
console.log( result.output ); // 構造化出力(aiSdk.Output.object 使用時)
console.log( result.usage );  // トークン数

結果は generateText と同じ形状です:text、result(text の別名)、output、usage、finishReason、toolCalls など。

追加メッセージの渡し方

会話を追加メッセージで拡張します:

const result = await agent.generate( {
  messages: [ { role: 'user', content: '導入部に焦点を当ててください。' } ]
} );

メッセージは初期プロンプトメッセージ(およびメッセージストア履歴)の後に追加されます。abortSignal と toolChoice も渡すことができます。

generateWithStreaming()

進行状況のコールバックと完全な結果が必要な場合は、generateWithStreaming() を使用します:

const result = await agent.generateWithStreaming( {
  onChunk( { chunk } ) {
    if ( chunk.type === 'text-delta' ) {
      process.stdout.write( chunk.text );
    }
  }
} );

このメソッドは内部的にストリーミングを使用しながら generate() のように動作します。完全な応答を返し、ストリームエラー時は拒否され、自動的に設定されたメッセージストアにメッセージを追加します。generate() と同じ messages、abortSignal、toolChoice に加えて onChunk を受け付けます。Temporal(ワークフロー実行エンジン)のアクティビティステップでは、ストリーム結果への直接アクセスが必要でない限り、stream() より優先してください。

stream()

textStream または stream に直接制御が必要な場合は、stream() を使用します。generate() と同じ messages、abortSignal、toolChoice に加えて onChunk、onEnd、onError を受け付けます:

const stream = await agent.stream();

for await ( const chunk of stream.textStream ) {
  process.stdout.write( chunk );
}

streamText と同様に、ストリーム結果は textStream と stream の反復可能オブジェクト、および完了時に解決するプロミスベースのプロパティ(text、usage、finishReason)を提供します。

stream() は finishReason が 'error' でない場合、ラップされた onEnd でメッセージストアにメッセージを追加します。ストリーミングとエラーハンドリングのガイダンスは output-dev-llm-streaming を参照してください。

構造化出力

aiSdk.Output.object() を使用して型付きの応答を取得します:

const reviewSchema = z.object( {
  issues: z.array( z.string() ).describe( '見つかった問題のリスト' ),
  suggestions: z.array( z.string() ).describe( '実行可能な改善案' ),
  score: z.number().describe( '品質スコア 0-100' ),
  summary: z.string().describe( '簡潔な全体評価' )
} );

const agent = new Agent( {
  prompt: 'writing_assistant@v1',
  variables: { content_type: 'documentation', focus: 'clarity', content: markdownContent },
  output: aiSdk.Output.object( { schema: reviewSchema } )
} );

const { output } = await agent.generate();
// output: { issues: string[], suggestions: string[], score: number, summary: string }

スキーマフィールドでは .min()/.max() ではなく .describe() を使用して、数値の制約を指定してください。Anthropic はツール定義で minimum/maximum といった JSON スキーマ制約をサポートしていません。

メッセージストア

デフォルトでは Agent はステートレス(状態を保たない)です。毎回の generate() 呼び出しは初期プロンプトメッセージのみで新規に始まります。呼び出し間で履歴を保つには messageStore を渡してください:

import { Agent } from '@outputai/llm';
import type { MessageStore } from '@outputai/llm';

const messages: Parameters<MessageStore['addMessages']>[0] = [];
const messageStore: MessageStore = {
  getMessages: () => messages,
  addMessages: incoming => {
    messages.push( ...incoming );
  }
};

const chatbot = new Agent( {
  prompt: 'chatbot@v1',
  messageStore
} );

const r1 = await chatbot.generate( {
  messages: [ { role: 'user', content: 'こんにちは、Output について教えてください。' } ]
} );
// r1.text: "Output は AI フレームワークで..."

const r2 = await chatbot.generate( {
  messages: [ { role: 'user', content: 'リトライはどのように処理されますか?' } ]
} );
// r2 は r1 の全履歴を確認します

MessageStore は以下の通りです:

interface MessageStore {
  getMessages(): ModelMessage[] | Promise<ModelMessage[]>;
  addMessages( messages: ModelMessage[] ): void | Promise<void>;
}

ModelMessage は aiSdk 名前空間を通じて、または ai からのインポートで利用可能な AI SDK 型です。組み込みストアはありません。単一プロセス用にメモリ内でインターフェースを実装するか、永続的な履歴をデータベースで実装してください。

ワークフロー ステップでの Agent 使用

ワークフロー ステップでは、呼び出しごとに新しい Agent を構築してください。変数はステップの入力から取得されます:

import { step, z } from '@outputai/core';
import { Agent, aiSdk } from '@outputai/llm';

const reviewSchema = z.object( {
  summary: z.string().describe( '簡潔な評価' ),
  issues: z.array( z.string() ).describe( '見つかった問題' ),
  suggestions: z.array( z.string() ).describe( '改善点' ),
  score: z.number().describe( '品質スコア 0-100' )
} );

export const reviewContent = step( {
  name: 'reviewContent',
  description: 'Agent を使用して技術コンテンツをレビューし、構造化出力を生成',
  inputSchema: z.object( {
    content: z.string().describe( 'レビュー対象のコンテンツ' ),
    content_type: z.string().describe( 'コンテンツタイプ' ),
    focus: z.string().describe( 'レビュー焦点エリア' )
  } ),
  outputSchema: reviewSchema,
  fn: async input => {
    const agent = new Agent( {
      prompt: 'writing_assistant@v1',
      variables: input,
      output: aiSdk.Output.object( { schema: reviewSchema } )
    } );
    const { output } = await agent.generate();
    return output;
  }
} );

これが標準パターンです。各ステップの呼び出しは独立しており、Agent の構築は低コストです。

スキルを使用した Agent

プロンプトのメタデータセクション(フロントマター)にスキルパスをリストします。スキルの完全なガイドは output-dev-skill-file を参照してください。

Agent と generateText の使い分け

generateText Agent
ベストな用途 単発の LLM 呼び出し 複数ステップのツールループ
ツール サポート サポート
スキル サポート サポート
会話履歴 手動管理 messageStore で組み込み
再利用可能インスタンス いいえ(関数呼び出し) はい(一度構築すれば何度も呼び出し)
構造化出力 aiSdk.Output.object() aiSdk.Output.object()

generateText から始めてください。会話状態または固定設定を持つ再利用可能インスタンスが必要になったら Agent に移行してください。

generateText の例(比較用)

import { generateText } from '@outputai/llm';

const { result } = await generateText( {
  prompt: 'generate_summary@v1',
  variables: {
    company_name: input.name,
    website_content: input.websiteContent
  }
} );

確認チェックリスト

  • [ ] Agent を @outputai/llm からインポート(ai から直接ではなく)
  • [ ] z を @outputai/core からインポート(zod から直接インポートしない)
  • [ ] プロンプトファイルが prompts/ フォルダに存在する
  • [ ] 変数がプロンプト内の {{ variable }} プレースホルダーと一致する
  • [ ] スキルまたはツールが 10 以外の上限を必要とする場合、プロンプトのメタデータセクションで maxSteps を設定
  • [ ] aiSdk.Output.object({ schema }) は数値に .min()/.max() ではなく .describe() を使用
  • [ ] messageStore は複数ターンの履歴が必要な場合のみ使用
  • [ ] ワークフロー ステップでは Agent をステップ fn 内で構築(モジュールレベルではなく)
  • [ ] コールバックで十分な場合は stream() より generateWithStreaming() を優先

関連スキル

  • output-dev-skill-file - エージェント用のスキルファイル作成
  • output-dev-llm-streaming - ストリーミング進行状況と Temporal 対応エラーハンドリング
  • output-dev-prompt-file - エージェントが使用する .prompt ファイル作成
  • output-dev-step-function - ステップ関数でのエージェント使用
  • output-dev-types-file - 構造化出力用の Zod スキーマ定義
  • output-dev-workflow-function - エージェント駆動型
原文(English)を表示

Using the Agent Class

Overview

The Agent class uses an internal AI SDK ToolLoopAgent through composition with Output prompt files and the skills system. It does not inherit from ToolLoopAgent. Use it when you need multi-step tool execution, conversation history, or a reusable agent instance. For single-shot LLM calls without tools, generateText is simpler.

When to Use This Skill

  • Building multi-step agents that call tools in a loop
  • Using skills (lazy-loaded instructions) with an agent
  • Creating agents with structured output via aiSdk.Output.object()
  • Implementing stateful conversations with messageStore
  • Streaming Agent progress with onChunk
  • Deciding between Agent and generateText

Import Pattern

import { Agent, aiSdk } from '@outputai/llm';
import type { MessageStore } from '@outputai/llm';
import { z } from '@outputai/core';

Agent comes from @outputai/llm. Use aiSdk.Output for structured output. Import z from @outputai/core (never from zod directly). MessageStore is the type for a pluggable getMessages / addMessages store; implement it yourself.

Construction

The prompt file is loaded and rendered at construction time. Variables and tools are fixed at construction. Skills and maxSteps come from the prompt file. The agent is ready to call generate(), generateWithStreaming(), or stream() immediately.

const agent = new Agent( {
  prompt: 'writing_assistant@v1',
  variables: {
    content_type: input.contentType,
    focus: input.focus,
    content: input.content
  },
  output: aiSdk.Output.object( { schema: reviewSchema } )
} );

Constructor Options

Option Type Default Description
prompt string (required) Prompt file name (e.g. 'writing_assistant@v1')
promptDir string - Override the stack-resolved prompt directory
variables PromptVariables - Template variables rendered at construction
tools AI SDK tools - Caller tools; merged with prompt YAML tools (load_skill last)
stopWhen function or function[] - Custom stop condition (overrides prompt maxSteps when tools exist)
output aiSdk.Output - Structured output spec (e.g. aiSdk.Output.object({ schema }))
messageStore MessageStore - Pluggable store for multi-turn history

generate()

Run the agent and return when complete:

const result = await agent.generate();
console.log( result.text );   // Generated text
console.log( result.output ); // Structured output (when using aiSdk.Output.object)
console.log( result.usage );  // Token counts

The result has the same shape as generateText: text, result (alias for text), output, usage, finishReason, toolCalls, etc.

Passing Additional Messages

Extend the conversation with extra messages:

const result = await agent.generate( {
  messages: [ { role: 'user', content: 'Focus on the introduction section.' } ]
} );

Messages are appended after the initial prompt messages (and any message-store history). You can also pass abortSignal and toolChoice.

generateWithStreaming()

Use generateWithStreaming() when you need progress callbacks and a complete result:

const result = await agent.generateWithStreaming( {
  onChunk( { chunk } ) {
    if ( chunk.type === 'text-delta' ) {
      process.stdout.write( chunk.text );
    }
  }
} );

The method behaves like generate() while using streaming internally. It returns the complete response, rejects on stream errors, and automatically appends messages to the configured message store. It accepts the same messages, abortSignal, and toolChoice as generate(), plus onChunk. Prefer it over stream() in Temporal activity steps unless direct access to the stream result is required.

stream()

Use stream() when direct control over textStream or stream is required. It accepts the same messages, abortSignal, and toolChoice as generate(), plus onChunk, onEnd, and onError:

const stream = await agent.stream();

for await ( const chunk of stream.textStream ) {
  process.stdout.write( chunk );
}

Like streamText, the stream result provides textStream and stream iterables, plus promise-based properties (text, usage, finishReason) that resolve on completion.

stream() appends messages to the message store in its wrapped onEnd when finishReason is not 'error'. See output-dev-llm-streaming for streaming and error-handling guidance.

Structured Output

Use aiSdk.Output.object() to get typed responses:

const reviewSchema = z.object( {
  issues: z.array( z.string() ).describe( 'List of issues found' ),
  suggestions: z.array( z.string() ).describe( 'Actionable suggestions' ),
  score: z.number().describe( 'Quality score 0-100' ),
  summary: z.string().describe( 'Brief overall assessment' )
} );

const agent = new Agent( {
  prompt: 'writing_assistant@v1',
  variables: { content_type: 'documentation', focus: 'clarity', content: markdownContent },
  output: aiSdk.Output.object( { schema: reviewSchema } )
} );

const { output } = await agent.generate();
// output: { issues: string[], suggestions: string[], score: number, summary: string }

Use .describe() on schema fields instead of .min()/.max() for number constraints. Anthropic does not support minimum/maximum JSON Schema constraints in tool definitions.

Message Store

By default, Agent is stateless. Each generate() call starts fresh with only the initial prompt messages. Pass a messageStore to maintain history across calls:

import { Agent } from '@outputai/llm';
import type { MessageStore } from '@outputai/llm';

const messages: Parameters<MessageStore['addMessages']>[0] = [];
const messageStore: MessageStore = {
  getMessages: () => messages,
  addMessages: incoming => {
    messages.push( ...incoming );
  }
};

const chatbot = new Agent( {
  prompt: 'chatbot@v1',
  messageStore
} );

const r1 = await chatbot.generate( {
  messages: [ { role: 'user', content: 'Hello, tell me about Output.' } ]
} );
// r1.text: "Output is an AI framework for..."

const r2 = await chatbot.generate( {
  messages: [ { role: 'user', content: 'How does it handle retries?' } ]
} );
// r2 sees the full history from r1

MessageStore is:

interface MessageStore {
  getMessages(): ModelMessage[] | Promise<ModelMessage[]>;
  addMessages( messages: ModelMessage[] ): void | Promise<void>;
}

ModelMessage is an AI SDK type available through the aiSdk namespace or as an import from ai. There is no built-in store. Implement the interface in memory for a single process, or with your database for durable history.

Using Agent in Workflow Steps

In workflow steps, construct a new Agent per invocation. Variables come from the step input:

import { step, z } from '@outputai/core';
import { Agent, aiSdk } from '@outputai/llm';

const reviewSchema = z.object( {
  summary: z.string().describe( 'Brief assessment' ),
  issues: z.array( z.string() ).describe( 'Problems found' ),
  suggestions: z.array( z.string() ).describe( 'Improvements' ),
  score: z.number().describe( 'Quality score 0-100' )
} );

export const reviewContent = step( {
  name: 'reviewContent',
  description: 'Review technical content using Agent with structured output',
  inputSchema: z.object( {
    content: z.string().describe( 'The content to review' ),
    content_type: z.string().describe( 'Type of content' ),
    focus: z.string().describe( 'Review focus areas' )
  } ),
  outputSchema: reviewSchema,
  fn: async input => {
    const agent = new Agent( {
      prompt: 'writing_assistant@v1',
      variables: input,
      output: aiSdk.Output.object( { schema: reviewSchema } )
    } );
    const { output } = await agent.generate();
    return output;
  }
} );

This is the standard pattern. Each step invocation is independent, and Agent construction is cheap.

Using Agent with Skills

List skill paths in the prompt frontmatter. See output-dev-skill-file for the full skills guide.

When to Use Agent vs generateText

generateText Agent
Best for Single-shot LLM calls Multi-step tool loops
Tools Supported Supported
Skills Supported Supported
Conversation history Manual Built-in with messageStore
Reusable instance No (function call) Yes (construct once, call many)
Structured output aiSdk.Output.object() aiSdk.Output.object()

Start with generateText. Move to Agent when you need conversation state or a reusable instance with a fixed configuration.

generateText Example (for comparison)

import { generateText } from '@outputai/llm';

const { result } = await generateText( {
  prompt: 'generate_summary@v1',
  variables: {
    company_name: input.name,
    website_content: input.websiteContent
  }
} );

Verification Checklist

  • [ ] Import Agent from @outputai/llm (not from ai directly)
  • [ ] Import z from @outputai/core (never from zod)
  • [ ] Prompt file exists in prompts/ folder
  • [ ] Variables match {{ variable }} placeholders in the prompt
  • [ ] Prompt frontmatter sets maxSteps when skills or tools need a ceiling other than 10
  • [ ] aiSdk.Output.object({ schema }) uses .describe() not .min()/.max() on numbers
  • [ ] messageStore is only used when multi-turn history is needed
  • [ ] Agent is constructed inside the step fn (not at module level) for workflow steps
  • [ ] Prefer generateWithStreaming() when callbacks are sufficient

Related Skills

  • output-dev-skill-file - Creating skill files for agents
  • output-dev-llm-streaming - Streaming progress and Temporal-safe error handling
  • output-dev-prompt-file - Creating .prompt files used by agents
  • output-dev-step-function - Using agents in step functions
  • output-dev-types-file - Defining Zod schemas for structured output
  • output-dev-workflow-function - Orchestrating agent-powered steps

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。