AI エージェント: アーキテクチャと実装パターン
AI エージェントは、単純な LLM 呼び出しの自然な進化を表します。モデルへの API 呼び出し中 linguistic は静的な応答を返します。 自律エージェント 推論し、計画し、 外部ツールを使用し、目標が達成されるまで繰り返します。このアーキテクチャの違い ソフトウェア自動化のためのまったく新しいシナリオを開きます。
この記事では、AI エージェントのアーキテクチャ、最も一般的な展開パターン、 メモリとオーケストレーション システムを構築し、TypeScript で動作するエージェントを構築します。
何を学ぶか
- 単純な LLM 呼び出しと AI エージェントの違い
- ReAct パターン (推論 + 行動)
- ツール呼び出しアーキテクチャ
- マルチエージェント システムとオーケストレーション パターン
- 記憶システム: 短期、長期、エピソード
- TypeScript でエージェントを構築する
- エージェントベースのワークフロー用の LangGraph
- エラー処理、フォールバック、セキュリティ
LLM 対 AI エージェントの通話
エージェントの価値を理解するには、エージェントと単純な対話の違いを理解することが重要です LLMを使用して。直接の比較は次のとおりです。
| 特性 | LLM シンプルに電話をかける | AIエージェント |
|---|---|---|
| 交流 | 単一のリクエスト/レスポンス | 完了するまでの反復ループ |
| 楽器 | 誰でもない | 外部ツール(API、DB、ファイル)へのアクセス |
| 推論 | 答えに暗黙的に含まれている | 推論手順を明示的に示す |
| メモリ | リクエストのコンテキストのみ | 短期、長期、エピソード的 |
| 企画 | なし | 下位目標への分解 |
| 自律性 | ゼロ (人間による入力が必要) | 高 (実行するアクションを決定します) |
| 料金 | 1 API呼び出し | N 回の API 呼び出し (複数回の反復) |
エージェントを使用する場合
すべての問題にエージェントが必要なわけではありません。 1 つ使用してください シンプルLLMと呼ばれる 明確に定義されたタスク用 分類、翻訳、テキスト生成など。を使用します。 エージェント タスクのとき 複数の手順が必要な場合、外部ツールへのアクセスが必要な場合、または解決策のパスが事前にわかっていない場合。
ReAct パターン: 推論 + 行動
パターン 反応する (Reason + Act) は、ほとんどのアーキテクチャの基盤です。 最新の AI エージェント。エージェントはフェーズを交互に切り替えます。 推論 (そこで彼は状況を分析し、決定を下します) 次のアクション) とフェーズ アクション (ツールまたは具体的な操作を実行します)。
interface ReActStep {
thought: string; // Ragionamento dell'agente
action: string; // Nome del tool da invocare
actionInput: any; // Parametri per il tool
observation: string; // Risultato dell'azione
}
interface AgentState {
goal: string;
steps: ReActStep[];
finalAnswer: string | null;
}
async function reactLoop(goal: string, maxIterations = 10): Promise<string> {
const state: AgentState = {
goal,
steps: [],
finalAnswer: null
};
for (let i = 0; i < maxIterations; i++) {
// 1. REASONING: Chiedi all'LLM di ragionare
const prompt = buildReActPrompt(state);
const response = await callLLM(prompt);
// 2. PARSING: Estrai thought, action e action_input
const parsed = parseReActResponse(response);
if (parsed.action === 'final_answer') {
state.finalAnswer = parsed.actionInput;
break;
}
// 3. ACTING: Esegui il tool scelto
const observation = await executeTool(parsed.action, parsed.actionInput);
// 4. Salva lo step e continua il loop
state.steps.push({
thought: parsed.thought,
action: parsed.action,
actionInput: parsed.actionInput,
observation
});
}
return state.finalAnswer ?? 'Obiettivo non raggiunto nel limite di iterazioni';
}
ReAct ループの各反復により、 考え (エージェントの推論)、アクション
(呼び出すツール) と観察 (結果)。このサイクルは、エージェントが完了するまで続きます。
特別なアクションを発行します final_answer または最大反復制限に達します。
ツール呼び出しアーキテクチャ
Il ツール呼び出し これは、エージェントが外部世界と対話できるようにするメカニズムです。 最新のモデル (GPT-4、Claude、Gemini) は、エージェントが実行する関数の定義をネイティブにサポートしています。 呼び出すことができます。構造化された方法でツールを定義および登録する方法を見てみましょう。
interface ToolDefinition {
name: string;
description: string;
parameters: Record<string, ToolParameter>;
execute: (params: any) => Promise<string>;
}
interface ToolParameter {
type: 'string' | 'number' | 'boolean' | 'object';
description: string;
required: boolean;
enum?: string[];
}
class ToolRegistry {
private tools = new Map<string, ToolDefinition>();
register(tool: ToolDefinition): void {
this.tools.set(tool.name, tool);
console.log(`Tool registrato: ${tool.name}`);
}
async execute(name: string, params: any): Promise<string> {
const tool = this.tools.get(name);
if (!tool) {
throw new Error(`Tool non trovato: ${name}`);
}
return tool.execute(params);
}
getSchemas(): object[] {
return Array.from(this.tools.values()).map(tool => ({
type: 'function',
function: {
name: tool.name,
description: tool.description,
parameters: {
type: 'object',
properties: tool.parameters,
required: Object.entries(tool.parameters)
.filter(([_, p]) => p.required)
.map(([key]) => key)
}
}
}));
}
}
// Esempio: registrazione tool
const registry = new ToolRegistry();
registry.register({
name: 'search_web',
description: 'Cerca informazioni sul web',
parameters: {
query: {
type: 'string',
description: 'La query di ricerca',
required: true
}
},
execute: async (params) => {
const results = await searchAPI(params.query);
return JSON.stringify(results.slice(0, 5));
}
});
registry.register({
name: 'read_file',
description: 'Legge il contenuto di un file',
parameters: {
path: {
type: 'string',
description: 'Il percorso del file da leggere',
required: true
}
},
execute: async (params) => {
return await fs.readFile(params.path, 'utf-8');
}
});
registry.register({
name: 'execute_sql',
description: 'Esegue una query SQL su un database',
parameters: {
query: {
type: 'string',
description: 'La query SQL da eseguire',
required: true
},
database: {
type: 'string',
description: 'Nome del database',
required: true
}
},
execute: async (params) => {
const result = await db.query(params.query, params.database);
return JSON.stringify(result.rows);
}
});
ツールのセキュリティ
外部システム (データベース、ファイルシステム、API) と対話するすべてのツールには、 入力検証, 権限の制限 e サンドボックス化。 エージェントが機能不全に陥り、データベースに無制限にアクセスすると、重大な損害が発生する可能性があります。
マルチエージェントオーケストレーションパターン
複雑なタスクの場合、単一のエージェントでは不十分な場合があります。ザ マルチエージェントシステム 彼らは調整します それぞれが特定のスキルを備えた複数の専門エージェント。主なオーケストレーション パターンは 3 つあります。
連続パターン
エージェントは次々と処刑されます。あるエージェントの出力は、次のエージェントの入力になります。 直線的なパイプラインに最適です。
interface AgentResult {
output: string;
metadata: Record<string, any>;
}
class SequentialOrchestrator {
private agents: Agent[] = [];
addAgent(agent: Agent): this {
this.agents.push(agent);
return this;
}
async run(initialInput: string): Promise<AgentResult> {
let currentInput = initialInput;
let metadata: Record<string, any> = {};
for (const agent of this.agents) {
console.log(`Esecuzione agente: ${agent.name}`);
const result = await agent.execute(currentInput);
currentInput = result.output;
metadata[agent.name] = result.metadata;
}
return { output: currentInput, metadata };
}
}
// Uso: pipeline di code review
const reviewPipeline = new SequentialOrchestrator()
.addAgent(new CodeAnalyzerAgent()) // Analizza il codice
.addAgent(new SecurityAuditorAgent()) // Cerca vulnerabilità
.addAgent(new ReportGeneratorAgent()); // Genera il report
const result = await reviewPipeline.run(codeToReview);
平行パターン
複数のエージェントが同じ入力に対して同時に動作します。結果は最後に集計されます。 並行して実行できる独立したタスクに最適です。
class ParallelOrchestrator {
private agents: Agent[] = [];
addAgent(agent: Agent): this {
this.agents.push(agent);
return this;
}
async run(input: string): Promise<AgentResult[]> {
const promises = this.agents.map(async (agent) => {
console.log(`Avvio parallelo: ${agent.name}`);
try {
return await agent.execute(input);
} catch (error) {
return {
output: `Errore in ${agent.name}: ${error.message}`,
metadata: { error: true }
};
}
});
return Promise.all(promises);
}
async runWithAggregation(
input: string,
aggregator: (results: AgentResult[]) => string
): Promise<string> {
const results = await this.run(input);
return aggregator(results);
}
}
// Uso: analisi multi-prospettiva di un PR
const prAnalysis = new ParallelOrchestrator()
.addAgent(new CodeQualityAgent())
.addAgent(new PerformanceAgent())
.addAgent(new SecurityAgent())
.addAgent(new DocumentationAgent());
const analyses = await prAnalysis.runWithAggregation(
prDiff,
(results) => results.map(r => r.output).join('\n---\n')
);
階層パターン
エージェント 監督者 専門化されたサブエージェントを調整し、動的に意思決定を行う 各サブタスクを誰に委任するか。これは最も柔軟で強力なパターンです。
class SupervisorAgent {
private subAgents = new Map<string, Agent>();
registerAgent(name: string, agent: Agent): void {
this.subAgents.set(name, agent);
}
async run(goal: string): Promise<string> {
const agentList = Array.from(this.subAgents.keys());
let context = '';
let iterations = 0;
while (iterations < 15) {
// Il supervisore decide chi invocare
const decision = await this.decide(goal, context, agentList);
if (decision.action === 'complete') {
return decision.finalAnswer;
}
// Delega al sotto-agente scelto
const agent = this.subAgents.get(decision.delegateTo);
if (!agent) {
context += `\nErrore: agente ${decision.delegateTo} non trovato`;
continue;
}
const result = await agent.execute(decision.task);
context += `\n[${decision.delegateTo}]: ${result.output}`;
iterations++;
}
return 'Obiettivo non raggiunto nel limite di iterazioni';
}
private async decide(
goal: string,
context: string,
agents: string[]
): Promise<SupervisorDecision> {
const prompt = `
Sei un supervisore che coordina questi agenti: ${agents.join(', ')}
Obiettivo: ${goal}
Contesto delle azioni precedenti:
${context || 'Nessuna azione precedente'}
Decidi la prossima azione:
- delegateTo: nome dell'agente
- task: descrizione del sotto-task
- oppure action: "complete" con finalAnswer
`;
return await callLLM(prompt);
}
}
| パターン | 利点 | 短所 | 理想的な使用例 |
|---|---|---|---|
| 一連 | シンプル、予測可能 | ゆっくり、硬い | ETLパイプライン、コードレビュー |
| 平行 | 高速かつ効率的 | 相互依存性がない | 多面分析・テスト |
| 階層的 | 柔軟で適応性のある | 複雑、高価 | タスクを開き、検索、デバッグする |
エージェント用の記憶システム
記憶はエージェントを変えるものです ステートレス 一つで ステートフル学習できる 過去のやり取りから学び、時間をかけて知識を構築します。記憶には 3 つの基本的なタイプがあります。
短期記憶
現在の会話のコンテキストと一致します。メッセージ履歴も含まれます。 ツールからの観察と中間推論。これはモデル コンテキスト ウィンドウによって制限されます。
長期記憶
異なるセッション間の永続的な情報: ユーザーの好み、学習した事実、確立された手順。 通常、ベクトル ストアまたは構造化データベースを使用して実装されます。
エピソード記憶
解決したタスク、犯した間違い、うまくいった戦略など、過去の経験を完全に記録します。 これにより、エージェントは同様の状況を「記憶」し、すでにテストされたソリューションを適用できます。
interface Memory {
id: string;
content: string;
type: 'short_term' | 'long_term' | 'episodic';
timestamp: Date;
relevanceScore?: number;
metadata: Record<string, any>;
}
interface Episode {
task: string;
steps: string[];
outcome: 'success' | 'failure';
lessonsLearned: string;
timestamp: Date;
}
class AgentMemorySystem {
private shortTerm: Memory[] = [];
private vectorStore: VectorStore;
private episodeStore: Episode[] = [];
private maxShortTerm = 50;
constructor(vectorStore: VectorStore) {
this.vectorStore = vectorStore;
}
// Short-term: aggiungi al contesto corrente
addToShortTerm(content: string, metadata: Record<string, any> = {}): void {
this.shortTerm.push({
id: crypto.randomUUID(),
content,
type: 'short_term',
timestamp: new Date(),
metadata
});
// Evita overflow: rimuovi i più vecchi
if (this.shortTerm.length > this.maxShortTerm) {
this.shortTerm = this.shortTerm.slice(-this.maxShortTerm);
}
}
// Long-term: salva nel vector store per retrieval semantico
async addToLongTerm(content: string, metadata: Record<string, any>): Promise<void> {
await this.vectorStore.addDocument({
content,
metadata: { ...metadata, type: 'long_term', timestamp: new Date() }
});
}
// Episodic: registra un'esperienza completa
addEpisode(episode: Episode): void {
this.episodeStore.push(episode);
}
// Recupera memorie rilevanti per il contesto attuale
async recall(query: string, limit = 5): Promise<Memory[]> {
// Short-term: ultime N interazioni
const recentShortTerm = this.shortTerm.slice(-10);
// Long-term: ricerca semantica
const longTermResults = await this.vectorStore.search(query, limit);
// Episodic: esperienze simili
const relevantEpisodes = await this.findSimilarEpisodes(query);
return [
...recentShortTerm,
...longTermResults.map(r => ({
id: r.id,
content: r.content,
type: 'long_term' as const,
timestamp: r.metadata.timestamp,
relevanceScore: r.score,
metadata: r.metadata
})),
...relevantEpisodes.map(ep => ({
id: crypto.randomUUID(),
content: `Episodio precedente: ${ep.task} - Esito: ${ep.outcome} - Lezione: ${ep.lessonsLearned}`,
type: 'episodic' as const,
timestamp: ep.timestamp,
metadata: {}
}))
];
}
private async findSimilarEpisodes(query: string): Promise<Episode[]> {
// Implementazione semplificata: ricerca per similarità
return this.episodeStore
.filter(ep => ep.task.toLowerCase().includes(query.toLowerCase().slice(0, 20)))
.slice(0, 3);
}
}
TypeScript で完全なエージェントを構築する
これまでに説明したすべての概念を組み合わせて、Web を閲覧できる機能するエージェントを構築しましょう。 ファイルを読んで複雑な質問に答えます。
import Anthropic from '@anthropic-ai/sdk';
interface Tool {
name: string;
description: string;
inputSchema: object;
execute: (input: any) => Promise<string>;
}
class TypeScriptAgent {
private client: Anthropic;
private tools: Tool[] = [];
private conversationHistory: any[] = [];
private maxIterations = 15;
constructor(apiKey: string) {
this.client = new Anthropic({ apiKey });
}
registerTool(tool: Tool): void {
this.tools.push(tool);
}
async run(userMessage: string): Promise<string> {
this.conversationHistory.push({
role: 'user',
content: userMessage
});
for (let i = 0; i < this.maxIterations; i++) {
const response = await this.client.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 4096,
system: this.buildSystemPrompt(),
tools: this.tools.map(t => ({
name: t.name,
description: t.description,
input_schema: t.inputSchema
})),
messages: this.conversationHistory
});
// Se il modello risponde con testo, abbiamo finito
if (response.stop_reason === 'end_turn') {
const textBlock = response.content.find(b => b.type === 'text');
return textBlock?.text ?? '';
}
// Se il modello vuole usare tool
if (response.stop_reason === 'tool_use') {
this.conversationHistory.push({
role: 'assistant',
content: response.content
});
const toolResults = [];
for (const block of response.content) {
if (block.type === 'tool_use') {
const tool = this.tools.find(t => t.name === block.name);
let result: string;
try {
result = await tool!.execute(block.input);
} catch (error) {
result = `Errore: ${error.message}`;
}
toolResults.push({
type: 'tool_result',
tool_use_id: block.id,
content: result
});
}
}
this.conversationHistory.push({
role: 'user',
content: toolResults
});
}
}
return 'Limite massimo di iterazioni raggiunto.';
}
private buildSystemPrompt(): string {
return `Sei un assistente AI avanzato con accesso a tool.
Ragiona step-by-step prima di agire.
Usa i tool quando necessario per completare il task.
Sii preciso e conciso nelle risposte.`;
}
}
// Configurazione e avvio dell'agente
const agent = new TypeScriptAgent(process.env.ANTHROPIC_API_KEY!);
agent.registerTool({
name: 'web_search',
description: 'Cerca informazioni sul web',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Query di ricerca' }
},
required: ['query']
},
execute: async (input) => {
const response = await fetch(
`https://api.search.com/search?q=${encodeURIComponent(input.query)}`
);
const data = await response.json();
return JSON.stringify(data.results.slice(0, 5));
}
});
agent.registerTool({
name: 'calculator',
description: 'Esegue calcoli matematici',
inputSchema: {
type: 'object',
properties: {
expression: { type: 'string', description: 'Espressione matematica' }
},
required: ['expression']
},
execute: async (input) => {
// Uso sicuro: solo operazioni matematiche
const result = Function(`"use strict"; return (${input.expression})`)();
return String(result);
}
});
// Esecuzione
const answer = await agent.run(
'Qual è la popolazione della Francia e quanto è il 15% di quella cifra?'
);
console.log(answer);
エージェント ワークフローの LangGraph
ランググラフ は、エージェントベースのワークフローをグラフとして定義できるフレームワークです。 各ノードは操作 (LLM、ツール実行、カスタム ロジックと呼ばれます) であり、エッジによって定義されます。 条件やループを含む制御フロー。
import { StateGraph, END } from '@langchain/langgraph';
import { ChatAnthropic } from '@langchain/anthropic';
// Definizione dello stato del grafo
interface WorkflowState {
messages: any[];
currentStep: string;
toolResults: Record<string, any>;
retryCount: number;
}
// Nodi del grafo
async function analyzeNode(state: WorkflowState): Promise<Partial<WorkflowState>> {
const llm = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' });
const response = await llm.invoke(state.messages);
return {
messages: [...state.messages, response],
currentStep: 'analyze'
};
}
async function toolNode(state: WorkflowState): Promise<Partial<WorkflowState>> {
const lastMessage = state.messages[state.messages.length - 1];
const toolCalls = lastMessage.tool_calls ?? [];
const results: Record<string, any> = {};
for (const call of toolCalls) {
results[call.name] = await executeTool(call.name, call.args);
}
return {
toolResults: { ...state.toolResults, ...results },
currentStep: 'tool_execution'
};
}
function shouldContinue(state: WorkflowState): string {
const lastMessage = state.messages[state.messages.length - 1];
if (lastMessage.tool_calls?.length > 0) {
return 'execute_tools';
}
return 'end';
}
// Costruzione del grafo
const workflow = new StateGraph<WorkflowState>({
channels: {
messages: { default: () => [] },
currentStep: { default: () => 'start' },
toolResults: { default: () => ({}) },
retryCount: { default: () => 0 }
}
});
workflow.addNode('analyze', analyzeNode);
workflow.addNode('execute_tools', toolNode);
workflow.addEdge('__start__', 'analyze');
workflow.addConditionalEdges('analyze', shouldContinue, {
execute_tools: 'execute_tools',
end: END
});
workflow.addEdge('execute_tools', 'analyze'); // Loop back
const app = workflow.compile();
// Esecuzione
const result = await app.invoke({
messages: [{ role: 'user', content: 'Analizza il repository GitHub xyz/abc' }]
});
エラー管理とフォールバック
堅牢なエージェントは、ツールの障害、不正な応答など、あらゆるレベルのエラーを処理する必要があります。 LLM からのタイムアウト、および制限の超過。主な戦略は次のとおりです。
class ResilientAgent {
private maxRetries = 3;
private retryDelayMs = 1000;
// Retry con backoff esponenziale per chiamate LLM
private async callWithRetry<T>(
fn: () => Promise<T>,
context: string
): Promise<T> {
for (let attempt = 0; attempt < this.maxRetries; attempt++) {
try {
return await fn();
} catch (error: any) {
const isRetryable = error.status === 429 || error.status >= 500;
if (!isRetryable || attempt === this.maxRetries - 1) {
throw new AgentError(`${context}: ${error.message}`, {
attempt,
originalError: error
});
}
const delay = this.retryDelayMs * Math.pow(2, attempt);
console.warn(`Retry ${attempt + 1} per ${context} tra ${delay}ms`);
await sleep(delay);
}
}
throw new Error('Unreachable');
}
// Fallback: se un tool fallisce, prova un'alternativa
private async executeWithFallback(
toolName: string,
params: any,
fallbacks: string[]
): Promise<string> {
try {
return await this.executeTool(toolName, params);
} catch (error) {
for (const fallbackTool of fallbacks) {
try {
console.warn(`Fallback da ${toolName} a ${fallbackTool}`);
return await this.executeTool(fallbackTool, params);
} catch {
continue;
}
}
return `Tutti i tool hanno fallito per: ${toolName}`;
}
}
// Circuit breaker: disabilita tool che falliscono ripetutamente
private toolFailureCounts = new Map<string, number>();
private circuitBreakerThreshold = 5;
private isToolCircuitOpen(toolName: string): boolean {
const failures = this.toolFailureCounts.get(toolName) ?? 0;
return failures >= this.circuitBreakerThreshold;
}
private recordToolFailure(toolName: string): void {
const current = this.toolFailureCounts.get(toolName) ?? 0;
this.toolFailureCounts.set(toolName, current + 1);
if (current + 1 >= this.circuitBreakerThreshold) {
console.error(`Circuit breaker aperto per tool: ${toolName}`);
}
}
}
class AgentError extends Error {
constructor(message: string, public details: Record<string, any>) {
super(message);
this.name = 'AgentError';
}
}
回復力のためのベストプラクティス
- バックオフを使用して再試行します。 一時的なエラーの場合 (レート制限、タイムアウト)
- フォールバックツール: プライマリに障害が発生した場合の代替ツール
- サーキットブレーカー: 繰り返し失敗するツールを自動的に無効にする
- グローバルタイムアウト: エージェント実行全体の最大制限
- 構造化されたロギング: デバッグと事後分析のために各ステップをトレースします
AIエージェントのセキュリティ
AI エージェントは、慎重に管理する必要がある特定のリスクをもたらします。ツールへのアクセス 外部エージェントはそれらを強力にしますが、適切に制御されない場合は潜在的に危険でもあります。
| リスク | 説明 | 緩和 |
|---|---|---|
| 即時注入 | エージェントの動作を変える悪意のある入力 | 入力検証、サンドボックス、プロンプト強化 |
| ツールの乱用 | エージェントが予期しない方法または悪意のある方法でツールを使用する | きめ細かな権限、レート制限、人間による承認 |
| データの引き出し | エージェントがツールを介して機密データを公開する | DLP (データ損失防止)、出力フィルター |
| 無限ループ | エージェントが収束せずにループに入る | 反復制限、タイムアウト、サーキット ブレーカー |
| リソースの枯渇 | 過剰な API 呼び出しによりコストが高くなる | セッションあたりの予算、レート制限、モニタリング |
interface SecurityPolicy {
allowedTools: string[];
maxTokenBudget: number;
maxIterations: number;
requireHumanApproval: string[]; // Tool che richiedono approvazione
blockedPatterns: RegExp[]; // Pattern da bloccare negli input
}
class SecureAgentWrapper {
private tokenUsed = 0;
constructor(
private agent: TypeScriptAgent,
private policy: SecurityPolicy
) {}
async run(input: string): Promise<string> {
// 1. Valida input contro pattern bloccati
for (const pattern of this.policy.blockedPatterns) {
if (pattern.test(input)) {
throw new Error('Input bloccato dalla policy di sicurezza');
}
}
// 2. Intercetta le chiamate tool
const originalExecute = this.agent.executeTool.bind(this.agent);
this.agent.executeTool = async (name: string, params: any) => {
// Verifica tool nella whitelist
if (!this.policy.allowedTools.includes(name)) {
return `Tool ${name} non permesso dalla policy`;
}
// Richiedi approvazione umana se necessario
if (this.policy.requireHumanApproval.includes(name)) {
const approved = await requestHumanApproval(name, params);
if (!approved) return 'Azione rifiutata dall\'utente';
}
return originalExecute(name, params);
};
return this.agent.run(input);
}
}
// Configurazione della policy
const policy: SecurityPolicy = {
allowedTools: ['web_search', 'calculator', 'read_file'],
maxTokenBudget: 100000,
maxIterations: 20,
requireHumanApproval: ['execute_sql', 'send_email', 'write_file'],
blockedPatterns: [
/ignore previous instructions/i,
/system prompt/i,
/you are now/i
]
};
人間参加型
重要な操作 (データベースへの書き込み、電子メールの送信、運用ファイルへの変更) の場合、 常にメカニズムを実装します 人間の承認。エージェントの自主性 特に実稼働環境では、人間による制御とのバランスを取る必要があります。
結論
AI エージェントは、単純な LLM 呼び出しと比較して、質的な飛躍を表します。パターン 反応する、と組み合わせる ツール呼び出し, メモリシステム e マルチエージェントオーケストレーションに対応できるシステムを構築できます。 複雑なタスクを独立して実行できます。
成功の鍵はバランスです 自主性とコントロール: エージェントに渡します 十分な自由があり便利ですが、行動を防ぐのに十分なガードレールが必要です 不要な。シリーズの最後の記事では、AI を直接統合する方法について説明します。 CI/CD パイプライン コードレビュー、テスト、展開を自動化します。
覚えておくべき重要なポイント
- 反応ループ: タスクを反復的に解決するための推論とアクションを交互に繰り返す
- ツール呼び出し: 各ツールに明確で安全なインターフェイスを定義する
- オーケストレーション: タスクに基づいてパターン (順次、並列、階層) を選択します
- メモリ: より賢いエージェント向けの短期、長期、エピソード
- 安全性: ホワイトリストツール、人間による承認、サーキットブレーカー
- 回復力: 本番環境での堅牢なエージェントの再試行、フォールバック、およびタイムアウト







