วิธีสร้าง AI Agents ในปี 2026 (หลักสูตรฉบับเต็ม)

วิธีสร้าง AI Agents ในปี 2026 (หลักสูตรฉบับเต็ม)

@Av1dlive
อังกฤษ4 วันที่ผ่านมา · 12 พ.ค. 2569

AI features

696K
368
68
22
1.2K

TL;DR

เจาะลึกเชิงเทคนิคเกี่ยวกับ agentic-harness runtime พร้อมอธิบายวิธีใช้สถาปัตยกรรม 3 ชั้น (three-layer architecture), remote sandboxes และ context compaction เพื่อสร้าง AI agents ที่มีความเสถียรและพร้อมใช้งานจริงในระดับโปรดักชัน

นี่คือความจริงที่ไม่มีใครบอกนักสร้าง AI

ส่วนใหญ่กำลังสร้างเดโมกันอยู่

สิ่งที่คุณต้องสร้างคือ

เอเจนต์ AI ระดับโปรดักชัน

TLDR; ถ้าคุณไม่อยากอ่าน ให้ลิงก์นี้ไปให้เอเจนต์ของคุณแล้วถามคำถาม: ➡️https://github.com/codejunkie99/agentic-harness

นี่คือทวีตที่เริ่มต้นทุกอย่าง

ปัญหาคือวิศวกร AI ส่วนใหญ่ไม่มีแนวคิดที่ชัดเจนว่าควรสร้างอะไรจริงๆ เมื่อตัดสินใจจริงจังกับเอเจนต์

บางคนหันไปใช้ LangChain เพราะเดโมแบบหลายเอเจนต์ดูสวยบน YouTube แล้วใช้เวลาสองสัปดาห์ถัดไปต่อสู้กับ Python interop และ async runtime mismatch ก่อนจะทิ้งทุกอย่าง

บางคนพยายามสร้าง orchestration layer แบบกำหนดเองตั้งแต่ต้น: loop, session store, context assembler และไม่เคยสร้างเอเจนต์จริงจังเพราะโครงสร้างพื้นฐานกินเวลาไปหมด

บางคนก็คัดลอกตัวอย่าง webhook แบบ hello-world ได้ JSON response กลับมา คิดว่าเข้าใจระบบแล้ว ส่งของที่พังทันทีที่เซสชันทำงานเกินสิบนาที, remote sandbox ล่มกลางคัน, หรือ context window เต็มโดยไม่มีการตั้งค่า compaction

ผลลัพธ์มักจะเหมือนเดิม: งานท่อประปาเยอะ, ไม่มีเอเจนต์โปรดักชัน, และไม่มีโมเดลทางความคิดว่ารันไทม์ของเอเจนต์ระดับโปรดักชันจริงๆ หน้าตาเป็นยังไง

ถ้าเป้าหมายของคุณคือสร้างและส่งเอเจนต์จริงในปี 2026 คุณไม่จำเป็นต้องเรียนรู้หกเฟรมเวิร์ก

คุณต้องเข้าใจรันไทม์เดียวอย่างลึกซึ้งพอที่จะเป็นเจ้าของเอเจนต์โปรดักชันตั้งแต่ handler ไปจนถึง deployment

นั่นหมายถึงการเรียนรู้วิธี:

  • เชื่อมต่อสถาปัตยกรรมสามชั้นเพื่อให้ handler logic ของคุณรอดพ้นจากการเปลี่ยน provider และ target โดยไม่ต้องแตะโค้ดเอเจนต์
  • ใช้ sessions และ tasks อย่างถูกต้องเพื่อให้งานยาวๆ ไม่ปนเปื้อนบริบทของตัวเอง
  • เขียน roles และ skills ที่กำหนดพฤติกรรมของโมเดลโดยไม่ต้องคอมไพล์อะไรใหม่
  • กำหนดค่า compaction เพื่อให้เซสชันที่ทำงานสองชั่วโมงไม่เริ่มหลอนในชั่วโมงแรก
  • ชี้ HttpSessionEnv ไปที่ remote sandboxes เพื่อให้ไบนารีทำงานในเครื่องขณะที่ execution ทำงานบน Linux
  • เลือก build target ที่ถูกต้อง: native, node, หรือ Cloudflare โดยไม่ต้องเขียน agent logic ใหม่ระหว่างกัน
  • สร้าง connectors แทนที่จะเขียน adapters ด้วยมือ และเข้าใจว่าทำไมความแตกต่างนั้นถึงสำคัญภายใต้โหลดจริง

คู่มือนี้เป็นคำอธิบายทางเทคนิคแบบเต็มรูปแบบที่สร้างจาก codebase agentic-harness จริง, หกสัปดาห์ของการสร้างและทำลายเอเจนต์จริงด้วยมัน, และโหมดความล้มเหลวที่ใช้เวลา debug มากที่สุด

ชิ้นนี้มีมากกว่า 4,000 คำ และดึงข้อมูลจาก repo และ docs โดยตรง ไม่ใช่สรุปมือสองหรือตัวอย่างระดับเดโม

แต่คุณค่าที่แท้จริงคือทุกส่วนมี snippet โค้ดที่ใช้งานได้, คำอธิบายที่ชัดเจนว่าทำไมถึงตัดสินใจแบบนั้น, และโหมดความล้มเหลวที่แน่นอนที่คุณจะเจอถ้าข้ามมันไป

ด้วยวิธีนี้ เมื่อคุณอ่านจบ คุณสามารถเป็นเจ้าของเอเจนต์โปรดักชันแบบ end-to-end ตั้งแต่ handler แรกไปจนถึง sandbox และ CI job ที่รันมันโดยไม่มีคนดูแล

การสร้างความเข้าใจนี้ใช้เวลามากกว่า 6 สัปดาห์ของการทำงานทุกวันกับ codebase ซึ่งส่วนใหญ่เป็นการ debug สิ่งที่ดูถูกต้องก่อนที่จะพังภายใต้เงื่อนไขจริง

มาเริ่มกันเลย ⬇️

รูปร่างของโปรเจกต์

สอง crates หนึ่งไบนารี ทุก execution target เป็นตัวเลือกการกำหนดค่า ไม่ใช่การเขียนใหม่

  • SDK คือไลบรารีที่คุณดึงเข้าไปในโปรเจกต์ Rust ใดๆ CLI ห่อมันไว้ เอเจนต์ของคุณคือไบนารี Rust ที่เริ่มต้นด้วย use agentic_harness::prelude::*;
  • cargo build คือทั้ง pipeline ไม่มี bundler ไม่มี transpile step ไม่มี language runtime บน target machine ไฟล์ปฏิบัติการเดี่ยวที่พึ่งพาตัวเองได้บวกกับ manifest.json

ข้อจำกัดการออกแบบที่ขับเคลื่อนทุกอย่าง: ไบนารีเอเจนต์เดียวกันควรทำงานบนแล็ปท็อปของคุณในโหมดโต้ตอบ, ในงาน GitHub Actions ที่ clone repo ใหม่, กับ remote E2B sandbox ผ่าน HTTP, และบน Cloudflare Worker boundary โดยไม่ต้องเปลี่ยน agent logic แม้แต่บรรทัดเดียวระหว่างกัน

ทุกการตัดสินใจใน codebase นี้มีอยู่เพื่อรักษาข้อจำกัดนั้น

3 ชั้นและเหตุผลที่แต่ละชั้นมีอยู่

โมเดลทางความคิดคือวงแหวนสามวงซ้อนกัน การรู้ว่าแต่ละขอบเขตอยู่ตรงไหนจะช่วยประหยัดเวลา debug ได้มากกว่าสิ่งอื่นใดในคู่มือนี้

โค้ด Rust ของคุณคือวงแหวนรอบนอก

  • คุณเขียน handlers handlers รับ AgentContext พวกมันเรียก sessions sessions เรียกโมเดล, อ่านไฟล์, เขียนไฟล์, รันคำสั่ง shell, สร้าง tasks, เชื่อมต่อกับ MCP servers
  • คุณไม่เคยแตะ HTTP client โดยตรง คุณไม่เคย parse model response โดยตรง SDK จัดการทั้งสองอย่าง

harness คือวงแหวนกลาง

  • มันจัดการ agent registry, เส้นทาง identity ตาม URL path, จัดการ session persistence ข้ามการเรียก, context compaction เมื่อเซสชันโต, การค้นพบ roles และ skills, ลำดับความสำคัญของการเลือกโมเดล, และ trait ModelClient ที่เป็นกลางต่อ provider
  • สิ่งนี้ทำให้คุณสามารถสลับ Anthropic เป็น OpenAI เป็น Ollama instance ในเครื่องได้โดยไม่ต้องแตะ handler code
  • harness คือสิ่งที่ทำให้ agent logic ของคุณนำกลับมาใช้ใหม่ได้ข้าม providers และ targets
  • มันยังเป็นที่ที่ทุกสิ่งที่พังในโปรดักชันได้รับการจัดการ: session state, context overflow, provider failures, concurrent request ordering

execution targets คือวงแหวนชั้นใน

  • local filesystem, CI checkout, HttpSessionEnv ที่ชี้ไปที่ Daytona หรือ E2B, Cloudflare Worker boundary
  • harness ไม่สนใจว่าคุณใช้ตัวไหน handlers ของคุณก็ไม่สนใจเช่นกัน พวกมันเรียก session.shell() และ session.write() และ harness แปลสิ่งเหล่านั้นเป็นสิ่งที่ target พื้นฐานต้องการ
  • การแยกนี้คือประเด็นทั้งหมด เมื่อ E2B ปล่อย API เวอร์ชันใหม่ คุณอัปเดต connector ไม่ใช่ agent logic
  • เมื่อ Anthropic ปล่อย claude-opus-4-7 คุณอัปเดต runtime.json ไม่ใช่ handlers ของคุณ วงแหวนรอบนอกสะอาดเพราะวงแหวนกลางดูดซับความยุ่งเหยิงทั้งหมด

runtime config: ไฟล์ที่ควบคุมเลเยอร์โมเดล

ก่อนที่คุณจะเขียน handler แม้แต่ตัวเดียว คุณต้องมี runtime.json ใน workspace ของคุณ

วางไฟล์นี้ที่ .agentic-harness/config.json หรือที่ราก workspace เป็น agentic-harness.json load_workspace_context() จะดึงมันขึ้นมาโดยอัตโนมัติ

การเลือกโมเดลในรันไทม์เป็นไปตามลำดับความสำคัญนี้:

  1. PromptOptions::model(...): การแทนที่ต่อการเรียก
  2. metadata โมเดลของ role ที่เลือก: ค่าเริ่มต้นต่อ role
  3. defaultModel จาก runtime config: ค่าเริ่มต้นของ workspace

สิ่งที่ต้องเข้าใจ: ต้องลงทะเบียน model ID ก่อนจึงจะใช้ได้ openaiCompatibleModels คือรายการที่ harness ใช้เพื่อเชื่อมต่อ built-in chat-completions client ถ้าโมเดลของคุณไม่อยู่ในรายการนั้น คุณจะได้รับ error ที่ชัดเจนตั้งแต่เริ่มต้นแทนที่จะเป็นความล้มเหลวที่สับสนกลางเซสชัน

สำหรับเกตเวย์ที่เข้ากันได้กับ OpenAI การกำหนดค่าจะเหมือนกัน ชี้ baseUrl ไปที่เกตเวย์ของคุณ:

  • อย่าเขียน literal API key ลงใน runtime.json ใช้ apiKeyEnv และเก็บคีย์จริงไว้ใน environment ของคุณ
  • harness อ่าน env var ในเวลาที่ร้องขอ ไม่ใช่ตอนเริ่มต้น ซึ่งหมายความว่าคุณสามารถหมุนคีย์ได้โดยไม่ต้องรีสตาร์ทเซิร์ฟเวอร์

ตัวตนของเอเจนต์คือ URL path ไม่ใช่การค้นหาจาก registry

นี่คือการตัดสินใจออกแบบแรกที่ทำให้ฉันประหลาดใจ ตอนนี้ฉันคิดว่ามันถูกต้องแล้ว

ไม่มีระบบ agent ID ไม่มี registry key ไม่มี UUID ที่คุณสร้างเอง ตัวตนของเอเจนต์ของคุณคือ POST /agents/<name>/<id>

  • harness จัดการ bookkeeping สถานะเซสชันทั้งหมดไว้เบื้องหลัง URL นั้น
  • เหตุผลที่ใช้ได้: ทุก caller ในทุกระบบรู้วิธีสร้าง ID ที่มีความหมายจากบริบทอยู่แล้ว หมายเลข PR, run ID, timestamp รวมกับชื่องาน, user handle
  • คุณไม่จำเป็นต้องมี session creation endpoint คุณไม่จำเป็นต้องเก็บ session ID แยกต่างหาก URL คือเซสชัน

agent handler ฝั่ง Rust เรียก ctx.id() เพื่อรับ ID ที่ caller ให้มา:

sessions: บริบทการดำเนินการที่มีสถานะ

เซสชันเป็นมากกว่าเธรดการสนทนา มันคือบริบทการดำเนินการเต็มรูปแบบสำหรับการเรียกใช้เอเจนต์

มันเก็บ:

  • ประวัติข้อความกับโมเดล
  • การเข้าถึงไฟล์ใน workspace (อ่าน, เขียน, แก้ไข, grep, glob, stat, readdir)
  • การดำเนินการ shell พร้อมการควบคุม cwd และ env
  • การลงทะเบียนเครื่องมือ (MCP servers, custom tools)
  • role ที่ได้รับมอบหมายและการซ้อนทับ system prompt
  • งบประมาณ compaction และ watermark ประวัติ

คุณได้รับเซสชันโดยเรียก ctx.session_with_id() ด้วย ID ที่เหมาะสม:

  • เซสชันคงอยู่ข้ามการเรียก HTTP เมื่อคุณใช้ ID เดียวกัน เรียก endpoint เอเจนต์เดียวกันสามครั้งด้วย session ID เดียวกัน โมเดลจะเห็นการแลกเปลี่ยนทั้งสามครั้งเป็นการสนทนาต่อเนื่องกัน
  • ประวัติสะสมโดยอัตโนมัติ คุณไม่ต้องจัดการมัน
  • นี่คือสิ่งที่ทำให้เวิร์กโฟลว์หลายขั้นตอนเป็นไปได้โดยไม่ต้องจัดการสถานะด้วยตัวเอง คุณเรียก session.prompt() ต่อไปเรื่อยๆ และ harness จัดการทุกอย่างอื่น

เมื่อคุณต้องการส่งบริบทจำนวนมากควบคู่ไปกับ prompt ให้อ่านไฟล์และจัดรูปแบบ inline:

เซสชันจัดการการนับ token เพื่อให้คุณไม่ล้น context window โดยไม่ตั้งใจกลางการสนทนา เมื่อคุณใกล้ถึงงบประมาณ compaction จะทำงาน เพิ่มเติมในส่วนหลัง

tasks: child sessions ที่โฟกัสซึ่งทำให้ parent สะอาด

  • นี่คือ primitive ที่ฉันหวังว่าจะเข้าใจตั้งแต่วันแรก มันคือความแตกต่างระหว่างเอเจนต์ที่คงความสอดคล้องข้ามงานยาวๆ กับเอเจนต์ที่เริ่มหลอนครึ่งทาง
  • task คือ child session แบบ one-shot ประวัติใหม่ แชร์ workspace ส่งคืนผลลัพธ์ให้ parent ประวัติของ parent ไม่เคยเห็นการให้เหตุผลระหว่างกลางของ task เลย
  • research task ทำงานแยกเดี่ยว ห่วงโซ่การให้เหตุผลทั้งหมด
  • ทุกการสังเกตระหว่างกลางที่โมเดลทำเกี่ยวกับโค้ด ทุก "เดี๋ยวก่อน ให้ฉันตรวจสอบไฟล์นี้ด้วย" อยู่ภายใน task
  • parent session ได้รับสรุปที่สะอาดหนึ่งอัน นั่นคือทั้งหมดที่มันเห็น

ทำไมสิ่งนี้ถึงสำคัญในทางปฏิบัติ: เมื่อคุณรัน exploratory analysis โดยตรงภายในเซสชันที่ทำงานยาวนาน ประวัติจะเต็มไปด้วยการเรียกเครื่องมือระหว่างกลาง คำตอบบางส่วน และการให้เหตุผลของโมเดลเกี่ยวกับสิ่งที่ไม่มี relevance อีกต่อไป โมเดลจะยึดติดกับ noise นั้นเมื่อไม่ควร compaction จะทำงานในที่สุดและสูญเสียบริบทที่คุณต้องการจริงๆ tasks คือการแก้ไขที่ตรงจุด

กฎ: ถ้าปัญหาย่อยมี deliverable ที่ชัดเจนและไม่ต้องการประวัติการสนทนาของ parent เพื่อทำให้เสร็จ ให้ทำให้มันเป็น task เกณฑ์สำหรับ "ทำให้เป็น task" ต่ำกว่าที่คุณคิด

สำหรับการวิเคราะห์แบบขนานข้าม codebase: รูปแบบ cartographer, กระจาย tasks และรวบรวมผลลัพธ์:

แต่ละ task สะอาด แต่ละ task โฟกัสที่ไดเรกทอรีเดียวเท่านั้น parent session รวบรวมผลลัพธ์และเขียนเอกสารสุดท้าย

ถ้าคุณมี 12 โมดูล คุณรัน 12 tasks ที่โฟกัส แต่ละอันเริ่มต้นด้วย baggage ศูนย์จากอันอื่น

roles และ skills: กำหนดพฤติกรรมโดยไม่ต้องคอมไพล์ใหม่

  1. roles อยู่ใน .agentic-harness/roles/ skills อยู่ใน .agents/skills/ ทั้งคู่ถูกค้นพบโดยอัตโนมัติเมื่อ harness เริ่มทำงาน
  2. roles คือ system-prompt overlays ที่ขอบเขตต่อการเรียก ใช้ในเวลาที่เรียกและทิ้งหลังจากนั้น พวกมันไม่คงอยู่ในประวัติข้อความ พวกมันไม่สะสมข้ามการเรียก

ห่วงโซ่ลำดับความสำคัญ: call role > session role > agent role > no role

  • frontmatter ของโมเดลเป็นตัวเลือกแต่มีประโยชน์ มันช่วยให้คุณกำหนดเส้นทาง roles เฉพาะไปยังโมเดลเฉพาะ
  • role อธิบายของคุณทำงานบน claude-sonnet-4-6 เพื่อความเร็วและต้นทุน role ตรวจสอบความปลอดภัยทำงานบน claude-opus-4-7 เพื่อความลึก คุณกำหนดค่านี้ครั้งเดียวในไฟล์ role และไม่ต้องคิดถึงมันอีก
  • skills คือไฟล์อธิบายพฤติกรรมที่โมเดลอ่านเมื่อเริ่มเซสชัน
  • พวกมันเป็นไฟล์ markdown ใน .agents/skills/ harness ค้นหาพวกมันโดยอัตโนมัติ คุณไม่ต้องลงทะเบียนที่ไหน

การใช้งานจริง: ไลบรารี skills ข้าง codebase ของคุณอธิบายวิธีที่คุณทำงาน รูปแบบ commit message, ไลบรารีที่ต้องการ, หลักการตั้งชื่อ migration, รูปแบบการออกแบบ API, ข้อกำหนดการทดสอบ

โมเดลอ่านสิ่งนี้ก่อนทุกเซสชัน คุณแก้ไข markdown พฤติกรรมอัปเดตในการรันครั้งถัดไป ไม่ต้องคอมไพล์ใหม่

โมเดลอ่านสิ่งนี้ มันเขียน commits ที่ตรงกับหลักการของคุณ คุณไม่ต้องเตือนมันทุกเซสชัน คุณดูแลไฟล์เดียว

วงจร coding agent ในรายละเอียดเต็ม

วงจร coding agent คือกรณีการใช้งานหลักที่ CLI ถูกสร้างขึ้นมา มันยังเป็นที่ที่สิ่งต่างๆ มากที่สุดอาจผิดพลาดได้ถ้าคุณกำหนดค่าผิด

คำสั่งเต็มพร้อมตัวเลือกทั้งหมดที่สำคัญ:

สิ่งที่แต่ละ flag ทำและทำไมถึงสำคัญ:

  1. --workspace . ตั้งค่าราก การดำเนินการไฟล์ทั้งหมดถูกแซนด์บ็อกซ์ที่นี่ เอเจนต์ไม่สามารถอ่านหรือเขียนนอกเส้นทางนี้ บังคับใช้ที่ระดับ harness — ไม่ใช่โดยการไว้วางใจให้โมเดลจำกัดตัวเอง
  2. --llm auto เลือกโมเดลจาก defaultModel ใน runtime config ของคุณ ใช้ --llm anthropic/claude-opus-4-7 สำหรับงานซับซ้อนที่ต้องการการให้เหตุผลเชิงลึก หรือ --llm anthropic/claude-sonnet-4-6 สำหรับการวนซ้ำที่เร็วขึ้น
  3. --deny-path คือการบล็อกแบบแข็ง มันจับคู่แบบ prefix ดังนั้น --deny-path config/ ครอบคลุมทุกอย่างภายใต้ config/ ตรวจสอบ workspace ของคุณก่อนรันครั้งแรกและแจกแจงทุกเส้นทางที่เก็บความลับหรือการกำหนดค่าโปรดักชัน — ไม่ใช่แค่ .env
  4. --approve-dependencies อนุญาตให้แก้ไข Cargo.toml โดยไม่ต้องมีขั้นตอนการอนุมัติจากมนุษย์ ปล่อยไว้ถ้าคุณต้องการตรวจสอบทุก crate ใหม่ก่อนที่จะถูกเพิ่ม
  5. --commit stage การเปลี่ยนแปลงทั้งหมดโดยอัตโนมัติและ commit พวกมันเมื่อสิ้นสุดการรันที่สำเร็จด้วยข้อความที่คุณให้ หากไม่มี flag นี้ การเปลี่ยนแปลงจะลงเป็น unstaged modifications ให้คุณตรวจสอบ
  6. --pr เปิด pull request จาก commit ต้องการสถานะ git ที่สะอาดก่อนรันและ branch จริง ไม่ใช่ detached HEAD

วงจรเอง: Inspect → Brief → LLM + Tools → Edit + Test → Commit · PR

  • inspect: อ่านโครงสร้าง workspace, โหลด skills และ roles, ระบุไฟล์ที่น่าจะเกี่ยวข้องกับ prompt มากที่สุด
  • เขียนความเข้าใจลงใน coding-brief.md ก่อนที่จะแตะโค้ดใดๆ
  • brief: โมเดลยอมรับแผน คุณสามารถอ่าน .agentic-harness/runs/<id>/coding-brief.md กลางรันเพื่อดูว่ามันตัดสินใจอะไร
  • ถ้า brief ดูผิด ให้ฆ่าการรัน มันถูกกว่าที่จะเริ่มใหม่ด้วย prompt ที่ชัดเจนกว่าปล่อยให้เอเจนต์ดำเนินการตามแผนที่ไม่ดี
  • LLM + tools: วงจร edit-test โมเดลทำการเปลี่ยนแปลง รันชุดทดสอบ อ่านผลลัพธ์ ทำการเปลี่ยนแปลงเพิ่มเติม วนซ้ำจนกว่าการทดสอบจะผ่าน, ถึงขีดจำกัดการวนซ้ำ, หรือตัดสินใจว่างานเสร็จสมบูรณ์

commit · PR: stage, commit, push, เปิด PR พร้อม diff ที่แนบมา

ทุกการรันเขียน artifacts หกชิ้นไปยัง .agentic-harness/runs/<id>/:

  1. coding-brief.md: แผนที่เอเจนต์ยอมรับก่อนเขียนโค้ดใดๆ
  2. summary.md: บัญชีที่มนุษย์อ่านได้ว่าทำอะไร, ลองอะไร, และทำไม
  3. run.json: metadata ที่มีโครงสร้าง: โมเดลที่ใช้, ระยะเวลาทั้งหมด, จำนวน token input/output, จำนวนการวนซ้ำ, สถานะออกสุดท้าย
  4. events.jsonl: ทุกการเรียกเครื่องมือตามลำดับพร้อม input และ output เต็ม สำหรับ debug ว่ามีอะไรผิดพลาด
  5. diff.patch: diff ที่สมบูรณ์ของการเปลี่ยนแปลงไฟล์ทั้งหมด
  6. checks.json: ผลการทดสอบและ lint สุดท้ายที่กำหนดความสำเร็จหรือความล้มเหลว

เคล็ดลับที่ควรจำ

  • ปฏิบัติต่อสิ่งเหล่านี้เป็น structured logs ไม่ใช่ output ชั่วคราว ฉัน commit run artifacts ไปยัง repo สำหรับงานใดๆ ที่ฉันต้องสามารถทำซ้ำได้
  • run.json เพียง 2KB บอกคุณถึงโมเดล, ต้นทุน token, และว่ามันสำเร็จหรือไม่ events.jsonl บอกคุณอย่างแน่ชัดว่าเอเจนต์ทำอะไรและในลำดับใดเมื่อคุณต้อง debug การรันที่ไม่ดี

สำหรับ CI รูปแบบคือ:

HttpSessionEnv: รันไบนารีในเครื่อง, ดำเนินการจากระยะไกล

  • นี่คือความสามารถที่ฉันใช้เวลานานที่สุดในการทำความเข้าใจอย่างถ่องแท้ ตอนนี้ฉันใช้มันกับเกือบทุกงานที่แตะโครงสร้างพื้นฐาน
  • ไบนารีเอเจนต์ทำงานบนเครื่องของคุณหรือใน CI การดำเนินการ filesystem และ shell ทำงานภายใน remote sandbox
  • เอเจนต์ไม่รู้และไม่สนใจว่ามันอยู่ในสภาพแวดล้อมใด

ใช้ use agentic_harness::HttpSessionEnv;

wire protocol คือ JSON ผ่าน HTTP ทุกการดำเนินการ:

  1. exec
  2. read
  3. write
  4. edit
  5. grep
  6. glob
  7. stat
  8. readdir
  9. mkdir
  10. rm

มีรูปร่าง request/response ที่กำหนดไว้

sandbox ใดๆ ที่ใช้โปรโตคอลนี้จะทำงานเป็นเป้าหมาย HttpSessionEnv

เพื่อเชื่อมต่อ sandbox ที่มีชื่อ:

built-in connectors จัดการ boilerplate การรับรองความถูกต้องและวงจรชีวิตสำหรับ Vercel Sandbox, Daytona และ E2B:

  • กรณีการใช้งานที่เป็นรูปธรรมที่ฉันใช้สิ่งนี้มากที่สุด: การทำซ้ำความล้มเหลวของ CI ในสภาพแวดล้อม Linux ที่สะอาด
  • เอเจนต์ clone repo ที่ commit hash ที่ล้มเหลวอย่างแน่ชัด, รันคำสั่งทดสอบที่ล้มเหลวอย่างแน่ชัด, อ่านผลลัพธ์เต็ม, วินิจฉัยความล้มเหลว, และเขียนรายงาน
  • ฉันอ่านรายงาน ฉันไม่เคยแตะเครื่องท้องถิ่นของฉัน sandbox ถูกทิ้งเมื่อเซสชันสิ้นสุด

ประสิทธิภาพที่ไม่มีใครเตือนคุณ: ทุกการเรียก shell ผ่าน HttpSessionEnv คือการเดินทางไปกลับของเครือข่าย ลูปที่แน่น: แก้ไข, ทดสอบ, ตรวจสอบผลลัพธ์, แก้ไข: สะสมความหน่วงอย่างรวดเร็ว

ลูป 40 ครั้งที่ใช้เวลา 5 วินาทีในเครื่องใช้เวลาหลายนาทีกับ remote sandbox ถ้าแต่ละครั้งทำการเรียก shell สามครั้งแยกกัน

วิธีแก้ไข: รวมงาน shell เป็นสคริปต์

หนึ่งการเรียกต่อครั้งแทนที่จะเป็นสาม เขียนสคริปต์ครั้งเดียว รันซ้ำๆ ความแตกต่างของความหน่วงในลูป 40 ครั้งนั้นมีจริง

build targets: codebase เดียว, รูปแบบ deployment สามแบบ

native เป็นค่าเริ่มต้น หนึ่งไบนารี หนึ่ง manifest ไม่มีอะไรอื่นบน target machine ทำงานได้ทุกที่ที่สามารถรัน native Linux binary

node สำหรับแพลตฟอร์มโฮสติ้งที่ต้องการ Node entrypoint build สร้าง server.mjs ที่เริ่ม native rust binary เป็น child process และ proxy HTTP ไปยังมัน agent logic ยังคงทำงานเป็น rust เลเยอร์ Node เป็น HTTP shim 30 บรรทัด

Cloudflare สำหรับ edge deployment

  • build สร้างไฟล์ Worker boundary และเชื่อมต่อ app adapter ที่เข้ากันได้กับ Worker
  • handlers คอมไพล์เป็น WASM ผ่าน WASM JSON ABI
  • Durable Object bindings จัดการ session persistence ผ่าน Cloudflare KV

ข้อจำกัดสำคัญเกี่ยวกับ Cloudflare: Workers ไม่รองรับคำสั่ง shell ที่ทำงานยาวนาน พวกมันไม่มี filesystem จริง

พวกมันไม่รองรับ cargo หรือ build tooling ใดๆ --target cloudflare มีไว้สำหรับการจัดการ webhook, route metadata, control endpoints ขนาดเล็ก, และ Durable Object routing — ไม่ใช่สำหรับงาน coding

สำหรับอะไรก็ตามที่ต้องรัน cargo test ให้มอบหมายให้ native process หรือ remote sandbox

เมทริกซ์การตัดสินใจในทางปฏิบัติ:

  • การส่งเอเจนต์เป็น API ที่บริการอื่นเรียก → native หลัง nginx หรือแพลตฟอร์มที่มีการจัดการ
  • โฮสต์บน Railway, Render หรือแพลตฟอร์มที่คาดหวัง Node → node
  • การรับ webhook, การกำหนดเส้นทางน้ำหนักเบา, การจัดการสถานะ Durable Object → cloudflare
  • ทุกอย่างอื่น → native

schema-guided output: typed rust structs จาก model responses

การขอให้โมเดลคืนค่า JSON และหวังว่ามันจะทำคือครึ่งหนึ่งของคำตอบ

การให้ harness แยก, ตรวจสอบความถูกต้อง, และ deserialize เป็น rust struct ของคุณคือคำตอบที่สมบูรณ์

โมเดลสามารถคืนร้อยแก้วการให้เหตุผลควบคู่ไปกับ payload ที่มีชนิดใน response เดียวกัน harness แยกบล็อกผลลัพธ์ระหว่าง

  • ---RESULT_START--- และ ---RESULT_END--- markers คุณจะได้ rust struct ความปลอดภัยของชนิดในเวลาคอมไพล์จาก model output ไปยัง handler logic ของคุณ
  • schema ทำสองสิ่ง: มันบอกโมเดลว่ารูปร่างใดที่จะสร้าง และมันให้บางอย่างแก่ harness เพื่อตรวจสอบความถูกต้องก่อน deserialization
  • ถ้าโมเดลคืนสิ่งที่ตรงกับ schema คุณจะได้รับ PromptError::SchemaValidationFailed แทนที่จะ panic สาม call sites ต่อมาเมื่อคุณเข้าถึงฟิลด์ที่หายไป

MCP tools: เอื้อมออกไปนอก sandbox

เมื่อเอเจนต์ต้องการความสามารถที่เกินกว่าไฟล์และ shell connect_mcp คือช่องทางหลบหนี

เอเจนต์ได้รับชุดเครื่องมือเต็มของ MCP server ไม่ต้องเขียน tool definitions คำอธิบายมาจาก server โมเดลตัดสินใจเมื่อจะเรียกใช้ tool ใดตามคำอธิบายเหล่านั้น

คุณสามารถเชื่อมต่อ MCP servers หลายตัวกับเซสชันเดียว:

  • โมเดลเรียกใช้ tools ตามคำอธิบายของพวกมัน คำอธิบายที่คลุมเครือเช่น "search sentry" จะถูกเรียกใช้ไม่สม่ำเสมอ
  • คำอธิบายที่บอกว่า "call this before responding to any question about errors, incidents, or production issues" จะถูกเรียกใช้อย่างน่าเชื่อถือ
  • ถ้าคุณควบคุม MCP server ให้เขียนคำอธิบายที่ชี้นำ: บอกโมเดลเมื่อจะเรียกใช้ ไม่ใช่แค่มันคืนอะไร

connectors: สร้าง adapters แทนที่จะเขียนด้วยมือ

แทนที่จะเขียน adapter code ด้วยมือกับ API ที่ไม่คุ้นเคย ให้ส่งสูตร connector ไปยัง coding agent ของคุณ:

  • สูตร connector คือคำอธิบายที่มีโครงสร้างของ sandbox API และสัญญา SessionEnv ที่ต้องทำให้สำเร็จ
  • coding agent อ่านมัน, เขียนโมดูล adapter rust, จัดการการรับรองความถูกต้อง, ห่อวงจรชีวิต provider, และเปิดเผยเป็น HttpSessionEnv
  • คุณตรวจสอบ diff คุณ merge มัน adapter อยู่ในโปรเจกต์ของคุณ มันเป็นโค้ดของคุณแล้ว

ฉันเชื่อมต่อ Daytona โดยใช้วิธีนี้ในเวลาประมาณ 20 นาทีรวมรอบการตรวจสอบทั้งหมด agent ได้รูปแบบ header auth ที่ถูกต้องในครั้งแรก

การเขียน adapter จาก scratch กับเอกสาร Daytona จะใช้เวลาส่วนใหญ่ของบ่ายและอย่างน้อยสองสมมติฐานที่ผิดเกี่ยวกับโฟลว์ refresh token

เมื่อ connector ถูกสร้าง:

automatic compaction: จัดการเซสชันยาวโดยไม่สูญเสียบริบท

เซสชันที่ทำงานนานสะสมประวัติ

ในที่สุดพวกมันจะล้น context window ของโมเดล

harness จัดการสิ่งนี้โดยอัตโนมัติ แต่คุณต้องกำหนดค่าอย่างถูกต้อง มิฉะนั้นคุณจะสูญเสียบริบทในเวลาที่ผิดอย่างแน่นอน

context_window_tokens คืองบประมาณทั้งหมดสำหรับเซสชัน

  • reserve_tokens คือสิ่งที่คุณกันไว้สำหรับการตอบสนองของโมเดล ขีดจำกัดที่มีผลสำหรับประวัติคือ context_window_tokens - reserve_tokens
  • keep_recent_messages คือจำนวนข้อความที่ส่วนท้ายที่ถูกเก็บไว้ตามตัวอักษรเสมอไม่ว่าจะมีการบีบอัดหรือไม่

เมื่อประวัติเกินงบประมาณ harness ขอให้โมเดลสรุปทุกอย่างระหว่าง system prompt และส่วนท้ายที่เก็บไว้

สรุปนั้นแทนที่ส่วนกลาง ข้อความส่วนท้ายยังคงอยู่เหมือนเดิม เซสชันที่ถูกบีบอัดมีขนาดเล็กลงและการเรียกครั้งถัดไปพอดีกับงบประมาณ

การแลกเปลี่ยนนั้นมีจริง: สรุปสูญเสียความแม่นยำ การตัดสินใจเฉพาะที่ทำเมื่อ 50 ข้อความก่อน: "เราเลือก authlib เพราะมันเป็นไลบรารีเดียวที่รองรับ PKCE ที่ทำงานกับโมเดล middleware ของ axum" อาจรอดเป็น "เราเลือก authlib สำหรับ auth" ในสรุป

ถ้าความแม่นยำนั้นรับน้ำหนักสำหรับการตัดสินใจในภายหลังในเซสชัน ให้เก็บไว้อย่างชัดเจน:

  • เขียนการตัดสินใจลงในไฟล์ ไฟล์รอดจากการบีบอัด โมเดลสามารถอ่านกลับมาได้ตามต้องการ ประวัติไม่จำเป็นต้องแบกทุกอย่างถ้า workspace ทำ
  • รัน agentic-harness doctor เพื่อดู context window ที่รายงานจริงของโมเดลของคุณ ตั้งค่า context_window_tokens เป็น 80-90% ของค่านั้น
  • ตัวนับ token ไม่แม่นยำสมบูรณ์แบบในฝั่งโมเดล และการอ่านไฟล์ขนาดใหญ่ครั้งเดียวสามารถผลักคุณเกินได้ถ้าคุณอยู่ที่ 99%

สิ่งที่ควรระวัง

  1. การปนเปื้อนประวัติเซสชัน
  • ปัญหา: การวิเคราะห์เชิงสำรวจภายในเซสชันยาวทำให้ prompt หลังๆ ปนเปื้อนด้วย noise จากขั้นตอนการสำรวจ
  • วิธีแก้ไข: ใช้ tasks ประวัติ task ไม่เคยแตะ parent เกณฑ์สำหรับ "ทำให้เป็น task" ต่ำกว่าที่คุณคิด
  1. ความประหลาดใจของลำดับความสำคัญ role
  • ปัญหา: call role บดบัง session role โมเดลทำงานแตกต่างจากที่คาดและคุณไม่รู้ว่าทำไม
  • วิธีแก้ไข: session role กำหนดตัวตน call role จำกัดขอบเขตให้แคบลง พวกมันซ้อนกัน — call role เพิ่มเข้าไป ไม่ควรยกเลิก
  1. ช่องว่าง --deny-path
  • ปัญหา: คุณ deny .env ความลับของคุณยังอยู่ใน .env.local และ config/staging.yaml เอเจนต์อ่านหนึ่งในนั้น
  • วิธีแก้ไข: deny prefixes ไม่ใช่ชื่อไฟล์ --deny-path config/ ครอบคลุมทุกอย่างภายใต้มัน
  1. detached HEAD ใน CI
  • ปัญหา: เอเจนต์แก้ไข, การทดสอบผ่าน, commit ล้มเหลว — เพราะไม่มี branch ให้ commit
  • วิธีแก้ไข: git checkout -b agent-run-$RUN_ID ก่อนเรียกใช้ harness
  1. ความหน่วงของ HttpSessionEnv ในลูปที่แน่น
  • ปัญหา: 40 ครั้งที่สามการเรียก shell ต่อครั้งคือความหน่วงของเครือข่ายบริสุทธิ์หลายนาที
  • วิธีแก้ไข: เขียน agent-check.sh ที่ทำทุกอย่างในการเรียกครั้งเดียว หนึ่งการเรียกต่อครั้ง
  1. การประเมินงบประมาณบริบทต่ำเกินไป
  • ปัญหา: compaction ทำงานกลาง task โมเดลสูญเสียแผนและเริ่มด้นสดจากสรุป
  • วิธีแก้ไข: รัน agentic-harness doctor เพื่อรับหน้าต่างจริง ตั้งค่างบประมาณเป็น 80-90% ของนั้น
  1. runtime config โหลดหลังจากลงทะเบียน handler
  • ปัญหา: handler ทำงานก่อน load_workspace_context() ไม่มีโมเดลที่ลงทะเบียน ข้อผิดพลาดดูไม่เหมือนปัญหาเรื่องการกำหนดค่า
  • วิธีแก้: เรียก load_workspace_context() ใน app() เสมอก่อนที่จะเชื่อมต่อ agent ใดๆ
  1. --llm เปลี่ยนอัตโนมัติระหว่างการรัน
  • ปัญหา: defaultModel ถูกอัปเดต การรันสองครั้งที่ห่างกันหกเดือนไม่สามารถเปรียบเทียบกันได้ คุณไม่สามารถจำลองการรันครั้งแรกได้
  • วิธีแก้: ปักหมุดโมเดลใน runtime.json สำหรับทุกอย่างที่ต้องการความสามารถในการทำซ้ำ
  1. การลบ artifacts ของการรัน
  • ปัญหา: คุณล้าง runs/ ในกฎ gitignore สามสัปดาห์ต่อมาคุณต้องจำลอง regression และทุกอย่างหายไป
  • วิธีแก้: commit artifacts ของการรันสำหรับงานใดๆ ที่คุณต้องการจำลอง run.json มีขนาด 2KB เก็บไว้

สิ่งที่ฉันจะทำแตกต่าง

  1. รันคู่มือ agentic-harness ก่อนแตะอะไรเลย
  2. เขียนการทดสอบระดับ session ก่อนเขียน logic ของ handler
  3. ใช้ tasks สำหรับทุกอย่างที่มีผลลัพธ์ย่อย
  4. ปักหมุดโมเดลตั้งแต่การรันจริงครั้งแรก
  5. เก็บการตัดสินใจในไฟล์ ไม่ใช่ในประวัติ session
  6. จัดการ shell operations เป็นชุดตั้งแต่เริ่มต้นเมื่อใช้ sandbox ระยะไกล

สรุป

เฟรมเวิร์ก agent ส่วนใหญ่เป็น wrapper รอบการเรียก API นี่คือ runtime

wrapper แก้ปัญหา "ทำให้โมเดลตอบสนอง" runtime แก้ปัญหา "ส่ง agent ไปยัง production และทำให้มันทำงานได้หลังจากโมเดลเปลี่ยน หลังจาก sandbox เปลี่ยน หลังจาก codebase เปลี่ยน หลังจาก session ทำงานเป็นเวลาสองชั่วโมงและล้น context window"

สถาปัตยกรรม 3 ชั้น

  1. โค้ดของคุณ
  2. harness
  3. เป้าหมายการทำงาน

คือสิ่งที่ทำให้สิ่งนี้เป็นไปได้ คุณเขียน handler harness รับภาระความซับซ้อนในการดำเนินการทั้งหมด เป้าหมายการทำงานเป็นตัวเลือกในการกำหนดค่า

สิ่งที่เปลี่ยนแปลง: logic ของ handler, โครงสร้าง session, รูปแบบ task, คำจำกัดความของบทบาท, ไฟล์ skill สิ่งที่เปลี่ยนแปลง: โมเดล, ผู้ให้บริการ, ผู้ขาย sandbox, เป้าหมายการ deploy

สถาปัตยกรรมถูกออกแบบมาเพื่อให้สิ่งที่เปลี่ยนแปลงไม่เคยแตะต้องสิ่งที่เปลี่ยนแปลงไม่ได้

นั่นคือการเดิมพัน มันเป็นการเดิมพันที่ถูกต้อง

หวังว่าคุณจะสนุกกับการอ่านบทความนี้และสำรวจว่าฉันสร้างสำหรับ agent และโดยทั่วไปอย่างไร ❣️

ข้อปฏิเสธความรับผิดชอบ

บทความนี้ได้รับการวิจัยและเขียนโดยผู้เขียน แก้ไขโดย Minimax-M2.7 ภาพขนาดย่อนำมาจาก Pinterest

Harrison Chase "memory should be open!" —

[https://x.com/hwchase17/status/2046308913939919232Harrison](https://x.com/hwchase17/status/2046308913939919232Harrison)

Chase :"Your Harness, Your Memory" —

[https://www.langchain.com/blog/your-harness-your-memory](https://www.langchain.com/blog/your-harness-your-memory)

Vivek Trivedi :"The Anatomy of an Agent Harness" —

[https://www.langchain.com/blog/the-anatomy-of-an-agent-harness](https://www.langchain.com/blog/the-anatomy-of-an-agent-harness)

More patterns to decode

Recent viral articles

Explore more viral articles

สร้างมาเพื่อครีเอเตอร์

หาไอเดียจากบทความไวรัลบน 𝕏 ถอดรหัสว่าทำไมถึงปัง แล้วเปลี่ยนแพตเทิร์นเหล่านั้นเป็นหัวข้อคอนเทนต์ถัดไปของคุณ