DEV Community

Cover image for DESIGN.md คืออะไร สำหรับ Coding Agents
Thanawat Wongchai
Thanawat Wongchai

Posted on • Originally published at apidog.com

DESIGN.md คืออะไร สำหรับ Coding Agents

เอเจนต์เขียนโค้ดเร็วและมั่นใจ แต่ไม่รู้สถาปัตยกรรมของฐานโค้ดคุณจนกว่าคุณจะบอกมันอย่างชัดเจน ถ้าคุณให้ตั๋วงานกำกวมกับ Claude Code, Codex หรือ Cursor มันอาจสร้างโค้ดที่คอมไพล์ได้ ผ่านเทสต์ และดูดีใน diff แต่แอบละเมิดขอบเขตระหว่าง domain layer กับ HTTP layer ได้ง่ายมาก วิธีลดปัญหานี้คือเพิ่ม DESIGN.md ไว้ใน repo เพื่อบันทึกเจตนารมณ์ทางสถาปัตยกรรม กฎที่ห้ามละเมิด และเหตุผลเบื้องหลังการออกแบบไว้ในที่ที่เอเจนต์อ่านได้จริง

ลองใช้ Apidog วันนี้

TL;DR

DESIGN.md คือไฟล์ Markdown ใน repository ที่อธิบายว่า “ทำไมโค้ดถึงมีรูปร่างแบบนี้” สำหรับทั้งมนุษย์และเอเจนต์เขียนโค้ด เช่น Claude Code, Codex และ Cursor

ใช้มันเพื่อบันทึก:

  • ขอบเขต layer/module
  • invariant ที่ห้ามละเมิด
  • decision สำคัญและเหตุผล
  • pattern ที่เลือกใช้
  • pattern ที่ปฏิเสธแล้ว
  • กฎ API contract, OpenAPI, error model, idempotency และ tenancy

AGENTS.md ตอบว่า “จะ build/test/lint อย่างไร” ส่วน DESIGN.md ตอบว่า “ทำไมระบบถูกออกแบบแบบนี้ และอะไรห้ามพัง”

บทนำ

รูปแบบความล้มเหลวที่ทีมส่วนใหญ่เจอเมื่อเริ่มใช้ coding agent คือ: คุณขอให้เพิ่ม endpoint refund ใน payment service แล้วเอเจนต์สร้าง handler ที่ใช้งานได้ แต่เรียก database จาก controller โดยตรง กลืน gateway error และสร้าง type สำหรับเงินขึ้นมาใหม่ ทั้งที่ใน domain มีอยู่แล้ว

ปัญหาไม่ใช่ว่าเอเจนต์เขียนโค้ดไม่เก่ง แต่คือมันมองไม่เห็น decision ที่อยู่ในหัว senior engineer, ใน Notion หรือใน Slack thread เมื่อหลายเดือนก่อน

DESIGN.md แก้ปัญหานี้ด้วยการทำให้ decision เหล่านั้นกลายเป็นไฟล์ที่อ่านได้ใน repo เดียวกับโค้ด เช่น:

  • “Domain layer ห้าม import web framework”
  • “เงินต้องเก็บเป็น integer minor unit เท่านั้น”
  • “ห้ามเรียก payment gateway จาก request thread ให้ใช้ outbox”
  • “OpenAPI spec คือ source of truth”
  • “Generated types ห้ามแก้ด้วยมือ”

DESIGN.md คืออะไร

DESIGN.md คือเอกสารสั้นๆ ที่บอกเหตุผลทางสถาปัตยกรรมของระบบ ไม่ใช่ README และไม่ใช่คู่มือการรันโปรเจกต์

ให้คิดว่ามันคือสิ่งที่ senior engineer จะพูดกับ engineer ใหม่ก่อนให้แก้โค้ดสำคัญ เช่น:

เราไม่เรียก payment gateway จาก request handler ทุกอย่างต้องผ่าน outbox เพราะ gateway timeout ภายใต้ load

เงินเป็น integer minor unit เสมอ ห้ามใช้ float เพราะเคยเกิด rounding bug

Account aggregate เป็น write path เดียวของ ledger ห้ามเขียน ledger จาก service อื่นโดยตรง

ซอร์สโค้ดแสดง “ผลลัพธ์” ของ decision แต่ไม่แสดง “เหตุผล” และ “ข้อห้าม” เอเจนต์อาจเห็นว่า Account.debit() มีอยู่ แต่ไม่รู้ว่ามันตั้งใจให้เป็น write path เดียว จึงอาจเพิ่มอีก path ได้ถ้าไม่มีเอกสารบอก

แนวคิดนี้ใกล้กับ ARCHITECTURE.md และ ADRs แต่เขียนให้เหมาะกับโลกที่ coding agent อ่าน repo ด้วย:

  • อยู่ใน root repo
  • เป็น Markdown ธรรมดา
  • สั้นและเป็น declarative
  • เน้น decision และ invariant
  • อ้างอิงได้จาก AGENTS.md หรือ CLAUDE.md

DESIGN.md กับ AGENTS.md กับ CLAUDE.md กับ README

ไฟล์เหล่านี้มีหน้าที่ต่างกัน:

ไฟล์ ผู้ชม ตอบคำถาม อัตราการเปลี่ยนแปลง ความยาว
README.md มนุษย์ โปรเจกต์นี้คืออะไร เริ่มใช้อย่างไร เปลี่ยนตามฟีเจอร์ ปานกลาง
AGENTS.md coding agent ใดๆ build, test, lint, commit อย่างไร เปลี่ยนตาม tooling สั้น
CLAUDE.md Claude Code คำสั่งเฉพาะ Claude หรือ import จาก AGENTS.md เปลี่ยนตาม tooling สั้น
DESIGN.md เอเจนต์ + วิศวกร + reviewer ทำไมระบบออกแบบแบบนี้ อะไรห้ามพัง เปลี่ยนตามสถาปัตยกรรม ปานกลาง

AGENTS.md เป็นรูปแบบที่แพร่หลายแล้ว โครงการ agents.md อธิบายว่าเป็นรูปแบบเปิดสำหรับนำทาง coding agent โดยเน้นเรื่อง operation เช่น build command, test command, style guide และ workflow

สำหรับ Claude Code เอกสาร Claude Code memory แนะนำให้ใช้ CLAUDE.md เป็นไฟล์คำสั่งเฉพาะ Claude และถ้ามี AGENTS.md อยู่แล้ว สามารถให้ CLAUDE.md import ด้วย @AGENTS.md

สิ่งที่ไม่ควรยัดลง AGENTS.md หรือ CLAUDE.md คือคำอธิบายสถาปัตยกรรมยาวๆ เพราะไฟล์เหล่านี้ควรสั้น เอกสาร Claude Code ยังแนะนำให้รักษา CLAUDE.md ให้ต่ำกว่า ~200 บรรทัด เพื่อไม่ให้กิน context และลดโอกาสที่โมเดลจะทำตาม

โครงสร้างที่แนะนำ:

README.md     -> สำหรับมนุษย์
AGENTS.md    -> build/test/lint/style สำหรับเอเจนต์
CLAUDE.md    -> @AGENTS.md + คำสั่งเฉพาะ Claude
DESIGN.md    -> สถาปัตยกรรม, invariant, decision
Enter fullscreen mode Exit fullscreen mode

ตัวอย่าง AGENTS.md:

# AGENTS.md

## Commands

- Install: `pnpm install`
- Test: `pnpm test`
- Lint: `pnpm lint`

## Architecture

อ่าน `DESIGN.md` ก่อนแก้โค้ดที่แตะ layer boundary, domain model,
API contract, database transaction หรือ external integration
Enter fullscreen mode Exit fullscreen mode

ตัวอย่าง CLAUDE.md:

@AGENTS.md

อ่าน @DESIGN.md ก่อนเสนอการเปลี่ยนแปลงเชิงสถาปัตยกรรม
Enter fullscreen mode Exit fullscreen mode

ถ้าคุณต้องการรายละเอียดเรื่องการจัด context สำหรับ Claude Code เพิ่มเติม อ่าน เวิร์กโฟลว์ Claude Code

ควรใส่อะไรใน DESIGN.md

DESIGN.md ควรตอบคำถามที่เอเจนต์อนุมานจากโค้ดไม่ได้:

  • ระบบแบ่ง layer/module อย่างไร
  • dependency ไหลไปทางไหน
  • invariant ใดต้องจริงเสมอ
  • decision สำคัญคืออะไร และทำไม
  • alternative ใดถูกปฏิเสธแล้ว
  • API contract อยู่ที่ไหน
  • generated code แก้ได้หรือไม่
  • transaction boundary อยู่ตรงไหน
  • code ใหม่ควรไปอยู่ที่ใด
  • ไฟล์หรือ module ใดห้ามแตะ

เขียนให้เป็นกฎที่ reviewer ใช้ enforce ได้ ไม่ใช่บทความยาวๆ

Template สำหรับ backend/API service

คัดลอก template นี้ไปไว้ที่ root repo เป็น DESIGN.md แล้วแก้ให้ตรงกับระบบของคุณ

# DESIGN.md: Payments API Service

ไฟล์นี้บันทึกเจตนารมณ์ทางสถาปัตยกรรมของระบบ
อ่านก่อนแก้โค้ดที่เกี่ยวกับ domain, API contract, transaction,
external integration หรือ data model

ถ้าคำขอขัดแย้งกับกฎในไฟล์นี้ ให้หยุดและแจ้ง conflict
อย่า workaround เงียบๆ

## System shape

ระบบแบ่งเป็น layer ดังนี้:

http -> app -> domain <- infra

- `http/` มี routes, handlers, DTOs
- `app/` มี use cases และ ports
- `domain/` มี entities, value objects และ invariants
- `infra/` มี database, queues และ external clients

Dependency rules:

- `domain/` ห้าม import `http/`, `app/`, `infra/` หรือ web framework
- `http/` ห้ามเรียก database หรือ payment gateway โดยตรง
- `http/` ต้องเรียก use case ใน `app/`
- `infra/` implement interface ที่ประกาศใน `app/ports/`

## Invariants

- Ledger entry เปลี่ยนไม่ได้หลังเขียนแล้ว
  การแก้ไขต้องสร้าง compensating entry ใหม่
- Account balance คำนวณจาก ledger entries
  ห้ามเก็บเป็น mutable field ที่ตั้งค่าโดยตรง
- Money เป็น integer minor unit + ISO-4217 currency code
  ห้ามใช้ float หรือ decimal สำหรับเงิน
- External payment gateway call ทุกครั้งต้องมี `idempotency_key`
- Retry ต้องไม่ทำให้เกิด double charge
- Account balance ห้ามติดลบ ยกเว้น `OverdraftPolicy` อนุญาตชัดเจน

## Key decisions

### Outbox สำหรับ gateway calls

Request handler ต้องเขียน intent ลง outbox ภายใน DB transaction เดียวกับ business change
จากนั้น worker จึงเรียก payment gateway

เหตุผล:

- Gateway timeout ได้ภายใต้ load
- Inline call ทำให้ request latency สูง
- Error handling และ retry ควบคุมยาก

ห้ามเรียก payment gateway จาก request handler โดยตรง

### Single write path ต่อ aggregate

เฉพาะ `Account.post_entry()` เท่านั้นที่เขียน ledger entry ได้

เหตุผล:

- เคยเกิด balance mismatch จาก write path ที่สอง
- ทุก business rule ของ account ต้องผ่าน aggregate เดียวกัน

เพิ่ม behavior ใหม่เป็น method บน aggregate ไม่ใช่ service ที่เขียน ledger โดยตรง

### Event sourcing เฉพาะ ledger

Ledger ใช้ append-only/event style
ส่วนอื่นของระบบใช้ CRUD ตามปกติ

เหตุผล:

- เงินต้องมี audit trail สมบูรณ์
- Event sourcing ทั้งระบบมี cost สูงเกินจำเป็น

## Rejected alternatives

ห้ามนำ pattern เหล่านี้กลับมาใช้ใหม่โดยไม่แก้ `DESIGN.md` ก่อน:

- ORM lazy-loading ข้าม aggregate
  เพราะทำให้เกิด N+1 และ transaction boundary ไม่ชัด
- การเก็บ balance เป็น column ที่ update โดยตรง
  เพราะทำให้ balance mismatch ได้
- การใช้ money library ภายนอกแบบ generic
  ให้ใช้ `domain/money.py`
- Synchronous webhook ไป merchant จาก request thread
  ให้ใช้ notification queue แทน

## Data and domain rules

- Timestamp ทั้งหมดเป็น UTC
- Database ใช้ `timestamptz`
- API response format ใช้ RFC 3339
- ห้ามส่ง timezone-naive datetime ข้าม function boundary
- ID เป็น ULID ที่สร้างใน app layer
- ห้ามใช้ DB autoincrement เป็น public ID
- ไม่มี soft delete
  record ต้อง active หรือถูกย้ายไป archive table ผ่าน use case ชัดเจน
- ทุก query ต้อง scope ด้วย `tenant_id`
- Repository method ที่ไม่มี tenant scope ถือเป็น bug

## API contract

- OpenAPI 3.1 spec อยู่ที่ `api/openapi.yaml`
- `api/openapi.yaml` คือ source of truth ของ request/response schema
- Types ใน `http/generated/` ถูก generate จาก OpenAPI
- ห้ามแก้ generated types ด้วยมือ
- Endpoint ใหม่ต้องอัปเดต OpenAPI ก่อน implement
- Error response ใช้ RFC 9457 `application/problem+json`
- ใช้ helper `problem()`
- ห้ามสร้าง error envelope เฉพาะ endpoint

## Where new code goes

- New endpoint:
  - route: `http/routes/`
  - DTO: `http/dto/`
  - use case: `app/usecases/`
  - domain logic: `domain/`

- New external integration:
  - interface: `app/ports/`
  - implementation: `infra/clients/`

- Cross-cutting concern:
  - auth/logging/idempotency: `http/middleware/`
  - ห้าม inline ใน handler

## Out of scope / do not touch

- `http/generated/`
  - generate จาก OpenAPI เท่านั้น
  - manual edit จะถูกเขียนทับ
- `legacy/billing_v1/`
  - frozen และกำลัง migrate
  - ห้ามเพิ่ม feature ใหม่
- `migrations/`
  - ห้ามแก้ migration ที่ apply แล้ว
  - ให้เพิ่ม migration ใหม่เท่านั้น

## When in doubt

ถ้าคำขอจำเป็นต้องละเมิดกฎข้างต้น
ให้แจ้ง conflict และเสนอทางเลือกที่สอดคล้องกับ design
อย่าเลี่ยงกฎเงียบๆ
Enter fullscreen mode Exit fullscreen mode

ส่วน When in doubt สำคัญมาก เพราะมันเปลี่ยน DESIGN.md จากเอกสาร passive เป็น guardrail เชิงปฏิบัติ เอเจนต์จะมี instruction ชัดเจนว่าเมื่อคำขอขัดกับ design ต้อง raise conflict ไม่ใช่ทำ workaround

วิธีทำให้เอเจนต์อ่าน DESIGN.md

เอเจนต์ไม่ได้มี parser พิเศษสำหรับ DESIGN.md มันอ่านไฟล์นี้เหมือนไฟล์อื่นใน repo ดังนั้นคุณต้องทำให้มันถูกโหลดหรือถูกอ้างอิงอย่างสม่ำเสมอ

สำหรับ Claude Code

ใน CLAUDE.md:

@AGENTS.md
@DESIGN.md

ถ้าการเปลี่ยนแปลงแตะ architecture, domain model, API contract,
database transaction หรือ external integration ให้ตรวจสอบกฎใน DESIGN.md ก่อน
Enter fullscreen mode Exit fullscreen mode

หรือถ้าต้องการให้ CLAUDE.md สั้นมาก:

@AGENTS.md

อ่าน @DESIGN.md ก่อนแก้โค้ดเชิงสถาปัตยกรรม
Enter fullscreen mode Exit fullscreen mode

สำหรับ agent ที่อ่าน AGENTS.md

ใน AGENTS.md:

## Architecture guardrails

อ่าน `DESIGN.md` ก่อนทำงานที่เกี่ยวกับ:

- layer boundary
- domain invariant
- API contract
- OpenAPI schema
- generated code
- database transaction
- external integration
- idempotency
- tenancy
Enter fullscreen mode Exit fullscreen mode

อย่าคัดลอกเนื้อหา DESIGN.md ทั้งหมดไปไว้ใน AGENTS.md เพราะจะทำให้ไฟล์ operation ยาวเกินไป ให้ใช้การอ้างอิงแทน

วิธีใช้ DESIGN.md ใน workflow จริง

1. ตอนสร้าง feature

Prompt ที่ดี:

เพิ่ม endpoint POST /refunds ตาม OpenAPI spec
ก่อน implement ให้อ่าน DESIGN.md และระบุว่ากฎใดเกี่ยวข้องกับงานนี้
Enter fullscreen mode Exit fullscreen mode

Expected behavior:

  • เอเจนต์เปิด DESIGN.md
  • เห็นว่า OpenAPI เป็น source of truth
  • เห็นว่า payment gateway ต้องผ่าน outbox
  • เห็นว่า money ต้องใช้ domain money type
  • ไม่สร้าง handler ที่เรียก gateway ตรงๆ

2. ตอน review diff

ถ้าเอเจนต์ละเมิด design ให้ feedback โดยอ้าง rule:

Diff นี้ละเมิด DESIGN.md:
- http handler เรียก payment gateway โดยตรง
- gateway calls ต้องผ่าน outbox

แก้ implementation ให้ handler เขียน outbox intent
และให้ worker เป็นคนเรียก gateway
Enter fullscreen mode Exit fullscreen mode

การอ้าง rule ที่ชัดเจนช่วยให้เอเจนต์แก้รอบถัดไปได้ตรงจุดมากกว่าการบอกว่า “ทำให้สะอาดขึ้น”

3. ตอนเปลี่ยนสถาปัตยกรรม

ถ้าทีมตัดสินใจเปลี่ยน rule เช่น จาก outbox เป็น synchronous gateway call ในบางกรณี ให้แก้ DESIGN.md ใน PR เดียวกับโค้ด

เพิ่ม checklist ใน PR template:

## Design impact

- [ ] PR นี้ไม่เปลี่ยน architecture decision
- [ ] PR นี้เปลี่ยน architecture decision และอัปเดต DESIGN.md แล้ว
- [ ] PR นี้เพิ่ม external dependency และอธิบายไว้ใน DESIGN.md แล้ว
Enter fullscreen mode Exit fullscreen mode

Anti-patterns ที่ควรหลีกเลี่ยง

1. เขียนซ้ำสิ่งที่โค้ดบอกได้อยู่แล้ว

ไม่ควรเขียน:

UserService จัดการ user
Enter fullscreen mode Exit fullscreen mode

เพราะเอเจนต์อ่านได้จากไฟล์อยู่แล้ว

ควรเขียน:

User aggregate เป็นเจ้าของ email verification state
ห้าม service อื่น update `email_verified_at` โดยตรง
Enter fullscreen mode Exit fullscreen mode

2. ใส่ tutorial หรือ command มากเกินไป

DESIGN.md ไม่ใช่ CONTRIBUTING.md

อย่าใส่:

รัน npm install
รัน npm test
วิธี create branch
Enter fullscreen mode Exit fullscreen mode

เรื่องพวกนี้ควรอยู่ใน AGENTS.md, README.md หรือ CONTRIBUTING.md

3. เขียนสิ่งที่อยากให้เป็น แต่ยังไม่จริง

ไม่ควรเขียน:

ระบบใช้ CQRS
Enter fullscreen mode Exit fullscreen mode

ถ้าครึ่งหนึ่งของระบบยังไม่ใช่ CQRS

ควรเขียน:

เป้าหมาย: write path ใหม่ทั้งหมดต้องผ่าน use case
สถานะปัจจุบัน: `legacy/` ยัง bypass use case อยู่
ห้ามขยาย pattern ใน `legacy/`
Enter fullscreen mode Exit fullscreen mode

4. ไม่มี owner และไม่มี review trigger

DESIGN.md จะเสื่อมเร็วถ้าไม่มีใครดูแล

กำหนด owner เช่น:

Owner: Platform/API team
Review required เมื่อ PR:
- เพิ่ม module ใหม่
- เปลี่ยน layer boundary
- เพิ่ม external dependency
- เปลี่ยน API contract
- เปลี่ยน transaction model
Enter fullscreen mode Exit fullscreen mode

5. พยายาม sync กับโค้ดแบบบรรทัดต่อบรรทัด

อย่าทำให้ DESIGN.md เป็น mirror ของโค้ด เพราะจะล้าสมัยเร็ว ให้เก็บเฉพาะ decision ที่เปลี่ยนไม่บ่อย เช่น invariant, boundary, contract และ trade-off

6. ขัดแย้งกับ AGENTS.md

ถ้า AGENTS.md บอก error response แบบหนึ่ง แต่ DESIGN.md บอกอีกแบบ เอเจนต์จะสับสน

แบ่งหน้าที่ให้ชัด:

  • AGENTS.md: command, workflow, style
  • DESIGN.md: architecture, invariant, decision
  • CLAUDE.md: Claude-specific instruction หรือ import

DESIGN.md สำหรับ API และ backend

Backend/API codebase ได้ประโยชน์จาก DESIGN.md มากเป็นพิเศษ เพราะมีข้อจำกัดที่มองไม่เห็นจากไฟล์เดียว เช่น:

  • API contract
  • transaction boundary
  • idempotency
  • retry behavior
  • external gateway
  • tenant isolation
  • generated code
  • error model
  • pagination
  • breaking change policy

ระบุว่า OpenAPI คือ source of truth

เพิ่มกฎนี้ใน DESIGN.md:

## API contract

- OpenAPI spec อยู่ที่ `api/openapi.yaml`
- OpenAPI คือ source of truth ของ request/response schema
- Types ใน `http/generated/` generate จาก OpenAPI
- ห้ามแก้ generated types ด้วยมือ
- Endpoint ใหม่ต้องอัปเดต OpenAPI ก่อน implement
Enter fullscreen mode Exit fullscreen mode

ถ้าคุณออกแบบ API แบบ contract-first ใน Apidog แล้ว export OpenAPI เข้า repo ให้ชี้ไฟล์นั้นใน DESIGN.md โดยตรง เอเจนต์จะ implement ตาม spec แทนที่จะเดา schema เอง

อ่านเพิ่มเรื่อง contract-first กับ agent ได้ที่ การออกแบบ API สำหรับเอเจนต์ AI

ระบุ transaction boundary

ตัวอย่าง:

External API call ห้ามเกิดภายใน DB transaction
ถ้าต้องเรียก gateway ให้เขียน outbox record ใน transaction
แล้วให้ worker เป็นคนเรียก gateway
Enter fullscreen mode Exit fullscreen mode

ถ้าไม่เขียน rule นี้ เอเจนต์มักจะ implement แบบตรงไปตรงมา เช่น เปิด transaction แล้วเรียก gateway ข้างใน ซึ่งอาจทำให้ lock ค้างหรือ retry ยาก

ระบุ idempotency

ตัวอย่าง:

Endpoint ที่สร้าง payment, refund, order หรือ provisioning job
ต้องรับและ persist `idempotency_key`

Retry ด้วย key เดิมต้องคืนผลลัพธ์เดิม
ห้ามสร้าง charge หรือ refund ซ้ำ
Enter fullscreen mode Exit fullscreen mode

ระบุ error model

ตัวอย่าง:

Error response ทั้งหมดใช้ RFC 9457 problem+json
ผ่าน helper `problem()`

ห้ามสร้าง error envelope เฉพาะ endpoint
Enter fullscreen mode Exit fullscreen mode

ถ้าไม่ระบุ คุณจะได้ error response หลายแบบใน API เดียวกัน

ระบุ tenancy boundary

ตัวอย่าง:

ทุก query ต้อง scope ด้วย `tenant_id`
Repository method ที่ไม่มี tenant scope ถือเป็น bug
ห้ามรับ `tenant_id` จาก request body
ให้ derive จาก authenticated context เท่านั้น
Enter fullscreen mode Exit fullscreen mode

นี่คือ security invariant ที่เอเจนต์อนุมานจาก query เดี่ยวๆ ได้ยาก

ระบุ breaking change policy

ตัวอย่าง:

Breaking changes:

- ลบ field response
- เปลี่ยน type ของ field
- เปลี่ยน meaning ของ enum
- เปลี่ยน error code
- เปลี่ยน pagination contract

Breaking change ต้องเพิ่ม API version ใหม่
ห้ามแก้ behavior เดิมใน minor release
Enter fullscreen mode Exit fullscreen mode

เอเจนต์มักเปลี่ยนชื่อ field หรือปรับ response shape เพื่อ “ทำให้ดูดีขึ้น” ถ้าไม่มี rule นี้

หากต้องการให้เอเจนต์ทดสอบ endpoint ที่เพิ่งสร้างกับ contract จริง ใช้ workflow ที่ DESIGN.md ชี้ไปยัง OpenAPI spec และใช้เครื่องมืออย่าง ดาวน์โหลด Apidog เพื่อออกแบบ API แบบ design-first, export OpenAPI และตรวจสอบว่า implementation ตรงกับ contract

Checklist สำหรับเริ่มใช้ใน repo วันนี้

ทำตามขั้นตอนนี้:

  1. สร้าง DESIGN.md ที่ root repo
  2. ใส่หัวข้อขั้นต่ำ:
    • System shape
    • Invariants
    • Key decisions
    • Rejected alternatives
    • API contract
    • Where new code goes
    • Do not touch
    • When in doubt
  3. เพิ่ม pointer ใน AGENTS.md
  4. เพิ่ม @DESIGN.md หรือ reference ใน CLAUDE.md
  5. เพิ่ม PR checklist ว่าต้องอัปเดต DESIGN.md เมื่อเปลี่ยน decision
  6. ใช้ review comment ที่อ้าง rule จาก DESIGN.md
  7. ลบเนื้อหาที่ซ้ำกับโค้ดหรือ command ออกจาก DESIGN.md

สรุป

  • DESIGN.md บันทึก “ทำไม” โค้ดจึงถูกออกแบบแบบนี้
  • มันเสริม AGENTS.md และ CLAUDE.md ไม่ใช่แทนที่
  • เขียนเป็นกฎ declarative ที่ enforce ได้
  • ใส่ invariant, decision, rejected alternatives และ API contract
  • สำหรับ backend/API ให้ระบุ OpenAPI spec เป็น source of truth
  • อ้าง DESIGN.md จากไฟล์ที่เอเจนต์โหลดอยู่แล้ว
  • รักษาไฟล์ให้สั้น มี owner และอัปเดตเมื่อ decision เปลี่ยน
  • ถ้าใช้ design-first API workflow ให้ ดาวน์โหลด Apidog เพื่อออกแบบ API, export OpenAPI และให้ DESIGN.md ชี้ไปยัง contract นั้น

คำถามที่พบบ่อย

DESIGN.md เป็นมาตรฐานทางการเหมือน AGENTS.md หรือไม่?

ไม่ใช่ AGENTS.md เป็นรูปแบบที่ถูกกำหนดและใช้งานแพร่หลายมากกว่า ส่วน DESIGN.md เป็น convention ของทีม คล้าย ARCHITECTURE.md หรือ ADRs ใช้เมื่อมันช่วยให้ทีมและเอเจนต์เข้าใจ architecture decision ได้ดีขึ้น

จำเป็นต้องมี DESIGN.md ไหมถ้ามี AGENTS.md แล้ว?

ถ้าระบบมีข้อจำกัดทางสถาปัตยกรรมที่เอเจนต์เดาไม่ได้ ควรมี

AGENTS.md เหมาะกับ command และ workflow ส่วน DESIGN.md เหมาะกับ invariant และ decision เชิงลึก ถ้าต้องการเขียน AGENTS.md ให้ดี อ่าน วิธีการเขียนไฟล์ AGENTS.md

DESIGN.md ต่างจาก ARCHITECTURE.md อย่างไร?

แนวคิดใกล้กัน แต่ DESIGN.md มักเขียนให้ coding agent อ่านง่ายกว่า:

  • declarative มากกว่า
  • เน้น invariant มากกว่า
  • ระบุ rejected alternatives
  • อ้างจาก AGENTS.md หรือ CLAUDE.md
  • ใช้เป็น guardrail ใน agent workflow

บางทีมใช้ชื่อ ARCHITECTURE.md แทนก็ได้ หลักสำคัญคือเนื้อหาและการถูกอ้างอิงจาก agent instruction

DESIGN.md ควรยาวแค่ไหน?

ยาวพอที่จะครอบคลุม decision ที่เอเจนต์มักทำผิด แต่สั้นพอที่ทุกบรรทัดมีค่า

แนวทางที่ดี:

  • 2-4 หน้า Markdown
  • ใช้ heading และ bullet
  • หลีกเลี่ยง paragraph ยาว
  • ไม่ใส่ tutorial
  • ไม่เขียนซ้ำโค้ด

จะทำให้เอเจนต์อ่านมันได้อย่างไร?

อ้างจากไฟล์ที่เอเจนต์โหลดอยู่แล้ว:

สำหรับ Claude Code:

@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

สำหรับ AGENTS.md:

อ่าน DESIGN.md ก่อนแก้ architecture, API contract, transaction หรือ domain model
Enter fullscreen mode Exit fullscreen mode

เอเจนต์จะทำตาม DESIGN.md เสมอไหม?

ไม่เสมอไป DESIGN.md เป็น context ไม่ใช่ enforcement mechanism

แต่คุณเพิ่มโอกาสให้มันทำตามได้ด้วยการ:

  • เขียน rule ให้ชัด
  • ใช้คำว่า “ห้าม” กับสิ่งที่ห้ามจริง
  • เพิ่ม section “When in doubt”
  • ใช้ review comment อ้าง rule
  • เพิ่ม automated tests หรือ lint rules สำหรับ invariant ที่ตรวจได้

DESIGN.md ช่วยเรื่อง API contract จริงไหม?

ช่วยมาก โดยเฉพาะถ้าระบุว่า OpenAPI spec เป็น source of truth และ generated types ห้ามแก้ด้วยมือ

ถ้าออกแบบ API ใน Apidog แล้ว export OpenAPI เข้า repo ให้ DESIGN.md ชี้ไปที่ไฟล์นั้น เอเจนต์จะมี contract ชัดเจนสำหรับ implement และ test

ควรวาง DESIGN.md ไว้ที่ไหน?

วางที่ root repo ถัดจาก README.md และ AGENTS.md

ใน monorepo ใช้ได้สองระดับ:

/DESIGN.md                  -> กฎทั้งระบบ
/services/payments/DESIGN.md -> กฎเฉพาะ payments service
/packages/auth/DESIGN.md     -> กฎเฉพาะ auth package
Enter fullscreen mode Exit fullscreen mode

ให้สะท้อนวิธีที่เอเจนต์ค้นหา context ใกล้กับพื้นที่ที่มันกำลังแก้โค้ดอยู่

Top comments (0)