HYBRID MIND · AGENT ENGINEERING · ARTICLE 001
Agent ที่ตอบได้หนึ่งครั้งยังไม่ได้ตอบว่าใครมีสิทธิ์เรียกเครื่องมือ งานหยุดแล้วกลับมาตรงไหน และผลที่ส่งมาถูกต้องพอจะใช้ต่อหรือไม่ ก่อนเพิ่มโมเดลหรือเพิ่ม Agent เราควรออกแบบความรับผิดชอบของระบบให้ตรวจได้
บทความนี้ใช้กรอบแปดองค์ประกอบเพื่อเปรียบเทียบ Workflow, Single-Agent และ Multi-Agent ด้วยโจทย์เดียวกัน กรอบนี้เป็นข้อเสนอสำหรับการออกแบบของบทความ ไม่ใช่มาตรฐานบังคับให้ทุกระบบต้องมีครบแปดส่วน และไม่ได้รับรองความพร้อม Production ของตัวอย่างที่ให้มา

Direct Answer: เลือกวิธีควบคุมงาน ก่อนเลือกจำนวน Agent
เลือกโครงสร้างจากสัญญางานและหลักฐานที่ต้องส่ง ไม่เริ่มจากจำนวน Agent ระบุการตัดสินใจที่ต้องมี การกระทำที่อนุญาต และวิธีรับผล แล้วประเมินว่าระบบง่ายที่สุดยังตอบโจทย์หรือไม่
ผลลัพธ์การเรียนรู้: หลังอ่าน คุณควรเขียนบันทึกตัดสินใจสถาปัตยกรรมหนึ่งหน้า ระบุรูปแบบที่เลือก ผู้รับผิดชอบแต่ละส่วน ขอบเขตเครื่องมือ เกณฑ์ตรวจรับ และเงื่อนไขหยุด โดยไม่ใช้จำนวน Agent เป็นหลักฐานว่าระบบดีขึ้น
บทความนี้ต่อยอดจาก Loop Engineering ที่เน้นวงจร Coding Agent และ 12 Agentic AI Projects ที่เป็นแผนฝึกทักษะ ตอนนี้เน้นการเลือกโครงสร้างและสัญญาระหว่างองค์ประกอบ ไม่ยืมผลทดสอบของงานเหล่านั้นมาเป็นผลของตัวอย่างใหม่
โจทย์เดียวที่ใช้เทียบ: รายงาน Repository แบบอ่านอย่างเดียว
สมมติทีมต้องการรายงานข้อมูลพื้นฐานของ Repository สาธารณะที่อนุญาต เช่น psf/requests หรือ python/cpython รายงานต้องมีตัวตน Repository, branch เริ่มต้น, URL ต้นทาง, เวลาที่อ่าน และรหัสงาน หากข้อมูลผิดรูปหรือบริการปฏิเสธ ต้องหยุดพร้อมเหตุผล ไม่มีการเปิด Issue, แก้โค้ด, เข้าถึง Repository ส่วนตัว หรือเผยแพร่รายงานแทนผู้ใช้
นี่เป็นโจทย์สอนที่กำหนดขึ้นเพื่อเทียบสถาปัตยกรรม ข้อมูลตัวอย่างในแบบฝึกเป็น Synthetic หรือข้อมูลสังเคราะห์ ไม่ใช่ผลอ่าน API สด ส่วนโค้ดที่ส่งมอบมีเส้นทาง HTTP จริงให้ผู้อ่านทดสอบในสิทธิ์ของตน แต่ผู้เขียนยังไม่ได้รัน โค้ดจึงมีสถานะ NOT RUN
ต่างจาก LLM chat ที่ตอบจากข้อมูลในบทสนทนา ระบบที่เชื่อมเครื่องมือต้องตรวจทั้งการเลือกเครื่องมือ สิทธิ์ ข้อมูลที่ส่งเข้า ผลตอบกลับ และการตรวจรับคำตอบสุดท้าย การมีข้อความว่า “อ่านสำเร็จ” ยังไม่พอ ต้องเห็นหลักฐานว่าผลมาจาก Repository ที่ขอและไม่ได้ขยายขอบเขตไปเอง
คำว่า สัญญา ในบทความหมายถึงข้อตกลงที่ตรวจได้ระหว่างส่วนของระบบ เช่น รับข้อมูลแบบใด ทำอะไรได้ ส่งผลแบบใด และผิดพลาดแล้วหยุดอย่างไร ไม่ใช่เพียงข้อความแนะนำให้โมเดลประพฤติตัวดี
Workflow, Single-Agent และ Multi-Agent ต่างกันตรงไหน
เอกสารต้นทางแยกเส้นทางที่โค้ดกำหนดจากขั้นตอนที่โมเดลเลือก Workflow แตกแขนงได้ จึงไม่รับรองเส้นทางหรือข้อความเหมือนกันทุกครั้ง Anthropic · LangGraph

| รูปแบบ | เส้นทางของกรณีสอน | ภาระที่ต้องตรวจ |
|---|---|---|
| Workflow | ตรวจคำขอ → เรียก GET ที่อนุญาต → ตรวจ JSON → สร้างรายงานตามรูปแบบ | Input/Output, สิทธิ์, Error และผลจากบริการ ภายในโจทย์ที่กำหนดครบนี้ยังไม่มีเหตุผลจำเป็นต้องเรียกโมเดล |
| Single-Agent | โมเดลรับโจทย์ → เสนอการอ่านที่จำเป็น → ตัวรันตรวจสิทธิ์ → คืนข้อมูลหรือเหตุหยุด → ตรวจรายงาน | จำกัดรอบและเครื่องมือ แยกคำเสนอของโมเดลจากคำอนุญาตของตัวรัน และยอมถามคนเมื่อคำขอไม่ชัด |
| Multi-Agent | ตัวประสานกำหนดงานย่อย → บทบาทอ่าน/ทบทวนส่งหลักฐาน → รวมผลตามเกณฑ์เดียวกัน | ตัวตนงานย่อย สถานะที่ส่งต่อ ผลขัดแย้ง ข้อมูลตกหล่น การอ่านซ้ำ และเกณฑ์ตรวจรับผลรวม |
สำหรับงานพื้นฐานนี้ใช้ Workflow เป็นตัวตั้ง หากคำขอเปิดกว้างจึงพิจารณาโมเดล แต่เครื่องมือของตอนนี้อ่านได้เฉพาะ metadata ถ้าถามรายละเอียด Source Code ให้ระบุว่าหลักฐานไม่พอ ไม่ขยายสิทธิ์หรือเดาจากชื่อ Repository
การอ่านสอง Repository ทำด้วยโค้ดเรียกทีละรายการได้ ก่อนเพิ่ม Agent ให้ระบุว่าบทบาทต้องตัดสินใจอิสระอะไร และจะรักษาตัวตน/ฉบับข้อมูลหลังส่งต่ออย่างไร
หลาย Agent อาจใช้โมเดลเดียวกันแต่มีสถานะหรือเครื่องมือต่างกัน หากทุกบทบาทใช้ข้อมูลผิดชุดเดียวกัน ความเห็นตรงกันยังไม่ใช่หลักฐานอิสระ
8 องค์ประกอบ: แยกหน้าที่ ไม่ใช่บังคับซื้อแปดบริการ

| ส่วน | คำถามที่ต้องตอบ | ใช้กับโจทย์นี้อย่างไร |
|---|---|---|
| 1. LLM / Model | ต้องใช้โมเดลตัดสินใจอะไร และหยุดก่อนทำอะไร | รายงาน metadata ที่กำหนดครบทำได้โดยไม่ใช้ LLM ส่วนทางเลือก Agent ต้องกำหนดเหตุที่เพิ่มโมเดลให้ชัด |
| 2. Tool Calling / API | ชื่อเครื่องมือ ข้อมูลเข้า ผลตอบกลับ และข้อผิดพลาดมีสัญญาหรือไม่ | รับ Repository ที่อนุญาตเท่านั้น ตรวจผลก่อนส่งต่อ ไม่รับ URL อิสระหรือคำสั่งเขียน |
| 3. State / Context | งานอยู่ขั้นไหน ใช้หลักฐานฉบับใด และลองไปแล้วกี่ครั้ง | ตัวอย่างเก็บจำนวนครั้งในรันและรหัสงาน ยังไม่มี state ที่กู้คืนข้าม process ได้ |
| 4. Memory / Retrieval | ต้องจำข้ามงานจริงหรือไม่ เก็บอะไร และจะค้นคืนพร้อมที่มาอย่างไร | งานครั้งเดียวนี้ไม่ต้องมี Vector Database หากเพิ่ม cache ต้องกำหนดอายุและไม่แอบส่งข้อมูลเก่าเป็นข้อมูลสด |
| 5. Orchestration / Execution | ใครควบคุมเส้นทางงาน งบการเรียก และการส่งต่อ | โค้ดควบคุมเส้นทางพื้นฐาน ทางเลือกหลายบทบาทต้องเพิ่มสัญญาของงานย่อยและผลรวม |
| 6. Authentication / Permissions | ใครเรียกใช้ได้ และทำอะไรกับทรัพยากรใดได้บ้าง | ไม่มี token ในตัวอย่าง อ่านได้เฉพาะ endpoint สาธารณะที่เลือกไว้ การอนุญาตต้องอยู่นอกคำตอบของโมเดล |
| 7. Observability / Logging | ย้อนจากรายงานกลับไปยังการเรียกและเหตุหยุดได้หรือไม่ | ส่ง JSON events พร้อม execution ID แต่ยังไม่มี exporter หรือระบบ trace ที่ติดตั้งจริง |
| 8. Evaluation / Recovery | รับงานจากอะไร และเมื่อพังจะกลับมาทำต่อหรือส่งคนเมื่อใด | ตรวจตัวตนและรูปแบบข้อมูล หยุดเมื่อผิดสัญญา พร้อมแผนทดสอบที่ยัง NOT RUN |
หน้าที่หนึ่งอาจกระจายหลาย process หรือบริการเดียวดูแลหลายส่วน ต้องป้องกันช่องว่าง เช่น gateway เข้าใจคำเสนอโมเดลว่าอนุมัติแล้ว หรือผู้รวมผลไม่ตรวจว่าข้อมูลเป็นฉบับเดียวกัน
เอกสาร LangGraph แยก checkpointer สำหรับสถานะ/ความจำระยะสั้นกับ store สำหรับข้อมูลข้ามงาน การเลือกใช้ขึ้นกับอายุและขอบเขตของข้อมูล ไม่ใช่เพิ่ม storage แล้วได้ recovery ถูกต้องทันที Persistence ต้นทาง
ความจำภายนอกไม่ใช่การเปลี่ยนน้ำหนักโมเดล ดัชนีหรือ Embedding ไม่รับรองว่าข้อมูลจริงหรือใหม่ ต้องกำหนดที่มา อายุ สิทธิ์ และวิธีจัดการข้อมูลขัดกัน
Data Flow: ให้สิทธิ์ตัดสินก่อนข้อมูลออกนอกระบบ
- รับคำขอ ระบุ Repository และผลที่ต้องส่ง ไม่รับคำสั่งทั่วไปที่ตีความเป็น URL ใดก็ได้
- ตรวจสัญญาและสิทธิ์ ตัวรันปฏิเสธฟิลด์หรือทรัพยากรนอกขอบเขตก่อนเปิดเครือข่าย
- เรียกเครื่องมือ ใช้ GET ไปยังปลายทางคงที่ บันทึก attempt และตัวตนงาน
- ตรวจผล ตรวจชนิดเนื้อหา ขนาด JSON และ Repository ที่ตอบกลับ หากไม่ตรงให้หยุด
- ส่งรายงาน ส่งเฉพาะข้อมูลที่ตรวจรูปแบบแล้ว พร้อม URL/เวลาที่อ่าน หรือเหตุหยุดอย่างชัดเจน
ถ้าเพิ่ม LLM ให้โมเดลเสนอขั้นตอนและรับผลเป็นข้อมูล ส่วนการอนุญาตยังอยู่ในโค้ด ชื่อเครื่องมือที่โมเดลเขียนเองต้องไม่ข้าม dispatcher
OpenAI Function Calling แยกคำขอเรียกฟังก์ชันจากผลที่แอปคืนให้โมเดล โดยผูกผลกับ call ID จึงต้องรักษาความสัมพันธ์นี้ในตัวรัน ไม่ถือคำขอของโมเดลว่าเครื่องมือทำสำเร็จแล้ว Official OpenAI documentation
MCP เพิ่มโครงเชื่อม host, client และ server เพื่อให้เข้าถึง tools/resources ได้ตาม protocol ไม่แทนการออกแบบสิทธิ์หรือการตรวจรับของแอป เอกสารที่เปิดอ่านครั้งนี้เป็น route รุ่น 2026-07-28 ตัวอย่างในบทความไม่ได้ติดตั้ง MCP SDK หรือจำลองว่าเชื่อม server จริงแล้ว MCP Architecture
เขียน Contract ก่อนเพิ่มขั้นตอน
| Contract | เกณฑ์ที่ตรวจได้ |
|---|---|
| Functional | รับชื่อจาก allowlist ส่ง JSON report ที่ตัวตนตรงคำขอและมี URL/เวลาอ่าน หากไม่สำเร็จส่ง stopped ไม่แต่งข้อมูล |
| Reliability | จำกัด GET สองครั้งสำหรับความผิดพลาดชั่วคราวที่อนุญาต ไม่ลองใหม่ทันทีเมื่อบริการขอให้รอ ไม่มี fallback ข้อมูลเก่าโดยไม่แจ้ง |
| Security | ไม่มี write endpoint ไม่รับ host อิสระ ไม่มี key ใน source และไม่ตีความข้อความจากบริการเป็นคำสั่ง |
| Observability | ผูก start/attempt/success/stop กับ execution ID แยก log ออกจากผลลัพธ์ ไม่บันทึก raw body หรือ secret |
| Evaluation | ข้อมูลนอก allowlist ต้องไม่เปิด network; JSON ผิด/ตัวตนผิดต้องไม่ส่ง ok; rate-limit ต้องไม่เกิดการลองใหม่ทันที |
เทียบทั้งสามโครงสร้างด้วยสิ่งส่งมอบเดียวกัน รายงานที่สวยแต่ตัวตนผิดยังไม่ผ่าน และบทบาทตรวจทานที่ใช้ข้อมูลคนละฉบับไม่ใช่หลักฐานว่าตรวจสองชั้นสำเร็จ
Structured Outputs ช่วยจำกัดรูปแบบตาม schema ที่รองรับ แต่ความถูกต้องของข้อมูลและสิทธิ์ต้องตรวจแยก โครง JSON ถูกแบบไม่ได้พิสูจน์ว่าข้อเท็จจริงถูก และ schema subset ต้องตรงกับ API ที่ใช้ เอกสาร Structured Outputs
Brief หกส่วนสำหรับเขียน Architecture Decision Record
เป้าหมาย: เลือก Workflow, Single-Agent หรือ Multi-Agent สำหรับรายงาน metadata ของ psf/requests หรือ python/cpython พร้อมเหตุผลจากสัญญางาน ข้อมูลและเครื่องมือ: เอกสาร GitHub GET repository ที่อ้างอิง; code/repository_tool.py เป็นตัวอย่างเครื่องมืออ่าน public metadata; ไม่มี Source Code/release/security audit อยู่ในผล metadata ขอบเขตสิทธิ์: เขียนแบบออกแบบและแผนทดสอบได้ โค้ดตัวอย่างยัง NOT RUN ไม่เรียก API/LLM ไม่ติดตั้ง package ไม่เปิด Issue แก้ repository หรือ deploy โดยไม่มีอำนาจ สิ่งส่งมอบ: Decision record หนึ่งหน้า ตารางความรับผิดชอบแปดส่วน Data Flow และรายการ acceptance/failure cases พร้อม source URL และสถานะสิ่งที่ยังไม่ทดสอบ เกณฑ์ตรวจรับ: ใช้โจทย์/Output เดียวกันทั้งสามทางเลือก ระบุส่วนที่ไม่จำเป็นและเหตุผล แยกข้อเสนอโมเดลจากสิทธิ์จริง ไม่อ้าง mock/แบบจำลองเป็น Live หรือ Production PASS จุดหยุด: คำขอไม่ชัด สิทธิ์ไม่พอ เอกสาร/ข้อมูลไม่ตรง version เกิด rate-limit หรือข้อมูลผิดรูป ให้ระบุข้อจำกัดและถามคน ไม่เพิ่มสิทธิ์หรือสร้างผลลัพธ์แทนเอง
Python Example: ขอบเขตเครื่องมืออ่านจริงที่ยัง NOT RUN
ส่งมอบ repository_tool.py, test_repository_tool.py และ README โค้ดนี้เป็นส่วน Tool/API และ Workflow แบบกำหนดเส้นทาง ไม่ใช่ implementation ของ Agent ทั้งสามแบบ และยังไม่มีโมเดล planner, MCP server, memory database, durable recovery หรือบริการที่ deploy แล้ว
Runtime: Python 3.12+ · Dependencies: Standard Library · Environment variables: ไม่มี · Credentials: ไม่มี · การติดตั้ง: บันทึกไฟล์ในโฟลเดอร์เดียวกัน ไม่ต้องติดตั้ง package เพิ่ม ตัวอย่างใช้ public GitHub GET และไม่เรียก LLM แบบเสียเงิน แต่ยังต้องเคารพโควตาและเงื่อนไขบริการ
GitHub ระบุว่า endpoint อ่าน Repository สาธารณะใช้โดยไม่ authenticate ได้ ตัวอย่างเอกสารปัจจุบันแสดง API version 2026-03-10 และอาจคืน 301/403/404 ตัวอย่างของเราจึงไม่สมมติว่าทุกคำขอได้ JSON สำเร็จ GET Repository ต้นทาง
วิธีอ่านโค้ด
validate_input ตรวจฟิลด์และ allowlist ก่อนเปิด network จากนั้นตรวจชนิดเนื้อหา ขนาด JSON และตัวตนด้วย validate_response ก่อนสร้างรายงาน ไม่ฝากการควบคุมนี้ไว้ใน prompt
HTTPError แยกเหตุหยุดจาก GET ที่ลองใหม่ได้ JSON/ตัวตนผิดไม่ควร retry เพื่อหวังคำตอบที่พอใจ การหยุดบน redirect เป็นนโยบายของตัวอย่าง ไม่ใช่ข้อห้ามตาม redirect ของ GitHub
ค่า timeout ของ urllib จำกัด blocking operations จึงไม่ได้รับรอง deadline ทั้งงาน หากต้องป้องกันบริการตอบช้ามากหรือ process ค้าง ต้องออกแบบ cancellation/worker limits และทดสอบเพิ่ม เอกสาร Python
Source Code: repository_tool.py — NOT RUN
"""Authored teaching example. Runtime/integration tests: NOT RUN.
Python 3.12+, Standard Library only. Public GitHub metadata GET only.
This is a tool boundary / deterministic workflow, not a complete LLM agent.
"""
from __future__ import annotations
import argparse
import json
import sys
import time
import uuid
from datetime import datetime, timezone
from http.client import IncompleteRead
from typing import Any
from urllib.error import HTTPError, URLError
from urllib.request import HTTPRedirectHandler, Request, build_opener
ALLOWED_REPOSITORIES = frozenset({"psf/requests", "python/cpython"})
API_VERSION = "2026-03-10"
MAX_BYTES = 262_144
MAX_ATTEMPTS = 2
IO_TIMEOUT_SECONDS = 8
TOOL_SCHEMA = {
"type": "object",
"properties": {"repository": {"type": "string", "enum": sorted(ALLOWED_REPOSITORIES)}},
"required": ["repository"],
"additionalProperties": False,
}
class ToolStop(Exception):
"""A classified, fail-closed result; message never contains raw response data."""
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None # Intentional teaching policy: review destination changes.
def validate_input(payload: Any) -> str:
if not isinstance(payload, dict) or set(payload) != {"repository"}:
raise ToolStop("INPUT_SHAPE")
repository = payload["repository"]
if not isinstance(repository, str) or repository not in ALLOWED_REPOSITORIES:
raise ToolStop("REPOSITORY_NOT_ALLOWED")
return repository
def validate_response(payload: Any, repository: str) -> str:
if not isinstance(payload, dict) or payload.get("full_name") != repository:
raise ToolStop("RESPONSE_IDENTITY")
branch = payload.get("default_branch")
if not isinstance(branch, str) or not branch or len(branch) > 200:
raise ToolStop("RESPONSE_SHAPE")
return branch # Data only. Never evaluate or turn this string into a command.
def event(execution_id: str, kind: str, **fields: Any) -> None:
record = {"execution_id": execution_id, "event": kind, **fields}
print(json.dumps(record, ensure_ascii=False), file=sys.stderr)
def repository_report(payload: Any) -> dict[str, Any]:
repository = validate_input(payload) # Validate before opening any URL.
execution_id = str(uuid.uuid4())
source = "https://api.github.com/repos/" + repository
opener = build_opener(NoRedirect())
request = Request(source, method="GET", headers={
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": API_VERSION,
"User-Agent": "HybridMind-Architecture-Teaching-Example",
})
started = time.perf_counter()
event(execution_id, "START", repository=repository)
for attempt in range(1, MAX_ATTEMPTS + 1):
event(execution_id, "TOOL_ATTEMPT", attempt=attempt)
try:
with opener.open(request, timeout=IO_TIMEOUT_SECONDS) as response:
if response.status != 200:
raise ToolStop("UNEXPECTED_HTTP_STATUS")
content_type = response.headers.get("Content-Type", "").split(";")[0].lower()
if content_type not in {"application/json", "application/vnd.github+json"}:
raise ToolStop("CONTENT_TYPE")
raw = response.read(MAX_BYTES + 1)
if len(raw) > MAX_BYTES:
raise ToolStop("RESPONSE_TOO_LARGE")
try:
data = json.loads(raw.decode("utf-8"))
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ToolStop("INVALID_JSON") from exc
branch = validate_response(data, repository)
elapsed_ms = round((time.perf_counter() - started) * 1000, 3)
event(execution_id, "TOOL_SUCCESS", attempt=attempt, elapsed_ms=elapsed_ms)
return {
"status": "ok", "execution_id": execution_id,
"repository": repository, "default_branch": branch,
"source_url": source,
"retrieved_at_utc": datetime.now(timezone.utc).isoformat(),
"attempts": attempt,
}
except HTTPError as exc:
code = exc.code
retry_after = exc.headers.get("Retry-After")
limit_remaining = exc.headers.get("X-RateLimit-Remaining")
exc.close()
if code in {403, 429} or retry_after is not None or limit_remaining == "0":
event(execution_id, "STOP", error="RATE_OR_PERMISSION", http_status=code,
retry_after_present=retry_after is not None,
rate_exhausted=limit_remaining == "0")
stop_code = "RATE_OR_PERMISSION_REVIEW" if code in {403, 429} else "SERVER_WAIT_REVIEW"
raise ToolStop(stop_code) from None
if code in {500, 502, 503, 504} and attempt < MAX_ATTEMPTS:
event(execution_id, "RETRY", error="READ_TRANSIENT", http_status=code)
time.sleep(0.5) # Chosen example delay, not GitHub's universal policy.
continue
event(execution_id, "STOP", error="HTTP_STOP", http_status=code)
raise ToolStop("HTTP_STOP") from None
except (URLError, TimeoutError, IncompleteRead, ConnectionError) as exc:
if attempt < MAX_ATTEMPTS:
event(execution_id, "RETRY", error="READ_NETWORK")
time.sleep(0.5)
continue
event(execution_id, "STOP", error="NETWORK_STOP")
raise ToolStop("NETWORK_STOP") from exc
except ToolStop as exc:
event(execution_id, "STOP", error=str(exc))
raise
raise ToolStop("ATTEMPTS_EXHAUSTED")
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("repository", choices=sorted(ALLOWED_REPOSITORIES))
parser.add_argument("--live-read", action="store_true",
help="Explicitly enable the public GitHub GET; no LLM or write requests")
args = parser.parse_args()
if not args.live_read:
print(json.dumps({"status": "NOT_RUN", "instruction": "Add --live-read only when authorized."}))
return 2
try:
print(json.dumps(repository_report({"repository": args.repository}), ensure_ascii=False))
return 0
except ToolStop as exc:
print(json.dumps({"status": "stopped", "error": str(exc)}))
return 1
if __name__ == "__main__":
raise SystemExit(main())
Source Code: test_repository_tool.py — NOT RUN
"""Synthetic offline unit-test deliverable. NOT RUN by the writer.
These tests do not contact GitHub, invoke an LLM, or prove production safety.
"""
import json
import unittest
from unittest.mock import MagicMock, patch
from urllib.error import HTTPError
from repository_tool import ToolStop, repository_report, validate_input, validate_response
class ContractTests(unittest.TestCase):
def test_allowed_input(self):
self.assertEqual(validate_input({"repository": "psf/requests"}), "psf/requests")
def test_unknown_repository_before_network(self):
with patch("repository_tool.build_opener") as network:
with self.assertRaisesRegex(ToolStop, "REPOSITORY_NOT_ALLOWED"):
repository_report({"repository": "https://example.invalid/private"})
network.assert_not_called()
def test_extra_action_rejected(self):
with self.assertRaisesRegex(ToolStop, "INPUT_SHAPE"):
validate_input({"repository": "psf/requests", "action": "write"})
def test_response_cannot_change_identity(self):
with self.assertRaisesRegex(ToolStop, "RESPONSE_IDENTITY"):
validate_response({"full_name": "other/repo", "default_branch": "main"}, "psf/requests")
def test_invalid_branch(self):
with self.assertRaisesRegex(ToolStop, "RESPONSE_SHAPE"):
validate_response({"full_name": "psf/requests", "default_branch": None}, "psf/requests")
@patch("repository_tool.build_opener")
def test_synthetic_success_shape(self, build):
fake = MagicMock()
fake.status = 200
fake.headers = {"Content-Type": "application/json"}
fake.read.return_value = json.dumps({"full_name": "psf/requests", "default_branch": "fixture-branch"}).encode()
build.return_value.open.return_value.__enter__.return_value = fake
result = repository_report({"repository": "psf/requests"})
self.assertEqual(result["default_branch"], "fixture-branch")
self.assertEqual(result["attempts"], 1)
self.assertEqual(result["source_url"], "https://api.github.com/repos/psf/requests")
@patch("repository_tool.build_opener")
def test_rate_limit_is_not_retried(self, build):
error = HTTPError("https://api.github.com/repos/psf/requests", 429, "limited",
{"Retry-After": "120"}, None)
build.return_value.open.side_effect = error
with self.assertRaisesRegex(ToolStop, "RATE_OR_PERMISSION_REVIEW"):
repository_report({"repository": "psf/requests"})
self.assertEqual(build.return_value.open.call_count, 1)
@patch("repository_tool.build_opener")
def test_invalid_json_stops_without_retry(self, build):
fake = MagicMock(status=200, headers={"Content-Type": "application/json"})
fake.read.return_value = b"not-json"
build.return_value.open.return_value.__enter__.return_value = fake
with self.assertRaisesRegex(ToolStop, "INVALID_JSON"):
repository_report({"repository": "psf/requests"})
self.assertEqual(build.return_value.open.call_count, 1)
if __name__ == "__main__":
unittest.main()
Source Code: README.md — NOT RUN
# Article001 — Read-only Repository Tool Boundary
**Testing Status: NOT RUN.** Writer authored these files and test instructions; did not execute/import/compile them, install dependencies, contact GitHub through the example, or invoke an LLM. A design/source review is not a runtime PASS.
Runtime: Python 3.12+; primary library documentation read was Python3.12.15. Dependencies: Standard Library only. No pip install, SDK, embedding model, database, container or GPU required. Environment variables: none. Credentials: none; only public repository metadata is requested.
This implementation covers input validation, a fixed read-only public GitHub endpoint, classified stopping/retry behavior and structured JSON events. It is a deterministic workflow/tool component, **not** a complete Single-Agent/Multi-Agent runtime, MCP server, durable-state system, VectorDB, OTel exporter or deployable production service.
## Install / Run
Save `repository_tool.py` and `test_repository_tool.py` in one directory. Verify your Python version yourself. Example commands to execute only in an authorized local environment:
```text
python --version
python repository_tool.py psf/requests
python repository_tool.py psf/requests --live-read
python -m unittest -v test_repository_tool.py
```
The second command defaults to NOT_RUN and exits2. `--live-read` explicitly enables network GET to `api.github.com`; the writer has not run it. The test command is synthetic/offline and mocks the opener; it has not been run either. Expected successful JSON shape includes `status`, `execution_id`, `repository`, `default_branch`, `source_url`, `retrieved_at_utc`, `attempts`. Actual branch/time/ID are live data, not fixture guarantees.
Input contract: exactly `{"repository":"psf/requests"}` or the allowed `python/cpython` value. Additional action/URL fields are rejected before network access. The schema file describes this deliberately limited contract; explicit Python validation is its enforcement, not a general JSON Schema library.
## Cost and Permissions
No paid LLM call occurs. Public GitHub API requests are still subject to service terms and quotas; no universal quota or provider-price guarantee is given. Do not insert private access tokens. Do not broaden repository/host permissions based on model output. No POST/PATCH/DELETE, shell execution, file modifications or publication are implemented.
## Failure / Recovery Contract
- HTTP403/429, any HTTP error with Retry-After, or an exhausted-rate header: stop for permission/wait review; presence of retry headers is recorded without logging their raw value. No immediate retry ignores a requested wait, including HTTP503 with Retry-After.
- HTTP301/other redirects: fail closed for destination review. This intentionally differs from automatic redirect-following; a moved repository is not silently treated as a new authorized endpoint.
- HTTP500/502/503/504 or network error: at most two GET attempts with a chosen0.5-second delay. This is not a universal retry policy or a complete exponential-backoff/circuit-breaker implementation.
- Wrong content type, oversized body, invalid JSON, identity mismatch or missing branch: stop; do not fabricate a successful report.
- `urlopen` timeout limits blocking operations. It is **not a guaranteed hard end-to-end deadline**; robust services need separate cancellation/process limits and tested slow-response handling.
- In-memory attempts/events do not survive process failure. There is no persistence, checkpoint/resume, cross-worker duplicate prevention, transaction safety or automatic fallback to stale data.
- Logs are JSON to stderr, result to stdout. They are not an OpenTelemetry integration and must be integrated/tested separately. No raw response body, secret or prompt is logged.
## Acceptance / Additional Tests to Run
Validate allowed input and extra-field rejection before network access; wrong repository identity; malformed/oversized/slow response; redirect destination; permissions;429 with wait; transient5xx exhaustion; interrupted runs; shared quota across workers; secret-redaction checks. The supplied unit cases are only a starting set; integration, regression, recovery, performance and runtime security remain NOT RUN. Expected cases must be verified against the actual runtime and recorded with version/commands/output before any PASS claim.
## Model / Orchestration Integration Plan
An authorized application may expose this boundary as an allowed tool. Keep schema and authorization outside the model; map a requested tool name/arguments to a fixed dispatcher, validate arguments, record the execution/tool-call identifiers, execute the GET, return data/error and verify the final answer's source. That plan is not implemented or tested here.
Workflow: code controls the known fetch→validate→report route. Single-Agent: a model may choose whether/when the allowed read is needed under a bounded loop. Multi-Agent: separate research/review roles need explicit handoff state and aggregate acceptance; they may use the same model. Neither alternative becomes necessary merely because it appears in the architecture comparison. No model credentials or API calls are included in this code deliverable.
คำสั่งสำหรับผู้อ่านที่มีอำนาจทดสอบ
python --version
python repository_tool.py psf/requests
python repository_tool.py psf/requests --live-read
python -m unittest -v test_repository_tool.py
ไม่มี --live-read จะไม่เปิด network ส่วน live ต้องมีอำนาจของผู้อ่าน unittest ใช้ข้อมูลสังเคราะห์และ mock ทั้งหมด ผู้เขียนยังไม่ได้รันคำสั่งเหล่านี้
Expected Output ไม่ใช่ผลรันที่สังเกตจริง
{"status":"ok","execution_id":"<รหัสที่สร้างเมื่อรัน>","repository":"psf/requests","default_branch":"<ข้อมูลจาก API>","source_url":"https://api.github.com/repos/psf/requests","retrieved_at_utc":"<เวลาที่อ่านจริง>","attempts":1}
ไม่ hardcode branch/เวลาจริงตาม fixture Expected Output เป็นสัญญา ไม่ใช่ผล integration ที่ยืนยันแล้ว หากส่งต่อให้ LLM ต้องรักษาที่มาและตรวจคำตอบกับหลักฐาน
Failure Scenario: 429 ไม่ใช่เหตุให้เพิ่ม Agent

สมมติ HTTP429 ขอให้รอ ตัวรันต้องหยุดและบันทึกเหตุ ไม่เปลี่ยนบัญชี เพิ่ม worker หรือเดาข้อมูลแทน การกลับมาหลังรอเป็น recovery ที่ต้องออกแบบเพิ่ม
GitHub ให้เคารพ Retry-After และเวลา reset เมื่อโควตาหมด ตัวอย่างหยุดให้ตรวจเมื่อมีคำสั่งรอ ไม่ใช้ค่าหน่วงสมมติสั้น ๆ แทนเวลาที่บริการกำหนด API best practices
ต้องทดสอบข้อมูลอ่านไม่ครบ ตัวตนผิด body ใหญ่ redirect timeout และ process หยุดก่อนบันทึกผล การ retry GET อาจได้ข้อมูลต่างเวลา และตัวนับในหน่วยความจำไม่ใช่ durable checkpoint
ตรวจ expected behavior กับ attempts/log/assertions จริง ไม่รับคำว่า “จัดการ error แล้ว” เป็นหลักฐาน ชุด unit tests เป็นจุดเริ่ม ยังไม่ครอบคลุม production/concurrency/recovery และยัง NOT RUN
Architecture Builder: ทดลองเหตุผลที่เลือกแต่ละส่วน
แบบจำลองใช้สถานการณ์สังเคราะห์และกฎที่เปิดให้อ่าน เลือกโครงสร้างกับลักษณะงานเพื่อดูหน้าที่แต่ละส่วน ไม่เรียกโมเดลหรือบริการ และไม่เป็น benchmark/ใบรับรองความปลอดภัย
3D แสดงความสัมพันธ์ของหน้าที่ ส่วน Contract Interactive แยกตรวจขอบเขตและรับผล มีข้อความสำรองเมื่อ JavaScript ปิด ป้าย/คีย์บอร์ด/reduced motion ออกแบบไว้ แต่ UI tests ยัง UNKNOWN
Architecture Builder: ทดลองแบ่งหน้าที่ก่อนสร้างระบบ
Simulation จากกฎของบทความ ไม่มีโมเดลหรือ API ทำงานจริง ไม่มีราคา เวลา หรือคะแนนประสิทธิภาพที่วัดได้ เลือกโครงสร้างแล้วตรวจว่าหน้าที่ใดต้องมีผู้รับผิดชอบ แปดส่วนเป็นกรอบออกแบบ ไม่ใช่ข้อบังคับให้ติดตั้งแปดบริการ
เลือกส่วนประกอบเพื่ออ่านหน้าที่ ผังใช้ตำแหน่งชั้นหน้าแทน control boundary ชั้นกลางแทน execution และชั้นหลังแทนข้อมูลสนับสนุน ไม่ใช่แผน deployment จริง
อ่านได้เมื่อ JavaScript หรือภาพสามมิติไม่พร้อม
- Workflow: โค้ดควบคุมขั้นและเงื่อนไขของงานนี้
- Single-Agent: ผู้ตัดสินใจหนึ่งบทบาทเสนอเครื่องมือ แต่ gateway ยังตรวจสิทธิ์
- Multi-Agent: ผู้วางแผน ผู้รวบรวม และผู้ตรวจแยกบทบาท ต้องกำหนดสัญญาการส่งต่อ ไม่มีสิทธิ์เพิ่มจากจำนวนบทบาท
- นอกขอบเขต: ปฏิเสธก่อนเรียกเครื่องมือ
- 429: หยุดและให้คนตรวจการรอหรือโควตา
- ข้อมูลผิดสัญญา: ไม่ส่งรายงานที่อ้างว่าสำเร็จ
Contract Inspector: ตรวจรับผลเครื่องมือแยกจากโครงสร้าง
ชุด Synthetic Test ที่สร้างเพื่อการเรียน ผลจากกฎในเบราว์เซอร์ไม่ใช่ผลทดสอบ Python หรือ GitHub จริง ไม่ส่งข้อมูลออกจากหน้านี้
กฎและผลคาดหมายที่อ่านได้โดยไม่รัน
| กรณี | ผลคาดหมาย |
|---|---|
| รายการอนุญาตและผลตรง | รับรายงานจำลอง ต้องแนบ source URL และเวลาเมื่อรันจริง |
| รายการนอกขอบเขต | ปฏิเสธ ไม่เรียก API |
| ชื่อผิดหรือฟิลด์หาย | ปฏิเสธข้อมูล ไม่อ้างสำเร็จ |
| 429 | หยุด ให้คนตรวจ rate limit |
| Timeout ครั้งที่หนึ่ง / ครั้งที่สอง | เสนอ retry หนึ่งครั้ง / หยุดเมื่อครบสองครั้ง |
เชื่อม Video Lab: แผนเดียวกันต้องมีผู้รับผิดชอบ
Video Lab ที่ติดตั้งรุ่น 1.4.0 เป็นแบบจำลองวงจรงานวิดีโอ ใช้เป็นโจทย์ประกอบเพื่อเลือกวิธีควบคุมงาน: ถ้าบรีฟกำหนดขั้นตอนและผลครบ ออกแบบ Workflow; ถ้าต้องตัดสินใจจากข้อมูลระหว่างทาง ให้เขียนเหตุที่ต้องใช้ Agent; ถ้าแยกบทบาท ให้กำหนดสัญญาส่งต่อและตรวจผลรวม
Lab นี้ไม่ได้เป็น runtime ของ Python หรือเครื่องมือสร้าง Workflow/Single/Multi ตามตัวอย่าง Repository และไม่ได้ใส่ brief ทั้งหกส่วนให้เอง ให้เลือกอ่านข้อความบรีฟด้านล่างแล้วใช้เป็นแผนตรวจออกแบบ ต้นทุน/เวลาใน Lab เป็นค่าตั้งเพื่อการเรียนรู้ ไม่ใช่ผลวัดของบทความ
เป้าหมาย: ออกแบบแผนวิดีโออธิบายการเลือก Workflow, Single-Agent และ Multi-Agent โดยชี้ผู้รับผิดชอบทุกขั้น ไม่ render หรือเผยแพร่จริง ข้อมูลและเครื่องมือ: เนื้อหาและแปดความรับผิดชอบในบทความ; Video Lab เป็น simulation สำหรับสำรวจวงจรงานวิดีโอ ไม่มี Python/API/โมเดลจริงจากการกดปุ่ม ขอบเขตสิทธิ์: เขียน Story/Hook และแผนลำดับงานได้ ห้าม upload/render/send/publish หรือติดต่อบริการภายนอกตามบรีฟนี้; ค่าต้นทุน/เวลาเป็นสมมติฐาน สิ่งส่งมอบ: แผนสามฉาก เปรียบเทียบสามโครงสร้างในโจทย์เดียว พร้อมรายชื่อผู้รับผิดชอบข้อมูล เครื่องมือ สิทธิ์ และตรวจรับ เกณฑ์ตรวจรับ: ระบุส่วนที่ไม่จำเป็น กำหนด input/output และ evidence ของแต่ละขั้น แยกผู้เสนอจากผู้อนุญาต ไม่อ้างว่าสาม topology ถูกสร้างหรือทดสอบแล้ว จุดหยุด: บรีฟไม่ชัด สิทธิ์/หลักฐานไม่พอ ฉากกล่าวเกินข้อเท็จจริง หรือเริ่มขอให้ทำงานภายนอก ให้หยุดและส่งคำถามให้คน
จากคลิปดิบ
สู่จักรวาลคอนเทนต์
ChatGPT ตัดต่อวิดีโอแทนคนได้จริงแค่ไหน? สำรวจระบบ AI Video Editing Agent ผ่านฉากสามมิติที่โต้ตอบได้ พร้อมแยกข้อเท็จจริง สร้างพรอมป์ต์ และจำลองต้นทุนก่อนลงมือทำจริง
ออกแบบระบบตัดต่อในมุมมอง 3D
ลากบนฉากเพื่อหมุนมุมมอง แตะโหนดเพื่อดูหน้าที่ของ AI ในแต่ละขั้นตอน
จัดระเบียบไฟล์ ตรวจคุณภาพภาพและเสียง และกำหนดสิทธิ์เข้าถึงให้ AI Agent
แยกความสามารถจริงจากคำโฆษณา
กดแต่ละประเด็นเพื่ออ่านรายละเอียดและแหล่งข้อมูล
ChatGPT Work เข้าถึงไฟล์ในเครื่องได้ตรวจสอบแล้ว / มีเงื่อนไข+
Astra ใช้โปรแกรมคอมพิวเตอร์ทำงานได้ตรวจสอบแล้ว / ไม่ใช่โปรแกรมตัดต่อในตัว+
ตัดเสร็จใน 5–10 นาทีทุกกรณียังพิสูจน์เป็นเกณฑ์ทั่วไปไม่ได้+
ถูกกว่าจ้างคน 10 เท่าต้องกำหนดต้นทุนให้เทียบกันได้+
หนึ่งไอเดีย สามรูปแบบคอนเทนต์
ปรับรูปแบบวิดีโอ แล้วดูกรอบภาพตัวอย่างและ Prompt เปลี่ยนตามแบบเรียลไทม์
ช่วยตัดต่อ?
พร้อมนำไปใช้กับ AI Agent
ตัวสร้าง Prompt นี้ไม่อัปโหลดคลิป ไม่เรียก API เสียเงิน และไม่ตัดต่อวิดีโอจริง ต้องใช้กับเครื่องมือที่ผู้ใช้อนุญาตภายหลัง
จำลองเวลาและต้นทุนของคุณเอง
เลื่อนตัวเลขเพื่อเปรียบเทียบสถานการณ์สมมติ ไม่ใช่ผล benchmark ที่ยืนยันแล้ว
ตัวเลขเป็นตัวอย่างเพื่อช่วยตัดสินใจ ไม่ใช่ผลประหยัดที่รับประกัน
AI ที่ตัดคลิปเป็น ไม่ได้ทำงานลำพัง
สิ่งที่น่าสนใจของ GPT-6 Astra และ GPT-6.1 Sol ไม่ได้อยู่ที่ว่าตัวโมเดลมีปุ่ม Render MP4 ซ่อนอยู่ แต่คือความสามารถในการจัดการงานหลายขั้นตอนร่วมกับเครื่องมืออื่น: อ่านไฟล์ วางลำดับเรื่อง ใช้แอป ตรวจผลลัพธ์ และแก้งานตามข้อเสนอแนะของมนุษย์
สำหรับคนทำคอนเทนต์ ความต่างสำคัญคือการเปลี่ยนจาก “ส่งคลิปให้ AI แล้วหวังว่าจะได้ผลงาน” ไปเป็น Workflow ที่ตรวจรับได้ทุกขั้น ตั้งแต่การเลือกช่วงเด็ด การสร้างซับ การตรวจคำผิด จนถึงการเรนเดอร์ไฟล์ตามสัดส่วนของแต่ละแพลตฟอร์ม
ข้อควรระวังคือระบบ Work ที่รันบนเว็บหรือมือถือไม่ได้หมายความว่า AI เข้าถึงคลิปบนคอมพิวเตอร์บ้านได้ทันที ต้องทำงานในสภาพแวดล้อมที่เปิดให้เข้าถึงไฟล์จริง มีเครื่องมือตัดต่อ และมีสิทธิ์ใช้งานอย่างชัดเจน
รวบรวมไฟล์ในโฟลเดอร์ที่เข้าถึงได้ ระบุสิทธิ์และข้อจำกัด
ให้ Agent เสนอ Hook, ช่วงตัด และโครงเรื่องก่อนตัดต่อ
ตรวจชื่อเฉพาะ ตัวเลข ภาษาไทย และความถูกต้องของคำกล่าวอ้าง
ตรวจความละเอียด เสียง ระยะเวลา safe zone และคำบรรยาย
Security: โมเดลเสนอได้ แต่ไม่ได้ออกสิทธิ์ให้ตัวเอง
Authentication ระบุตัวตน Authorization ระบุสิทธิ์ ตัวอย่าง public GET ไม่มี token จึงยังไม่เป็นบริการยืนยันผู้ใช้ ต้องออกแบบ per-user policy/rate limits/secrets เพิ่มเมื่อขยายระบบ
OWASP อธิบายว่าเนื้อหาจากภายนอกอาจแฝงคำสั่งที่เบี่ยงพฤติกรรมโมเดลได้ จึงต้องมองผลเครื่องมือเป็นข้อมูลที่ยังไม่ไว้วางใจ และไม่ใช้ข้อความนั้นเปลี่ยนสิทธิ์ของระบบ Prompt Injection ต้นทาง
ตัวอย่างกรองฟิลด์ ไม่ eval หรือใช้ข้อมูลเป็น shell command แต่ยังไม่พิสูจน์ว่าป้องกัน injection ครบ หากเพิ่ม README/เว็บ ต้องทดสอบข้อมูลแฝงก่อนให้สิทธิ์เขียนหรือส่งข้อความ
Agent ทุกบทบาทรับสิทธิ์จากแอป ไม่แจก token รวม และไม่ถือคำอนุมัติของ Agent อื่นเป็นคำอนุมัติของคน ระบุผู้อนุญาตและหลักฐานที่ตรวจได้ก่อนกระทำภายนอก
Logs, Traces และการวัดที่ยังไม่มี
ใช้รหัสงานเชื่อมคำขอ attempt ผลและเหตุหยุด เมื่อเพิ่ม worker ให้มีรหัสงานย่อย/งานแม่ เพื่อแยกว่าข้อมูลหายที่ผู้ส่ง ผู้รับ หรือผู้รวมผล
OpenTelemetry ใช้ spans แทนหน่วยงานและใช้ความสัมพันธ์เชื่อมเป็น trace ส่วน JSON events ของตัวอย่างเป็น log แบบกำหนดเอง ยังไม่ได้ติดตั้ง SDK/exporter หรือทดสอบ context propagation Traces ต้นทาง
แยกเวลาโมเดล เครื่องมือ คิวและคนอนุมัติ ค่าเฉลี่ยอาจซ่อน timeout ต้องผูก errors กับประเภทและจำนวนงาน ไม่เลือกเฉพาะรันที่ดีมาสรุป
ยังไม่มี integration/architecture benchmark จึงไม่มี latency, success rate หรือต้นทุนวัดจริง ตัวเลขจากโค้ดเมื่อผู้อ่านรันต้องผูก runtime และเงื่อนไขก่อนใช้เป็นหลักฐาน
ต้นทุน: เขียนวิธีคิดก่อนใส่ตัวเลข
ประมาณต้นทุนจาก token ของแต่ละ call ค่าเครื่องมือและทรัพยากร ระบุหน่วยราคา/จำนวน หากตั้งราคาเองให้เรียกสมมติฐาน หากยังไม่วัดใช้สูตรและรายการข้อมูลที่ต้องเก็บ
ต้นทุนประมาณการ = ผลรวม(token input × ราคาต่อหน่วย input
+ token output × ราคาต่อหน่วย output)
+ ค่าเครื่องมือ/บริการ + ทรัพยากรที่เกี่ยวข้อง
หลายบทบาทอาจเพิ่ม calls/บริบท แต่ไม่มีตัวคูณราคา/เวลาตายตัว เทียบงานที่ผ่านเกณฑ์เดียวกัน รวม retry และงานล้มเหลว ไม่สรุปการประหยัดจากจำนวน node
จาก Prototype สู่ Production: สิ่งที่ยังต้องพิสูจน์
- ระบุ Output Contract และข้อมูลที่ห้ามส่งออก ก่อนเพิ่มเครื่องมือหรือบทบาท
- ทดสอบ Input/Schema, ข้อมูลผิดรูปและสิทธิ์ โดยตรวจว่ากรณีปฏิเสธไม่เกิดการกระทำภายนอก
- แยกการ retry ที่ปลอดภัยจากการเรียกที่อาจเขียนสำเร็จไปแล้ว และออกแบบ duplicate prevention ตามผลกระทบจริง
- ทดสอบ rate-limit, timeout, การอ่านไม่ครบ, dependency failure และ partial success ที่ต้องส่งให้คน
- ออกแบบ state persistence และ recovery แล้วทดสอบ process interruption ไม่ใช้การมีไฟล์ checkpoint เป็นหลักฐานว่ากู้คืนถูก
- เก็บ logs/traces ที่เชื่อมกลับได้ พร้อมนโยบายข้อมูลส่วนบุคคลและ secret redaction
- เปรียบเทียบกับระบบง่ายกว่า ด้วยชุดงานและ acceptance เดียวกัน ก่อนเพิ่มหลาย Agent
- เตรียม README, configuration, resource limits, incident response และขอบเขต deploy ที่ได้รับอำนาจ
Deploy ต้องมีอำนาจและผู้รับผิดชอบ ไม่เริ่มเพิ่ม infrastructure จากภาพ Production แพลตฟอร์มสำเร็จรูปอาจรับภาระบางชั้น แต่ต้องตรวจสิทธิ์ state recovery หลักฐานและต้นทุนที่รองรับจริง
ตัวอย่างนี้ยังไม่มี hard deadline, persistent state, cross-worker idempotency, authenticated multi-user service, live LLM/MCP/OTel integration หรือผลทดสอบ failure/recovery จึงเป็นชิ้นส่วนเพื่อเรียนรู้และต่อยอด ไม่ใช้คำว่า Production Ready จากการอ่านโค้ดหรือกรณีสำเร็จที่ยังไม่ได้รัน
แบบฝึก: ปกป้องคำตัดสินใจของคุณด้วยหลักฐาน
ใช้โจทย์ public Repository report เดิม เขียน decision record เลือกหนึ่งโครงสร้างและอธิบายว่าทำไมอีกสองแบบยังไม่เหมาะหรือควรทดลองเพิ่ม จากนั้นเปลี่ยนเงื่อนไขเป็น “ต้องถามข้อมูลเพิ่มระหว่างงาน” หรือ “แบ่งบทบาทอ่านกับตรวจหลักฐานได้” แล้วระบุว่าสัญญาใดต้องเปลี่ยน โดยยังไม่รันหรือ deploy ตามแบบฝึกนี้
- ใช้ Input/Output เดียวกันทั้งสามทางเลือก และระบุสิ่งที่ metadata ยังตอบไม่ได้
- แปดส่วนมีผู้รับผิดชอบหรือเหตุผลว่าไม่จำเป็น ไม่มี storage หรือโมเดลที่เพิ่มโดยไม่มีโจทย์รองรับ
- แสดง data flow ผ่านตัวตรวจสิทธิ์ก่อนเครื่องมือ ไม่ให้คำเสนอของโมเดลข้าม gateway
- มีอย่างน้อยสาม failure cases พร้อม expected behavior และหลักฐานที่จะใช้ตรวจ ไม่กรอก actual result ที่ยังไม่รัน
- แยกเหตุผลเชิงออกแบบ เอกสารต้นทาง สมมติฐาน และสิ่งที่ยัง UNKNOWN/NOT RUN
คำตอบอาจต่างจากผู้เขียน แต่ต้องระบุความจำเป็นและวิธีพิสูจน์ ถ้าอ้างว่าเร็วหรือปลอดภัยกว่า ให้กำหนด baseline และเงื่อนไขการวัดก่อนกล่าวเป็นผลจริง
FAQ สำหรับผู้เริ่มสร้างระบบ Agent
ทุกระบบต้องมี LLM และ Vector Database หรือไม่?
ไม่ต้องเพิ่มส่วนเหล่านั้นโดยไม่มีหน้าที่ งานรายงานที่มีเส้นทางข้อมูลครบอาจใช้โค้ดธรรมดาได้ ส่วนความจำข้ามงานต้องเริ่มจากสิ่งที่ควรเก็บ อายุ สิทธิ์และวิธีตรวจความถูกต้อง ไม่เริ่มจากการเลือกฐานข้อมูลก่อนโจทย์
มี JSON Schema แล้วเชื่อคำตอบได้หรือยัง?
รูปแบบถูกเป็นเงื่อนไขหนึ่ง ยังต้องตรวจตัวตนของข้อมูล ที่มา สิทธิ์และข้อเท็จจริง การส่งข้อความที่เข้ารูปแบบไม่ได้พิสูจน์ว่าเรียก API สำเร็จหรือว่าข้อมูลตอบคำถามได้ครบ
ตัวอย่างนี้เรียก API จริงหรือเป็น Mock?
ไฟล์หลักเขียนเส้นทาง public GitHub GET จริงโดยต้องเปิด --live-read แต่ผู้เขียนไม่ได้รัน ส่วน unit tests ใช้ mock network และข้อมูลสังเคราะห์ ทั้ง integration และ tests จึง NOT RUN ไม่ใช่ผล Live ที่ยืนยันแล้ว
ใช้ Framework แล้วไม่ต้องเขียน Contract เองหรือไม่?
Framework อาจช่วยวงจรงานหรือ persistence แต่ผู้สร้างยังต้องกำหนดสิทธิ์ Input/Output และการรับผลของโจทย์ของตน ตรวจ docs/version ที่ใช้จริง และแยกความสามารถที่เอกสารระบุจากสิ่งที่ได้ติดตั้งและทดสอบในระบบ
เมื่อใดควรเพิ่ม Multi-Agent?
เขียนก่อนว่าบทบาทแยกทำอะไรและสื่อสารข้อมูลใดได้ แล้วออกแบบการทดลองกับงานเดียวและ baseline ที่ง่ายกว่า ถ้ายังอธิบายความจำเป็นหรือเกณฑ์ผลรวมไม่ได้ ให้ลดความซับซ้อนก่อน ไม่ใช้เสียงเห็นพ้องกันแทนหลักฐาน
References และ Source Code
ตรวจเอกสารต้นทางวันที่ 13 ตุลาคม 2026 ข้อค้นพบเป็น documented behavior ตามขอบเขตที่อ้าง ไม่ใช่ผลรันของตัวอย่าง ไม่มีการใช้บริการ Deep Research เฉพาะมาอ้างเป็นผลตรวจอิสระ
- Anthropic: แนวทางการสร้าง Agent
- LangGraph: รูปแบบ Workflow และ Agent
- LangGraph: Persistence
- MCP: Architecture รุ่นเอกสาร 2026-07-28
- GitHub: อ่าน Repository
- GitHub: การใช้ API และข้อผิดพลาด
- OpenTelemetry: Traces
- OWASP: Prompt Injection
- Python 3.12: urllib.request
- OpenAI: Function Calling
- OpenAI: Structured Outputs
Source Code ฉบับที่จัดทำอยู่ในส่วน Code Example ของหน้านี้ ได้แก่ไฟล์หลักและ synthetic tests พร้อมวิธีใช้ ทั้งสองไฟล์ยังไม่ได้ execute/import/compile โดยผู้เขียน ผล runtime, integration, failure/recovery, security และ performance จึง NOT RUN; optional browser UI QA ยังคง UNKNOWN

ใส่ความเห็น