Category: reference
AI Agents & Agentic Patterns
สถาปัตยกรรมและ patterns สำหรับ AI agents: agentic loop, tool use, multi-step planning, orchestration, parallel agents และการจัดการ context window
สารบัญ
Agent คืออะไร
Agent คือ LLM ที่ได้รับ tools และตัดสินใจเองว่าจะใช้ tool อะไร กี่ครั้ง เพื่อให้งานสำเร็จ แทนที่จะตอบครั้งเดียว
[Task] → [LLM] → [Tool call] → [Result] → [LLM] → [Tool call] → ... → [Final Answer]
Agentic Loop พื้นฐาน
async function runAgent(task: string, tools: Tool[]): Promise<string> {
const messages: Message[] = [{ role: 'user', content: task }];
while (true) {
const response = await llm.call({ messages, tools });
if (response.stop_reason === 'end_turn') {
return response.text; // งานเสร็จ
}
if (response.stop_reason === 'tool_use') {
const toolResults = await executeTools(response.tool_calls);
messages.push(
{ role: 'assistant', content: response.content },
{ role: 'user', content: toolResults },
);
// วนซ้ำ
}
if (messages.length > MAX_TURNS) throw new Error('Max turns exceeded');
}
}
Tool Design
// ✓ Tool ที่ดี: action เดียว ผลลัพธ์ชัด
const readFile: Tool = {
name: 'read_file',
description: 'อ่านเนื้อหาไฟล์จาก path ที่ระบุ',
input_schema: {
type: 'object',
properties: { path: { type: 'string', description: 'absolute path to file' } },
required: ['path'],
},
};
// ❌ Tool ที่ไม่ดี: ทำหลายอย่าง, description ไม่ชัด
const doStuff: Tool = {
name: 'process_and_save',
description: 'ทำอะไรบางอย่างกับข้อมูล', // ❌ ไม่รู้จะใช้เมื่อไหร่
// ...
};
// ✓ Set of tools ที่ดี: ครอบคลุม แต่ไม่ซ้ำซ้อน
const tools = [
readFile,
writeFile,
listDirectory,
searchFiles,
runCommand,
fetchURL,
];
Agent Patterns
1. ReAct (Reason + Act)
บังคับให้ agent คิดก่อนทำ ลด hallucination และ wrong tool call
const systemPrompt = `
ก่อนทำงานทุกครั้ง ให้คิดออกเสียงใน <thinking> tag ว่า:
- ตอนนี้รู้อะไรบ้าง
- ขาดข้อมูลอะไร
- tool ไหนควรใช้ถัดไป
<thinking>
ผมต้องอ่านไฟล์ config ก่อน เพื่อรู้ว่า database อยู่ที่ไหน
</thinking>
[tool call: readFile]
`;
2. Plan-and-Execute
วางแผนทั้งหมดก่อน แล้วค่อย execute ทีละขั้น
// Phase 1: Planning
const plan = await plannerAgent(task);
// plan = ["อ่านไฟล์ทั้งหมด", "วิเคราะห์ dependencies", "สร้าง summary", ...]
// Phase 2: Execute each step
for (const step of plan.steps) {
const result = await executorAgent(step, context);
context.push(result);
}
3. Parallel Agents
แยกงานออกเป็น sub-tasks และรันพร้อมกัน
const results = await Promise.all([
agent('วิเคราะห์คุณภาพ code', { files: changedFiles }),
agent('ตรวจ security vulnerabilities', { files: changedFiles }),
agent('วัด performance impact', { files: changedFiles }),
]);
const combined = synthesizeAgent(results);
4. Orchestrator–Subagent
Agent หลักสั่ง sub-agents ทำงาน แล้วรวมผล
// Orchestrator
const orchestratorPrompt = `
คุณเป็น project manager ควบคุม agents อื่น
เมื่อได้รับงาน ให้แบ่งและมอบหมายให้ sub-agents ที่เหมาะสม:
- frontend_agent: งาน UI/CSS
- content_agent: งานเขียน
- qa_agent: ตรวจคุณภาพ
รายงานกลับเมื่อทุก agent เสร็จหรือติดปัญหา
`;
Context Management
// Context window มีขีดจำกัด — ต้องจัดการ
const MAX_TOKENS = 100_000; // Claude Sonnet = 200k context
// Strategy 1: Summarize ก่อน overflow
if (estimateTokens(messages) > MAX_TOKENS * 0.8) {
const summary = await summarizeAgent(messages.slice(0, -5));
messages = [
{ role: 'user', content: `Summary of previous work:\n${summary}` },
...messages.slice(-5), // เก็บ recent messages
];
}
// Strategy 2: Handoff — บันทึก state แล้ว start fresh
const state = await agent.exportState();
// บันทึก state ลง disk หรือ database
// รอบหน้า: load state แล้วใช้ต่อ
Error Recovery
async function robustAgent(task: string): Promise<string> {
let attempts = 0;
const errors: string[] = [];
while (attempts < MAX_RETRIES) {
try {
return await runAgent(task);
} catch (error) {
errors.push(String(error));
attempts++;
// บอก agent เกี่ยวกับ error และให้ลองใหม่
task = `${task}\n\nPrevious attempt failed: ${error}\nTry a different approach.`;
}
}
throw new Error(`Failed after ${attempts} attempts:\n${errors.join('\n')}`);
}
Human-in-the-Loop
// หยุดรอ human confirm ก่อน action ที่ risky
async function confirmAction(action: string): Promise<boolean> {
console.log(`\nAgent wants to: ${action}`);
const answer = await prompt('Approve? (y/n): ');
return answer.toLowerCase() === 'y';
}
// ใน agentic loop
if (toolCall.name === 'deleteFile' || toolCall.name === 'sendEmail') {
const approved = await confirmAction(JSON.stringify(toolCall));
if (!approved) {
messages.push({ role: 'user', content: 'User rejected this action. Try alternative.' });
continue;
}
}
เมื่อไหร่ควรใช้ Agent
| สถานการณ์ | ใช้ Agent? |
|---|---|
| งานที่ขั้นตอนรู้ล่วงหน้าทั้งหมด | ❌ ใช้ pipeline แทน |
| งานที่ต้องตัดสินใจตามข้อมูลที่ได้ | ✓ |
| งานที่ต้องวนซ้ำหลายรอบ | ✓ |
| งาน 1 ขั้นตอนตรงๆ | ❌ ใช้ single LLM call |
| งานที่ error cost สูงมาก | ⚠️ ต้องมี human review |