{"slug": "ai-sdk-asun-p-ur-agent-ttnny-cheaak-kh-ng-tutorial", "title": "AI SDK အသုံးပြု၍ Agent တည်ဆောက်ခြင်း - Tutorial", "summary": "A developer published a tutorial on building AI agents using TypeScript, Vercel AI SDK, and OpenRouter. The tutorial covers creating agents with tools, memory, subagents, and sequential/parallel execution. It provides step-by-step code examples for setting up a project with OpenRouter API and TypeScript.", "body_md": "ဒီ သင်ခန်းစာမှာ TypeScript၊ Vercel AI SDK နဲ့ OpenRouter တို့ကို အသုံးပြုပြီး AI Agent တစ်ခုကို အတူတူ တည်ဆောက်ကြည့်ကြပါမယ်။\n\nသင်ခန်းစာ ပြီးဆုံးသွားတဲ့အခါ -\n\n- Language model ခေါ်ယူခြင်း၊\n- Agent Tool ဖန်တီးခြင်း၊\n- Agent Tool အသုံးပြုခြင်း၊\n- Agent Loop ဖန်တီးခြင်း၊\n- Memory စနစ် ထည့်သွင်းခြင်း၊\n- Subagent တည်ဆောက်ခြင်း၊\n- Sequential Agents အကြောင်းနဲ့\n- Parallel Agents အကြောင်းတို့ကို\n\nသိရှိသွားမှာပဲ ဖြစ်ပါတယ်။ အခြေခံအဆင့်တွေပဲ ဖြစ်လို့ Database တွေ၊ Vector Search တွေ၊ Web UI တွေ မပါသေးပါဘူး။\n\nပထမဆုံးအနေနဲ့ Agent ဆိုတာဘာလဲ၊ ဒီလို အကျဉ်းချုပ်မှတ်ပါ။\n\nAgent ဆိုတာ ဘာလဲ?Agent ဆိုတာ AI Model တစ်ခုနဲ့အတူ ပေးထားတဲ့ Tool တွေကို ပေါင်းစပ် အသုံးပြုပြီး အဖြေတစ်ခု ထွက်လာတဲ့အထိ အဆင့်ဆင့် လုပ်ဆောင်သွားနိုင်တဲ့ ကွန်ပျူတာပရိုဂရမ်တစ်ခု ဖြစ်ပါတယ်။\n\nအရင်ဆုံး မိမိနှစ်သက်ရာနေရာမှာ ပရောဂျက်တစ်ခု တည်ဆောက်ပါ။ package.json ဖိုင်တစ်ခုလည်း တည်ဆောက်လိုက်ပါ။ ဥပမာ -\n\n```\nmkdir my-agent\ncd my-agent\n\nnpm init -y\n```\n\nဆက်လက်ပြီး လိုအပ်တဲ့ Package တွေကို Install လုပ်ပါ -\n\n```\nnpm install ai @openrouter/ai-sdk-provider zod dotenv\n```\n\nအဓိကနည်းပညာအဖြစ် အသုံးပြုလိုတဲ့ Vercel AI SDK နဲ့ OpenRouter Provider တို့ကို ထည့်သွင်းလိုက်တာပါ။ နောက်ထပ် လိုအပ်တဲ့ Development Dependencies တွေကိုလည်း ထပ်ပြီး Install လုပ်ပါ -\n\n```\nnpm install -D typescript tsx @types/node\n```\n\nTypeScript ကို အသုံးပြုရေးသားမှာဖြစ်လို့ သက်ဆိုင်တာတွေ ထည့်သွင်းလိုက်တာပါ။\n\nOpenRouter အတွက် API Key လိုအပ်ရင် ဒီလိပ်စာမှာ ရယူလို့ရပါတယ်။\n\nဆက်လက်ပြီး ပရောဂျက်မှာ ပါဝင်မည့်ဖိုင်တွေ အပြည့်အစုံနဲ့ အခုလို Folder Structure တစ်ခုကို တည်ဆောက်လိုက်ပါ -\n\n```\nmy-agent/\n├── src/\n│   ├── 01-basic.ts\n│   ├── 02-tool.ts\n│   ├── 03-agent-loop.ts\n│   ├── 04-memory.ts\n│   ├── 05-subagent.ts\n│   ├── 06-sequential.ts\n│   └── 07-parallel.ts\n├── .env\n├── .gitignore\n├── package.json\n└── tsconfig.json\n```\n\nTypeScript နဲ့ပတ်သက်ပြီး လိုအပ်တာတွေ အသင့်ဖြစ်သွားအောင် `tsconfig.json`\n\nဖိုင်ထဲမှာ အောက်ပါအတိုင်း ရေးသားပေးပါ -\n\n```\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"types\": [\"node\"],\n    \"strict\": true,\n    \"esModuleInterop\": true\n  },\n  \"include\": [\"src\"]\n}\n```\n\n`package.json`\n\nဖိုင်ထဲမှာ `scripts`\n\nတွေကို အခုလို ကြိုတင်ထည့်သွင်းထားလိုက်ပါ။ ကျန်တာတွေက ပြင်စရာမလိုပါဘူး၊ အသင့်ကူးယူလို့ရအောင်သာ အစုံထည့်ပေးလိုက်တာပါ -\n\n```\n{\n  \"name\": \"my-agent\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"basic\": \"tsx src/01-basic.ts\",\n    \"tool\": \"tsx src/02-tool.ts\",\n    \"loop\": \"tsx src/03-agent-loop.ts\",\n    \"memory\": \"tsx src/04-memory.ts\",\n    \"subagent\": \"tsx src/05-subagent.ts\",\n    \"sequential\": \"tsx src/06-sequential.ts\",\n    \"parallel\": \"tsx src/07-parallel.ts\",\n    \"check\": \"tsc --noEmit\"\n  },\n  \"dependencies\": {\n    \"@openrouter/ai-sdk-provider\": \"latest\",\n    \"ai\": \"latest\",\n    \"dotenv\": \"latest\",\n    \"zod\": \"latest\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"latest\",\n    \"tsx\": \"latest\",\n    \"typescript\": \"latest\"\n  }\n}\n```\n\n`.env`\n\nဖိုင်ထဲမှာ OpenRouter API Key နဲ့ အသုံးပြုလိုတဲ့ Model တို့ကို အောက်ပါအတိုင်း ထည့်သွင်းပါမယ် -\n\n```\nOPENROUTER_API_KEY=your-openrouter-api-key\nOPENROUTER_MODEL=xiaomi/mimo-v2.5\n```\n\nနမူနာမှာ `xiaomi/mimo-v2.5`\n\nကို Model အနေနဲ့ ရွေးချယ်ထားပြီး၊ အခြားနှစ်သက်ရာ Model ကို အစားထိုးရွေးချယ်နိုင်ပါတယ်။ အခမဲ့ရတဲ့ Model တွေ သုံးပြီး စမ်းလို့လည်း ရပါတယ်။ ကိုယ်ရွေးချယ်တဲ့ Model က Tool Calling ရတဲ့ Model ဖြစ်ရမယ်ဆိုတာကိုတော့ သတိပြုပါ။\n\n`.gitignore`\n\nဖိုင်ထဲမှာလည်း အခုလို ရေးသားပေးပါ၊ မဖြစ်မနေ လိုအပ်ချက်မဟုတ်ပေမဲ့ `.env`\n\nလိုဖိုင်မျိုးတွေ မျှဝေတဲ့အခါ ပါမသွားစေဖို့ပါ -\n\n```\nnode_modules\ndist\n.env\n```\n\nပထမဆုံးကုဒ်အနေနဲ့ `src/01-basic.ts`\n\nဖိုင်ထဲမှာ အောက်ပါအတိုင်း ရေးပါမယ် -\n\n``` js\nimport \"dotenv/config\";\n\nimport { generateText } from \"ai\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n\nconst apiKey = process.env.OPENROUTER_API_KEY;\nconst modelName = process.env.OPENROUTER_MODEL;\n\nif (!apiKey) {\n  throw new Error(\"OPENROUTER_API_KEY is missing.\");\n}\n\nif (!modelName) {\n  throw new Error(\"OPENROUTER_MODEL is missing.\");\n}\n\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n\nconst model = openrouter(modelName);\n\nconst result = await generateText({\n  model,\n  prompt: \"Explain what an AI agent is in two simple sentences.\",\n});\n\nconsole.log(result.text);\n```\n\nရေးပြီးသွားရင် Terminal ကနေ အောက်ပါအတိုင်း Run ပြီး စမ်းကြည့်လို့ ရပါပြီ။ လိုအပ်တဲ့ NPM Script ကို စောစောက ကြိုထည့်ခဲ့ပြီးသားပါ -\n\n```\nnpm run basic\n```\n\nဒီကုဒ်လေးက OpenRouter provider တစ်ခုကို တည်ဆောက်လိုက်တာ ဖြစ်ပါတယ် -\n\n``` js\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n```\n\nဒီကုဒ်ကတော့ အသုံးပြုလိုတဲ့ model ကို ရွေးချယ်လိုက်တာပါ -\n\n``` js\nconst model = openrouter(modelName);\n```\n\nModel ဆီကို request လှမ်းပို့တဲ့အခါ အခုလို ပို့ရပါတယ် -\n\n``` js\nconst result = await generateText({\n  model,\n  prompt: \"...\",\n});\n```\n\nနောက်ဆုံးမှာ Model ဆီကနေ ရလာတဲ့ ရလဒ်ကို Console မှာပဲ ပြပေးလိုက်တာ ဖြစ်ပါတယ် -\n\n```\nconsole.log(result.text);\n```\n\n`generateText()`\n\nfunction ကို အဓိကအားဖြင့် စာသားတွေ ထုတ်ခိုင်းဖို့ သုံးတာ ဖြစ်ပါတယ်။ Streaming လို လုပ်ဆောင်ချက်တွေ ထည့်သုံးမထားလို့၊ ရလဒ်ကို တစ်လုံးချင်းပြန်ထုတ်ပေးတာမျိုး မဟုတ်ဘဲ အားလုံးပြီးမှ တစ်ခါတည်း ပေးထားတာ ဖြစ်ပါတယ်။\n\nအခုအဆင့်က Agent မဟုတ်သေးပါဘူး။ Model Request တစ်ခုသာ ရှိပါသေးတယ်။ သူ့ရဲ့ Flow က အောက်ပါအတိုင်း ဖြစ်ပါတယ် -\n\n```\nProgram\n  ↓\nPrompt\n  ↓\nModel\n  ↓\nText response\n```\n\nTool ဆိုတာ Model က လှမ်းခေါ်ခွင့် ပြုထားတဲ့ ရိုးရိုး function တစ်ခုသာ ဖြစ်ပါတယ်။ အဓိကအားဖြင့် အစိတ်အပိုင်း ၃ ခု ပါဝင်ပါတယ် -\n\n- Description\n- Input Schema\n- Execution Function\n\nSchema နဲ့ Model ထည့်ပေးရမဲ့ Arguments သတ်မှတ်ပါတယ်။ Model က ပြန်ပေးတဲ့ arguments တွေ မှန်/မမှန်ကိုလည်း အလုပ်မလုပ်ခင် ဒီ Schema နဲ့ပဲ စစ်ဆေးပေးပါတယ်။\n\nနမူနာအနေနဲ့ အလွန်ရိုးရှင်းလွယ်ကူတဲ့ Calculator Tool လေးတစ်ခုလောက် လုပ်ကြပါမယ်။ `src/02-tool.ts`\n\nဖိုင်မှာ အောက်ပါအတိုင်း ရေးသား လိုက်ပါ -\n\n``` js\nimport \"dotenv/config\";\n\nimport { generateText, tool } from \"ai\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\nimport { z } from \"zod\";\n\nconst apiKey = process.env.OPENROUTER_API_KEY;\nconst modelName = process.env.OPENROUTER_MODEL;\n\nif (!apiKey || !modelName) {\n  throw new Error(\n    \"OPENROUTER_API_KEY and OPENROUTER_MODEL must be configured.\",\n  );\n}\n\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n\nconst model = openrouter(modelName);\n\nconst calculatorTool = tool({\n  description:\n    \"Perform basic arithmetic using two numbers. Use this instead of calculating mentally.\",\n\n  inputSchema: z.object({\n    operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n    a: z.number(),\n    b: z.number(),\n  }),\n\n  execute: async ({ operation, a, b }) => {\n    switch (operation) {\n      case \"add\":\n        return {\n          result: a + b,\n        };\n\n      case \"subtract\":\n        return {\n          result: a - b,\n        };\n\n      case \"multiply\":\n        return {\n          result: a * b,\n        };\n\n      case \"divide\":\n        if (b === 0) {\n          return {\n            error: \"Cannot divide by zero.\",\n          };\n        }\n\n        return {\n          result: a / b,\n        };\n    }\n  },\n});\n\nconst result = await generateText({\n  model,\n\n  prompt:\n    \"Use the calculator to multiply 37 by 14. Do not calculate it yourself.\",\n\n  tools: {\n    calculator: calculatorTool,\n  },\n});\n\nconsole.log(\"Text:\");\nconsole.log(result.text);\n\nconsole.log(\"\\nTool calls:\");\nconsole.dir(result.toolCalls, {\n  depth: null,\n});\n\nconsole.log(\"\\nTool results:\");\nconsole.dir(result.toolResults, {\n  depth: null,\n});\n```\n\nရေးပြီးသွားရင် အခုလို Run ပြီး စမ်းကြည့်လို့ ရနေပါပြီ -\n\n```\nnpm run tool\n```\n\nModel က ခေါ်ယူအသုံးပြုလို့ရမယ့် Tool ရဲ့ အမည် အခုလို သတ်မှတ်ပေးပါတယ် -\n\n```\ntools: {\n  calculator: calculatorTool,\n}\n```\n\nDescription ကို ကြည့်ပြီး Model က ဒီ tool ကို ဘယ်အချိန်မှာ သုံးသင့်လဲဆိုတာ အလိုအလျှောက် ဆုံးဖြတ်သွားမှာပါ၊ ဒါကြောင့် ကိုယ့် tool အကြောင်းကို သေချာရှင်းပြထားရမှာ ဖြစ်ပါတယ် -\n\n```\ndescription:\n  \"Perform basic arithmetic using two numbers...\"\n```\n\nInput schema ကတော့ အထက်မှာ ပြောခဲ့သလို ဘယ်လို input မျိုး လက်ခံမလဲဆိုတာ စစ်ဆေးပေးပါတယ် -\n\n```\ninputSchema: z.object({\n  operation: z.enum([\n    \"add\",\n    \"subtract\",\n    \"multiply\",\n    \"divide\",\n  ]),\n  a: z.number(),\n  b: z.number(),\n})\n```\n\nExecution function ကတော့ ပုံမှန် TypeScript function code ပါပဲ -\n\n``` js\nexecute: async ({ operation, a, b }) => {\n  // deterministic application code\n}\n```\n\nModel က ဒီ function ကို သူကိုယ်တိုင် တိုက်ရိုက်ဝင် run တာတော့ မဟုတ်ပါဘူး။ လုပ်ငန်းစဉ်က အောက်ပါအတိုင်း သွားတာပါ -\n\n```\n1. Model က calculator ကိုခေါ်ဖို့ တောင်းဆိုတယ်။\n2. AI SDK က arguments တွေကို စစ်ဆေးတယ်။\n3. AI SDK က calculatorTool.execute() ကို run ပေးတယ်။\n4. AI SDK က ရလာတဲ့ tool ရလဒ်ကို Model ဆီ ပြန်ပို့ပေးပါတယ်။\n```\n\nဒီနည်းနဲ့ Model က ခေါ်ချင်တဲ့ Tool ကို ပြန်ပေးပြီး SDK က တစ်ကယ်ခေါ် အလုပ်လုပ်ပြီး ရလဒ်ကို Model ထံ ပြန်ပေးလိုက်တာ ဖြစ်ပါတယ်။\n\nစမ်းကြည့်တဲ့အခါ Tool ရလဒ် ထွက်လာပေမယ့် အဖြေ ပြန်မရတာမျိုး ကြုံရနိုင်ပါတယ်။ Model က အလုပ်လုပ်ပုံက Tool ကို လှမ်းခေါ်ဖို့ တောင်းဆိုလိုက်တာနဲ့တင် ပြီးဆုံးသွားလို့ ဖြစ်ပါတယ်။\n\n```\nModel request\n  ↓\nTool call\n  ↓\nTool executes\n  ↓\nGeneration ends\n```\n\nModel အနေနဲ့ ရလာတဲ့ Tool ရလဒ်ကို ကြည့်ပြီး ဆက်အလုပ်လုပ်ခွင့် မရလိုက်ပါဘူး။ ဒါကြောင့် Agent Loop တစ်ခု လိုအပ်လာတာ ဖြစ်ပါတယ်။\n\nAgent Loop တစ်ခု စမ်းသပ်တည်ဆောက်ကြည့်ဖို့အတွက် `src/03-agent-loop.ts`\n\nဖိုင်ထဲမှာ အောက်ပါအတိုင်း ရေးလိုက်ပါ -\n\n``` js\nimport \"dotenv/config\";\n\nimport {\n  generateText,\n  stepCountIs,\n  tool,\n} from \"ai\";\n\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\nimport { z } from \"zod\";\n\nconst apiKey = process.env.OPENROUTER_API_KEY;\nconst modelName = process.env.OPENROUTER_MODEL;\n\nif (!apiKey || !modelName) {\n  throw new Error(\n    \"OPENROUTER_API_KEY and OPENROUTER_MODEL must be configured.\",\n  );\n}\n\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n\nconst model = openrouter(modelName);\n\nconst calculatorTool = tool({\n  description: \"Perform basic arithmetic accurately.\",\n\n  inputSchema: z.object({\n    operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n    a: z.number(),\n    b: z.number(),\n  }),\n\n  execute: async ({ operation, a, b }) => {\n    console.log(`Executing: ${operation}(${a}, ${b})`);\n\n    switch (operation) {\n      case \"add\":\n        return { result: a + b };\n\n      case \"subtract\":\n        return { result: a - b };\n\n      case \"multiply\":\n        return { result: a * b };\n\n      case \"divide\":\n        if (b === 0) {\n          return { error: \"Division by zero is not allowed.\" };\n        }\n\n        return { result: a / b };\n    }\n  },\n});\n\nconst result = await generateText({\n  model,\n\n  system: `\nYou are a careful assistant.\n\nUse the calculator whenever arithmetic is needed.\nAfter using a tool, explain the result clearly.\n`,\n\n  prompt: `\nA shop sold 18 boxes.\nEach box contained 24 books.\nThen 35 books were returned.\n\nHow many books remained sold?\n`,\n\n  tools: {\n    calculator: calculatorTool,\n  },\n\n  stopWhen: stepCountIs(5),\n});\n\nconsole.log(\"\\nFinal answer:\");\nconsole.log(result.text);\n\nconsole.log(\"\\nNumber of steps:\");\nconsole.log(result.steps.length);\n\nfor (const [index, step] of result.steps.entries()) {\n  console.log(`\\nStep ${index + 1}`);\n\n  console.log(\"Text:\");\n  console.log(step.text || \"(no text)\");\n\n  console.log(\"Tool calls:\");\n  console.dir(step.toolCalls, {\n    depth: null,\n  });\n\n  console.log(\"Tool results:\");\n  console.dir(step.toolResults, {\n    depth: null,\n  });\n}\n```\n\nပြီးတဲ့အခါ အခုလို Run ကြည့်လိုက်ပါ -\n\n```\nnpm run loop\n```\n\nModel က Tool ကို အသုံးပြုပြီး နောက်ဆုံးရလဒ်ထွက်တဲ့အထိ အလုပ်လုပ်သွားတာကို တွေ့ရမှာပဲ ဖြစ်ပါတယ်။\n\nအထက်က Agent Loop ကုဒ်မှာ ဒီပိုင်းက အဓိက ဖြစ်ပါတယ် -\n\n```\nstopWhen: stepCountIs(5)\n```\n\nသူက SDK ကို Tool အလုပ်လုပ်လို့ ပြီးသွားရင်လည်း ရပ်မပစ်ဘဲ သတ်မှတ်ထားတဲ့ အကြိမ်ရေအထိ ဆက်ပြီး loop ပတ်ခိုင်းလိုက်တာ ဖြစ်ပါတယ်။ လုပ်ငန်းစဉ်က အောက်ပါအတိုင်း ဖြစ်သွားပါမယ် -\n\n```\nStep 1:\nModel က multiply(18, 24) ကို လှမ်းခေါ်ပါတယ်။\n\nStep 2:\nModel က ရလဒ် 432 ကို လက်ခံရရှိပြီး subtract(432, 35) ကို ထပ်ခေါ်ပါတယ်။\n\nStep 3:\nModel က ရလဒ် 397 ကို လက်ခံရရှိပြီး နောက်ဆုံးအဖြေကို ပြန်ပေးသွားမှာပါ။\n```\n\n`stopWhen`\n\nကြောင့် SDK က Tool ကို run တယ်၊ ရလဒ်ကို model ဆီ ပြန်ပေးပါတယ်၊ ပြီးတော့ Model က အဖြေထုတ်ပေးနိုင်တဲ့အထိ ဆက်တိုက် အလုပ်လုပ်သွားပါတယ်။ `stepCountIs(5)`\n\nလို့ ကန့်သတ်ထားလိုက်တာက အဆုံးမရှိ loop ပတ် မနေအောင် ကာကွယ်ပေးတာ ဖြစ်ပါတယ်။\n\nဒါဟာ ကျွန်တော်တို့ရဲ့ ပထမဆုံး တကယ့် Agent တစ်ခုပဲ ဖြစ်ပါတယ် -\n\n```\nUser task\n  ↓\nModel decides action\n  ↓\nTool executes\n  ↓\nResult returns to model\n  ↓\nModel decides next action\n  ↓\nFinal answer\n```\n\nကျွန်တော်တို့ရဲ့ Agent မှာ အဓိကအကျဆုံး အစိတ်အပိုင်း ၄ ခု ပါဝင်တာကို နောက်တစ်ကြိမ်လောက် သတိပြုကြည့်လိုက်ပါ -\n\n```\n1. Model\n2. Instructions\n3. Tools\n4. Loop\n```\n\nCode အနေနဲ့ အောက်ပါအတိုင်း ဖြစ်ပါတယ် -\n\n```\ngenerateText({\n  model,\n  system,\n  prompt,\n  tools,\n  stopWhen,\n});\n```\n\nဒီနေရာမှာ Memory ဆိုတာ မှတ်တမ်းတွေကို ယာယီသိမ်းဆည်းထားခြင်းသာ ဖြစ်ပါတယ်။ ဒါကြောင့် Program ပိတ်လိုက်ရင် ပျောက်သွားမှာဖြစ်ပြီး Database တွေဘာတွေနဲ့ သိမ်းထားတာ မဟုတ်ပါဘူး။\n\nကျွန်တော်တို့ လုပ်မှာက User နဲ့ Model ကြားထဲက အပြန်အလှန် ဆက်သွယ် အလုပ်လုပ်ထားတဲ့ အချက်အလက်တွေကို ခပ်ရိုးရိုးပဲ Array တစ်ခုနဲ့ သိမ်းထားလိုက်မှာ ဖြစ်ပါတယ်။\n\nနမူနာစမ်းကြည့်ဖို့အတွက် `src/04-memory.ts`\n\nဖိုင်မှာ အခုလိုရေးသားပေးပါ -\n\n``` js\nimport \"dotenv/config\";\n\nimport { createInterface } from \"node:readline/promises\";\nimport { stdin as input, stdout as output } from \"node:process\";\n\nimport {\n  generateText,\n  stepCountIs,\n  tool,\n  type ModelMessage,\n} from \"ai\";\n\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\nimport { z } from \"zod\";\n\nconst apiKey = process.env.OPENROUTER_API_KEY;\nconst modelName = process.env.OPENROUTER_MODEL;\n\nif (!apiKey || !modelName) {\n  throw new Error(\n    \"OPENROUTER_API_KEY and OPENROUTER_MODEL must be configured.\",\n  );\n}\n\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n\nconst model = openrouter(modelName);\n\nconst calculatorTool = tool({\n  description: \"Perform basic arithmetic accurately.\",\n\n  inputSchema: z.object({\n    operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n    a: z.number(),\n    b: z.number(),\n  }),\n\n  execute: async ({ operation, a, b }) => {\n    switch (operation) {\n      case \"add\":\n        return { result: a + b };\n\n      case \"subtract\":\n        return { result: a - b };\n\n      case \"multiply\":\n        return { result: a * b };\n\n      case \"divide\":\n        if (b === 0) {\n          return { error: \"Cannot divide by zero.\" };\n        }\n\n        return { result: a / b };\n    }\n  },\n});\n\nconst memory: ModelMessage[] = [];\n\nasync function runAgent(userText: string): Promise<string> {\n  memory.push({\n    role: \"user\",\n    content: userText,\n  });\n\n  const result = await generateText({\n    model,\n\n    system: `\nYou are a helpful assistant with access to a calculator.\nUse previous messages to understand references such as\n\"it\", \"that number\" and \"my name\".\n`,\n\n    messages: memory,\n\n    tools: {\n      calculator: calculatorTool,\n    },\n\n    stopWhen: stepCountIs(5),\n  });\n\n  memory.push({\n    role: \"assistant\",\n    content: result.text,\n  });\n\n  return result.text;\n}\n\nconst readline = createInterface({\n  input,\n  output,\n});\n\nconsole.log('Type \"exit\" to stop.');\n\ntry {\n  while (true) {\n    const userText = await readline.question(\"\\nYou: \");\n\n    if (userText.trim().toLowerCase() === \"exit\") {\n      break;\n    }\n\n    if (!userText.trim()) {\n      continue;\n    }\n\n    const answer = await runAgent(userText);\n\n    console.log(`Agent: ${answer}`);\n  }\n} finally {\n  readline.close();\n}\n```\n\nပြီးတဲ့အခါ အခုလို Run ကြည့်လို့ ရပါပြီ -\n\n```\nnpm run memory\n```\n\nအောက်ပါအတိုင်း Chat ပုံစံ စကားပြောကြည့်ပြီး စမ်းသပ်လိုက်ပါ -\n\n```\nYou: Hello, how can you assist me today?\nYou: Calculate 18 times 7.\nYou: Add 20 to that number.\n```\n\nပထမဆုံး အောက်ပါအတိုင်း Array တစ်ခုကို တည်ဆောက်ထားပါတယ် -\n\n``` js\nconst memory: ModelMessage[] = [];\n```\n\nModel ဆီ မပို့ခင် User ရဲ့ Prompt ကို Array ထဲမှာ ထည့်သွင်းပါတယ် -\n\n```\nmemory.push({\n  role: \"user\",\n  content: userText,\n});\n```\n\nပြီးရင် Model messages နေရာမှာ Array ထဲက သိမ်းထားသမျှ အကုန်ထည့်ပေးလိုက်ပါတယ် -\n\n```\nmessages: memory\n```\n\nမော်ဒယ်ဆီက အဖြေရလာတော့လည်း အလားတူ Array ထဲမှာ ထပ်တိုးပြီး မှတ်ခိုင်းပါတယ် -\n\n```\nmemory.push({\n  role: \"assistant\",\n  content: result.text,\n});\n```\n\nအခုလိုပုံစံဖြစ်မှာပါ -\n\n```\nRequest 1:\n[user message 1]\n\nRequest 2:\n[user message 1]\n[assistant response 1]\n[user message 2]\n\nRequest 3:\n[user message 1]\n[assistant response 1]\n[user message 2]\n[assistant response 2]\n[user message 3]\n```\n\nကြာလာတာနဲ့အမျှ Array က တဖြည်းဖြည်း ကြီးမားလာမှာ ဖြစ်လို့ `trimMemory`\n\nfunction ထည့်သွင်းပြီး မှတ်တမ်း အဟောင်းတွေကို ဖြတ်ထုတ်နိုင်ပါတယ် -\n\n```\nfunction trimMemory(maxMessages: number): void {\n  if (memory.length > maxMessages) {\n    memory.splice(0, memory.length - maxMessages);\n  }\n}\n```\n\nမော်ဒယ်ဆီ မပို့ခင် `trimMemory`\n\nကို လှမ်းခေါ်ပေးလိုက်ရုံပါပဲ -\n\n```\nasync function runAgent(userText: string): Promise<string> {\n  memory.push({\n    role: \"user\",\n    content: userText,\n  });\n\n  trimMemory(10);\n\n  const result = await generateText({\n    // ...\n  });\n\n  memory.push({\n    role: \"assistant\",\n    content: result.text,\n  });\n\n  return result.text;\n}\n```\n\nဒါက အခြေခံအကျဆုံး Context management နည်းလမ်းလေးတစ်ခုကို တစ်ခါတည်း ထည့်ကြည့်လိုက်တဲ့ သဘောပါ။\n\nSubagent ဆိုတာ ပင်မအလုပ်ကနေ ခွဲထုတ်ပြီး သီးခြားအလုပ်လုပ်ခိုင်းလိုက်တဲ့ သီးခြား Specialist အေးဂျင့်လေးတွေ ဖြစ်ပါတယ်။\n\nနမူနာမှာတော့ -\n\n- Research Subagent ခေါ် အချက်အလက်တွေကို စုဆောင်းပေးမယ့် Agent တစ်ခုနဲ့၊\n- Writer Agent ခေါ် ရလာတဲ့ အချက်အလက်တွေကို သေသေချာချာ ပြန်ရေးပေးတဲ့ Agent တို့ကို လုပ်ကြည့်ကြပါမယ်။\n\n`src/05-subagent.ts`\n\nဖိုင်မှာ အခုလိုရေးပေးလိုက်ပါ -\n\n``` js\nimport \"dotenv/config\";\n\nimport { generateText } from \"ai\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n\nconst apiKey = process.env.OPENROUTER_API_KEY;\nconst modelName = process.env.OPENROUTER_MODEL;\n\nif (!apiKey || !modelName) {\n  throw new Error(\n    \"OPENROUTER_API_KEY and OPENROUTER_MODEL must be configured.\",\n  );\n}\n\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n\nconst model = openrouter(modelName);\n\nasync function researchAgent(topic: string): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nYou are a research assistant.\n\nYour job is to identify:\n1. The central idea\n2. Important supporting points\n3. Common misunderstandings\n\nDo not write a polished article.\nReturn concise research notes.\n`,\n\n    prompt: `Research this topic: ${topic}`,\n  });\n\n  return result.text;\n}\n\nasync function writerAgent(\n  topic: string,\n  researchNotes: string,\n): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nYou are a teacher.\n\nTurn supplied research notes into a clear beginner explanation.\nDo not claim that the notes were externally verified.\nUse a simple example.\n`,\n\n    prompt: `\nTopic:\n${topic}\n\nResearch notes:\n${researchNotes}\n`,\n  });\n\n  return result.text;\n}\n\nasync function main(): Promise<void> {\n  const topic = \"Why AI agents need tools\";\n\n  console.log(\"Running research subagent...\\n\");\n\n  const notes = await researchAgent(topic);\n\n  console.log(\"Research notes:\");\n  console.log(notes);\n\n  console.log(\"\\nRunning writer agent...\\n\");\n\n  const article = await writerAgent(topic, notes);\n\n  console.log(\"Final explanation:\");\n  console.log(article);\n}\n\nawait main();\n```\n\nပြီးတဲ့အခါ အခုလို Run ကြည့်လို့ ရပါပြီ -\n\n```\nnpm run subagent\n```\n\nResearch agent မှာ ကိုယ်ပိုင် Instruction နဲ့ ရလဒ်တွေ ရှိပါတယ်။ ပင်မ Agent က အဲ့ဒီ ရလဒ်ကို ယူပြီး -\n\n``` js\nconst notes = await researchAgent(topic);\n```\n\nနောက် Agent တစ်ခုဆီ အခုလို လွှဲပေးလိုက်တာပါ -\n\n``` js\nconst article = await writerAgent(topic, notes);\n```\n\nဖွဲ့စည်းပုံက အောက်ပါအတိုင်း ဖြစ်ပါတယ် -\n\n```\nParent agent\n    │\n    ├── Research subagent\n    │        ↓\n    │    Research notes\n    │\n    └── Writer agent\n            ↓\n        Final answer\n```\n\nSubagent ဆိုတာ ဒီလိုမျိုး သီးခြားအလုပ်လုပ်နိုင်တဲ့ အစိတ်အပိုင်းလေးတွေပဲ ဖြစ်ပါတယ်။ ဒီအစိတ်အပိုင်းလေးတွေကို အဆင့်လိုက် Sequential တစ်ခုပြီးတစ်ခု လုပ်အောင် စီစဉ်ထားလို့ရသလို၊ Parallel ပြိုင်တူလုပ်အောင်လည်း စီစဉ်ထားလို့ ရပါတယ်။\n\nSequential workflow ဆိုတာ အလုပ်တစ်ခုပြီးမှ နောက်အလုပ်တစ်ခုကို အဆင့်ဆင့် လက်ဆင့်ကမ်း လုပ်သွားတဲ့ အလုပ်တွေ ဖြစ်ပါတယ် -\n\nဒီနေရာမှာ အစီအစဉ်က အရေးကြီးပါတယ်။ ကျွန်တော်တို့ နမူနာ လုပ်မယ့် Sequential အစီအစဉ်ကတော့ -\n\n၁။ Outline ထုတ်မယ်။ ၂။ Review စစ်မယ်။ ၃။ သင်ခန်းစာ ရေးမယ်။\n\nဆိုတဲ့အဆင့်တွေပဲ ဖြစ်ပါတယ်။\n\nနမူနာအနေနဲ့ `src/06-sequential.ts`\n\nမှာ အခုလို ရေးပေးပါ -\n\n``` js\nimport \"dotenv/config\";\n\nimport { generateText } from \"ai\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n\nconst apiKey = process.env.OPENROUTER_API_KEY;\nconst modelName = process.env.OPENROUTER_MODEL;\n\nif (!apiKey || !modelName) {\n  throw new Error(\n    \"OPENROUTER_API_KEY and OPENROUTER_MODEL must be configured.\",\n  );\n}\n\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n\nconst model = openrouter(modelName);\n\nasync function createOutline(topic: string): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nCreate a short beginner lesson outline.\nReturn only the outline.\n`,\n\n    prompt: topic,\n  });\n\n  return result.text;\n}\n\nasync function reviewOutline(\n  topic: string,\n  outline: string,\n): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nYou are an educational editor.\n\nReview the supplied outline.\nFix unclear ordering and remove unnecessary complexity.\nReturn the improved outline only.\n`,\n\n    prompt: `\nTopic:\n${topic}\n\nOutline:\n${outline}\n`,\n  });\n\n  return result.text;\n}\n\nasync function writeLesson(\n  topic: string,\n  approvedOutline: string,\n): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nWrite a concise beginner lesson based strictly on the supplied outline.\nInclude one practical analogy.\n`,\n\n    prompt: `\nTopic:\n${topic}\n\nApproved outline:\n${approvedOutline}\n`,\n  });\n\n  return result.text;\n}\n\nasync function main(): Promise<void> {\n  const topic = \"How an AI agent loop works\";\n\n  console.log(\"Step 1: Creating outline\");\n  const outline = await createOutline(topic);\n\n  console.log(\"\\nStep 2: Reviewing outline\");\n  const reviewedOutline = await reviewOutline(topic, outline);\n\n  console.log(\"\\nStep 3: Writing lesson\");\n  const lesson = await writeLesson(topic, reviewedOutline);\n\n  console.log(\"\\nInitial outline:\");\n  console.log(outline);\n\n  console.log(\"\\nReviewed outline:\");\n  console.log(reviewedOutline);\n\n  console.log(\"\\nFinal lesson:\");\n  console.log(lesson);\n}\n\nawait main();\n```\n\nပြီးတဲ့အခါ အခုလို Run ကြည့်လိုက်ပါ -\n\n```\nnpm run sequential\n```\n\nလုပ်ရမယ့် အစီအစဉ်အဆင့်ဆင့်ကို Model က ဆုံးဖြတ်တာ မဟုတ်ဘဲ ကျွန်တော်တို့ရဲ့ TypeScript code ကပဲ အခုလို ဆုံးဖြတ်ထားတာ သတိပြုပါ -\n\n``` js\nconst outline = await createOutline(topic);\n\nconst reviewedOutline = await reviewOutline(\n  topic,\n  outline,\n);\n\nconst lesson = await writeLesson(\n  topic,\n  reviewedOutline,\n);\n```\n\nဒါဟာ အရေးကြီးတဲ့ ကွဲပြားမှု ဖြစ်ပါတယ် -\n\n```\nAgentic decision:\nModel က သူ ဘယ် Tool ကို သုံးရမလဲဆိုတာ ရွေးချယ်တာ ဖြစ်ပါတယ်။\n\nWorkflow decision:\nProgram က နောက်ထပ် ဘယ်အဆင့်ကို သွားရမလဲဆိုတာ သတ်မှတ်ထားတာ ဖြစ်ပါတယ်။\n```\n\nရှေ့က အလုပ်ရဲ့ ရလဒ်ပေါ် မူတည်ပြီး နောက်တစ်ဆင့်ကို လုပ်ရမယ့် နေရာမျိုးတွေမှာ ဒီလို Sequential workflow တွေက အသုံးဝင်ပါတယ်။\n\nParallel workflow အလုပ်လုပ်ပုံဆိုတာကတော့ အလုပ်တစ်ခုကို တစ်ခုက စောင့်ဆိုင်းနေစရာမလိုဘဲ တစ်ပြိုင်တည်း အလုပ်လုပ်ခြင်း ဖြစ်ပါတယ် -\n\n```\n                  ┌── Explain benefits ──┐\nTopic ────────────┼── Explain risks ─────┼── Combine\n                  └── Give example ──────┘\n```\n\nဒီနမူနာ Flow မှာ Task ၃ ခုလုံးဟာ တစ်ခုရဲ့ အဖြေကို တစ်ခုက စောင့်နေဖို့ မလိုပါဘူး။ ဒါကြောင့် Parallel ပြိုင်တူလုပ်လို့ ရပါတယ်။\n\nနမူနာအနေနဲ့ `src/07-parallel.ts`\n\nဖိုင်မှာ အခုလိုရေးပေးပါ -\n\n``` js\nimport \"dotenv/config\";\n\nimport { generateText } from \"ai\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n\nconst apiKey = process.env.OPENROUTER_API_KEY;\nconst modelName = process.env.OPENROUTER_MODEL;\n\nif (!apiKey || !modelName) {\n  throw new Error(\n    \"OPENROUTER_API_KEY and OPENROUTER_MODEL must be configured.\",\n  );\n}\n\nconst openrouter = createOpenRouter({\n  apiKey,\n});\n\nconst model = openrouter(modelName);\n\nasync function askSpecialist(\n  role: string,\n  task: string,\n): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nYou are the ${role}.\nComplete only your assigned task.\nBe concise and suitable for a beginner.\n`,\n\n    prompt: task,\n  });\n\n  return result.text;\n}\n\nasync function combineResults(\n  topic: string,\n  benefits: string,\n  risks: string,\n  example: string,\n): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nCombine the supplied specialist reports into one coherent explanation.\n\nUse this order:\n1. Main idea\n2. Benefits\n3. Risks\n4. Example\n`,\n\n    prompt: `\nTopic:\n${topic}\n\nBenefits report:\n${benefits}\n\nRisks report:\n${risks}\n\nExample report:\n${example}\n`,\n  });\n\n  return result.text;\n}\n\nasync function main(): Promise<void> {\n  const topic = \"Using AI agents for software development\";\n\n  console.log(\"Running three specialists in parallel...\");\n\n  const [benefits, risks, example] = await Promise.all([\n    askSpecialist(\n      \"benefits analyst\",\n      `Explain the main benefits of ${topic}.`,\n    ),\n\n    askSpecialist(\n      \"risk analyst\",\n      `Explain the main risks and limitations of ${topic}.`,\n    ),\n\n    askSpecialist(\n      \"example designer\",\n      `Create one realistic beginner example of ${topic}.`,\n    ),\n  ]);\n\n  console.log(\"Combining the reports...\\n\");\n\n  const finalAnswer = await combineResults(\n    topic,\n    benefits,\n    risks,\n    example,\n  );\n\n  console.log(\"Benefits:\");\n  console.log(benefits);\n\n  console.log(\"\\nRisks:\");\n  console.log(risks);\n\n  console.log(\"\\nExample:\");\n  console.log(example);\n\n  console.log(\"\\nCombined answer:\");\n  console.log(finalAnswer);\n}\n\nawait main();\n```\n\nပြီးတဲ့အခါ အခုလို Run ကြည့်လိုက်ပါ -\n\n```\nnpm run parallel\n```\n\nSequential တစ်ခုပြီးတစ်ခု အလုပ်လုပ်ပုံက ဒီလိုပါ -\n\n``` js\nconst benefits = await getBenefits();\nconst risks = await getRisks();\nconst example = await getExample();\n```\n\nParallel ပြိုင်တူ အလုပ်လုပ်ပုံက ဒီလိုဖြစ်သွားပါတယ် -\n\n```\nconst [benefits, risks, example] = await Promise.all([\n  getBenefits(),\n  getRisks(),\n  getExample(),\n]);\n```\n\nတချို့နေရာတွေမှာ Sequential နည်းလိုအပ်ပြီး တချို့နေရာတွေမှာ Parallel က အသုံးဝင်မှာပဲ ဖြစ်ပါတယ်။\n\nSubagent တစ်ခုမှာ ကိုယ်ပိုင် Model, Instructions, Tools နဲ့ Loop တွေ ပါဝင်နိုင်ပါတယ်၊ ဒီလိုပါ -\n\n``` js\nasync function mathSubagent(\n  task: string,\n): Promise<string> {\n  const result = await generateText({\n    model,\n\n    system: `\nYou are a mathematics subagent.\nUse the calculator for all arithmetic.\n`,\n\n    prompt: task,\n\n    tools: {\n      calculator: calculatorTool,\n    },\n\n    stopWhen: stepCountIs(5),\n  });\n\n  return result.text;\n}\n```\n\nပင်မ workflow ကနေ သူ့ကို ဒီလို လှမ်းခေါ်ရုံပါပဲ -\n\n``` js\nconst result = await mathSubagent(\n  \"Calculate the total cost of 17 items at $24 each.\",\n);\n```\n\nဖွဲ့စည်းပုံက အောက်ပါအတိုင်း ဖြစ်ပါတယ် -\n\n```\nParent workflow\n    ↓\nMath subagent\n    ↓\nModel\n    ↓\nCalculator tool\n    ↓\nModel\n    ↓\nSubagent result\n    ↓\nParent workflow\n```\n\nဘယ်အချိန်မှာ ဘာတွေခေါ်ပြီး ဘာတွေလုပ်သွားလဲ အဆင့်လိုက် သိရဖို့ဟာ အရေးပါတဲ့ လိုအပ်ချက်တစ်ခုပါ။ ဒါကြောင့် အဲ့ဒီလို လုပ်ဆောင်ချက် ရရှိဖို့ အခုလို Helper function တစ်ခုကို သုံးနိုင်ပါတယ် -\n\n```\nfunction printTrace(result: {\n  text: string;\n  steps: Array<{\n    text: string;\n    toolCalls: unknown[];\n    toolResults: unknown[];\n  }>;\n}): void {\n  console.log(\"\\n=== Final answer ===\");\n  console.log(result.text);\n\n  console.log(\"\\n=== Trace ===\");\n\n  for (const [index, step] of result.steps.entries()) {\n    console.log(`\\nStep ${index + 1}`);\n\n    if (step.text) {\n      console.log(\"Text:\");\n      console.log(step.text);\n    }\n\n    if (step.toolCalls.length > 0) {\n      console.log(\"Tool calls:\");\n      console.dir(step.toolCalls, {\n        depth: null,\n      });\n    }\n\n    if (step.toolResults.length > 0) {\n      console.log(\"Tool results:\");\n      console.dir(step.toolResults, {\n        depth: null,\n      });\n    }\n  }\n}\n```\n\nရလဒ်တွေ ရိုက်ထုတ်တဲ့အခါ အခုလို ခေါ်ယူအသုံးပြုလိုက်ရုံပါပဲ -\n\n``` js\nconst result = await generateText({\n  // ...\n});\n\nprintTrace(result);\nPrompt → Model → Text\nawait generateText({\n  model,\n  prompt,\n});\nPrompt → Model chooses tool → Application executes tool → Tool result\nawait generateText({\n  model,\n  prompt,\n  tools,\n});\nPrompt → Model chooses tool → Tool executes → Result returns to model → Model continues\nawait generateText({\n  model,\n  prompt,\n  tools,\n  stopWhen: stepCountIs(5),\n});\nPrevious messages + Current message → Model\nawait generateText({\n  model,\n  messages: memory,\n});\nParent → Specialized agent → Result returns to parent\njs\nconst notes = await researchAgent(topic);\nA → B → C\njs\nconst a = await taskA();\nconst b = await taskB(a);\nconst c = await taskC(b);\n┌→ A →┐\n├→ B →┼→ Combine\n└→ C →┘\nconst [a, b, c] = await Promise.all([\n  taskA(),\n  taskB(),\n  taskC(),\n]);\n```\n\nဒါက ရိုးရိုး Model call သာ ဖြစ်ပါတယ် -\n\n```\nawait generateText({\n  model,\n  prompt,\n});\n```\n\nဒါမှသာ Agent စနစ် ဖြစ်ပါတယ် -\n\n```\nawait generateText({\n  model,\n  prompt,\n  tools,\n  stopWhen: stepCountIs(5),\n});\n```\n\n**မဖြစ်သင့်သောပုံစံ:** `manageEverything`\n\n**ဖြစ်သင့်သောပုံစံ:** `calculate`\n\n, `getWeather`\n\n, `findCustomer`\n\n, `createInvoice`\n\nTool က သေးပြီး တိကျလေလေ၊ Model အတွက် နားလည်ရလွယ်လေလေ ဖြစ်ပါတယ်။\n\nAI Model တွေဟာ ထုံးစံအတိုင်း ရလဒ်ကို ခန့်မှန်းအလုပ်လုပ်ခြင်းသာ ဖြစ်ပါတယ်။ တိကျမှာ မဟုတ်ပါဘူး။ တိကျဖို့လိုတဲ့ ကိစ္စတွေကို ကုဒ်တွေ Function တွေနဲ့ပဲ တိတိကျကျ လုပ်ပေးရပါတယ်။\n\n``` js\nexecute: async ({ a, b }) => {\n  return {\n    result: a * b,\n  };\n}\n```\n\nအကန့်အသတ်မရှိ ပတ်နေမယ့် loop မျိုးကို ရှောင်ကြရပါမယ်။ အမြဲတမ်း `stopWhen: stepCountIs(5)`\n\nလိုမျိုး ပါအောင် ထည့်ပေးပါ။\n\n``` js\nconst memory: ModelMessage[] = [];\n```\n\nဒီ Memory က program ပိတ်လိုက်ရင် ပျောက်သွားမှာ ဖြစ်ပါတယ်။ ဒါကို အမြဲသုံးဖို့ မသင့်တော်ပါဘူး။ ရေရှည်အတွက်ဆိုရင် ဖိုင် သို့မဟုတ် Database ထဲမှာ သိမ်းဖို့ လိုအပ်ပါတယ်။\n\n**မဖြစ်သင့်သောပုံစံ:**\n\n```\nawait Promise.all([\n  createOutline(),\n  writeArticleUsingOutline(),\n]);\n```\n\n**မှန်ကန်သောပုံစံ:**\n\n``` js\nconst outline = await createOutline();\nconst article = await writeArticleUsingOutline(outline);\n```\n\nတိတိကျကျ အလုပ်လုပ်ပါတယ်ဆိုတဲ့ Tool ရှိနေပေမယ့်လည်း အမြဲတမ်း လက်လွတ်မယုံသင့်ပါဘူး။ Model က parameter အမှားတွေ ထည့်ပေးလိုက်တာမျိုး ဖြစ်နိုင်လို့ လုပ်ဆောင်ချက် အဆင့်ဆင့်ကို အမြဲစစ်ဆေးကြည့်ဖို့ လိုပါတယ်။\n\nဒီအထိ ရသွားပြီးဆိုရင်တော့ Agent တွေကို ကိုယ်တိုင်တည်ဆောက်ဖို့ လိုအပ်တဲ့ အခြေခံလေးတွေ ရရှိသွားပြီ ဖြစ်ပါတယ်။ အသေးစိတ်ကို အောက်ပါ Documentation မှာ ဆက်လက်လေ့လာနိုင်ပါတယ်။\n\nအားလုံးပဲ အဆင်ပြေကြပါစေ။", "url": "https://wpnews.pro/news/ai-sdk-asun-p-ur-agent-ttnny-cheaak-kh-ng-tutorial", "canonical_source": "https://gist.github.com/eimg/3856a76ec56848a0054518b09a1b804f", "published_at": "2026-07-16 09:25:00+00:00", "updated_at": "2026-07-17 05:55:04.332328+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "large-language-models", "artificial-intelligence"], "entities": ["Vercel AI SDK", "OpenRouter", "TypeScript", "xiaomi/mimo-v2.5"], "alternates": {"html": "https://wpnews.pro/news/ai-sdk-asun-p-ur-agent-ttnny-cheaak-kh-ng-tutorial", "markdown": "https://wpnews.pro/news/ai-sdk-asun-p-ur-agent-ttnny-cheaak-kh-ng-tutorial.md", "text": "https://wpnews.pro/news/ai-sdk-asun-p-ur-agent-ttnny-cheaak-kh-ng-tutorial.txt", "jsonld": "https://wpnews.pro/news/ai-sdk-asun-p-ur-agent-ttnny-cheaak-kh-ng-tutorial.jsonld"}}