คู่มือ

ความจำของ AI agent ระหว่างเซสชัน: ไฟล์ความคืบหน้า บันทึกการตัดสินใจ git และสคริปต์ init

อัปเดต: · Skillaria.Top

AI agent ไม่มีความจำระหว่างเซสชัน สิ่งที่ไม่ได้เขียนลงไฟล์ในรีโพซิทอรี เซสชันใหม่จะไม่รู้เลย จึงสร้างความจำของ AI agent จากสิ่งประดิษฐ์ ได้แก่ PROGRESS.md (ตอนนี้เราอยู่ตรงไหน) DECISIONS.md (ทำไมจึงเลือกแบบนี้และอะไรถูกปฏิเสธ) git commit ที่อธิบายเจตนา และโปรโตคอลส่งต่องานใน AGENTS.md ที่สั่งให้อ่านตอนเริ่มและอัปเดตตอนจบ พร้อมสคริปต์ init ที่ตรวจสภาพแวดล้อมและแสดงสถานะปัจจุบัน

ทำไม agent ถึงไม่จำอะไรเลย

โมเดลไม่เก็บสถานะระหว่างการรันแต่ละครั้ง สิ่งที่ agent "รู้" เกี่ยวกับงานของคุณอยู่ในหน้าต่างบริบทของเซสชันปัจจุบันเท่านั้น ได้แก่ ไฟล์ที่อ่าน ผลลัพธ์ของคำสั่ง และบทสนทนากับคุณ เมื่อเซสชันปิดหรือบริบทเต็ม เซสชันใหม่จะเริ่มจากศูนย์ และเห็นเพียงสิ่งที่ถูกเขียนลงดิสก์เท่านั้น

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

ดังนั้นความจำของ AI agent จึงไม่ใช่คุณสมบัติของโมเดล แต่เป็นส่วนหนึ่งของ harness คือชุดไฟล์และกฎที่คุณออกแบบเอง ข่าวดีคือไม่จำเป็นต้องใช้ vector database หรือบริการพิเศษใด ๆ แค่ไฟล์ Markdown ไม่กี่ไฟล์ git และวินัยก็เพียงพอ

ทำไมหน้าต่างบริบทที่ใหญ่ขึ้นไม่ช่วยแก้ปัญหา

อาจดูเหมือนว่าแค่รอโมเดลที่มีหน้าต่างใหญ่กว่าก็พอ แต่งานที่ซับซ้อนจะเติมหน้าต่างไม่ว่าจะใหญ่แค่ไหน agent อ่านโค้ดเบสทั้งหมด สะสมประวัติการตัดสินใจ รับผลลัพธ์เทสต์ที่ยืดยาว และเก็บบทสนทนาทั้งหมดไว้ ความต้องการโตขึ้นพร้อมกับหน้าต่าง นี่คือปัญหาเชิงสถาปัตยกรรม ไม่ใช่เรื่องของขนาด

ยังมีผลกระทบอีกอย่าง เมื่อใกล้ขอบของหน้าต่าง โมเดลหลายตัวเริ่มรีบให้จบ มันข้ามการตรวจสอบและเลือกทางง่ายแทนทางที่ถูกต้อง Anthropic อธิบายการสังเกตนี้ในโมเดลของตนเอง และความเข้มข้นของผลต่างกันไปในแต่ละโมเดล เซสชันที่ยาวจนชนขอบบริบทจึงมีความเสี่ยงสองอย่าง คือการสูญเสียข้อมูล และการที่คุณภาพของงานแย่ลง

Compaction: อะไรถูกเก็บไว้ และอะไรหายไป

Compaction คือการบีบส่วนต้นของบทสนทนาให้เป็นสรุปสั้น ๆ เพื่อเพิ่มพื้นที่ในเซสชันเดิม ใน Claude Code ทำได้ด้วยคำสั่ง /compact และการบีบอัดยังเกิดขึ้นอัตโนมัติเมื่อใกล้ถึงขีดจำกัด ส่วนคำสั่ง /clear ล้างประวัติและเริ่มบทสนทนาใหม่

ปัญหาของ compaction คือสรุปมักเก็บ "อะไร" และทำให้ "ทำไม" หายไป โค้ดที่เขียนเสร็จยังคงอยู่ในไฟล์ แต่เหตุผล เช่น ทำไมเลือกตัวเลือก ข ทำไมไม่ใช้ไลบรารีนั้น ทำไมตั้งใจข้ามการปรับแต่ง จะถูกบีบจนเหลือแค่ไม่กี่คำหรือหายไปเลย ขั้นตอนถัดไปของ agent จึงไป "ปรับปรุง" การตัดสินใจที่ตั้งใจไว้ เพราะไม่เห็นเหตุผลอีกต่อไป

Compactionรีเซ็ต (เซสชันใหม่)
สิ่งที่เกิดขึ้นส่วนต้นของบทสนทนาถูกแทนที่ด้วยสรุปเซสชันปิด เซสชันใหม่อ่านไฟล์สถานะ
สิ่งที่ถูกเก็บสิ่งที่โมเดลเห็นว่าสำคัญระหว่างการบีบเฉพาะสิ่งที่คุณเขียนลงไฟล์เท่านั้น
ความรีบเมื่อใกล้ขอบหน้าต่างอาจยังคงอยู่ถูกรีเซ็ต
เหมาะเมื่องานจะพอดีกับเซสชันปัจจุบันแน่นอนขอบเขตของงานยาวหรือไม่ชัดเจน

กฎปฏิบัติง่าย ๆ ที่ไม่ต้องใช้ตัวชี้วัดซับซ้อน: เมื่องานใช้หน้าต่างไปราว 60% ให้หยุดเขียนโค้ดและเตรียมการส่งต่องาน แต่ถ้าบริบทใช้ไปเพียง 40% และงานใกล้จะเสร็จแล้ว compaction ก็เพียงพอ

สี่สิ่งประดิษฐ์ที่ประกอบเป็นความจำของ agent

แทนที่จะหวังพึ่งความจำของโมเดล ให้สร้างสมุดบันทึกประจำ มันมีสี่ส่วน และแต่ละส่วนมีบทบาทของตัวเอง

  1. PROGRESS.md ตอนนี้เราอยู่ตรงไหน
  2. DECISIONS.md ทำไมจึงทำแบบนี้ ไม่ใช่แบบอื่น
  3. git commit จุดตรวจสถานะที่ไม่เสียค่าใช้จ่าย
  4. โปรโตคอลการส่งต่องานใน AGENTS.md ต้องทำอะไรตอนเริ่มและตอนจบ

PROGRESS.md: ไฟล์ความคืบหน้า

ไฟล์นี้ตอบคำถามเดียว: โปรเจกต์อยู่ในสถานะใดตอนนี้ agent อ่านมันเป็นอย่างแรกตอนเริ่มเซสชัน และอัปเดตเป็นอย่างสุดท้ายก่อนจบ ไฟล์ควรสั้น เขียนทับใหม่แทนการต่อท้ายเรื่อย ๆ เพราะประวัติอยู่ใน git อยู่แล้ว

# PROGRESS.md

## เป้าหมายปัจจุบัน
ค้นหาสินค้าในแคตตาล็อก (ฟีเจอร์ search-01)

## สถานะ
- HEAD: 4f2a9c1
- make check: เขียว, เทสต์ 142/142
- ทำแล้ว: ดัชนีใน PostgreSQL (tsvector) และ endpoint GET /search
- ตรวจแล้ว: unit test + curl ด้วยคำค้น 3 คำ

## บล็อกเกอร์
- ยังไม่มีข้อมูล morphology สำหรับภาษาคาซัค รอการตัดสินใจ

## ขั้นตอนถัดไป
เพิ่มการแบ่งหน้าใน GET /search เกณฑ์: มีเทสต์สำหรับหน้าที่ 2

ให้สังเกตสี่ฟิลด์ที่เพียงพอสำหรับการส่งต่องาน ได้แก่ hash ของ commit สัดส่วนของเทสต์ที่ผ่าน บล็อกเกอร์ และขั้นตอนถัดไป ถ้าเซสชันใหม่ที่อ่านไฟล์นี้ไม่สามารถทำงานต่อได้อย่างชัดเจน แปลว่าเทมเพลตยังขาดฟิลด์บางอย่าง

DECISIONS.md: บันทึกการตัดสินใจ

ไฟล์นี้เก็บเหตุผลที่ "ทำไม" ซึ่งหายไปเมื่อเกิด compaction รูปแบบของแต่ละรายการ: การตัดสินใจ เหตุผล สิ่งที่ปฏิเสธและเพราะอะไร และข้อจำกัด

## 2026-03-14 — แคชการตั้งค่าของผู้ใช้ด้วย Redis
- การตัดสินใจ: Redis, TTL 5 นาที, ล้างแคชทันทีเมื่อมีการเขียน
- เหตุผล: ถูกอ่านทุกคำขอ และข้อมูลมีขนาดเล็กมาก
- ปฏิเสธ: materialized view ใน PostgreSQL เพราะข้อมูลเปลี่ยนบ่อย การดูแลไม่คุ้ม
- ข้อจำกัด: ห้ามแคชการตั้งค่าการชำระเงิน

บรรทัดที่มีค่าที่สุดคือ "ปฏิเสธ" เพราะมันป้องกันไม่ให้เซสชันถัดไปไป "ปรับให้ดีขึ้น" กลับไปเป็นตัวเลือกที่เคยพิจารณาแล้วและทิ้งไป บันทึกการตัดสินใจต่างจากไฟล์ความคืบหน้าตรงที่มีแต่จะเพิ่มขึ้น รายการเก่าไม่ถูกลบ แต่ถูกทำเครื่องหมายว่าถูกแทนที่ด้วยรายการใหม่

ประวัติ git เป็นจุดตรวจสถานะ

commit คือ snapshot ของสถานะที่มีเวอร์ชันอยู่แล้วในงาน agent อ่าน git log และ git diff เพื่อดูว่ามีอะไรเปลี่ยนไป และสร้างภาพได้ ข้อความ commit ต้องอธิบายเจตนาไม่ใช่ทวนซ้ำสิ่งที่ diff แสดงอยู่แล้ว ประวัติจึงทำหน้าที่เป็นความจำได้

# ไม่ดี
git commit -m "update search.py"

# ดี
git commit -m "search: ดัชนี tsvector แทน LIKE

LIKE '%q%' ไม่ใช้ดัชนี บน 200k สินค้าใช้เวลา 1.8 วินาที
ยังไม่ได้ทำการแบ่งหน้า ดู PROGRESS.md"

commit ขนาดเล็กที่บ่อยหลังการรันเทสต์ที่เขียว ยังให้จุดย้อนกลับด้วย ถ้าเซสชันไปผิดทาง การกลับไปยังสถานะที่ตรวจแล้วล่าสุดง่ายกว่าการแก้การแก้ไขที่ค้างครึ่งเดียว

โปรโตคอลการส่งต่องานใน AGENTS.md

ไฟล์สถานะไม่มีประโยชน์ถ้า agent ไม่รู้ว่ามันมีอยู่ ดังนั้นในไฟล์คำสั่งหลัก (AGENTS.md หรือ CLAUDE.md) ให้เขียนโปรโตคอลสั้น ๆ ว่าต้องทำอะไรตอนเริ่มและตอนจบ

## เริ่มกะ
1. อ่าน PROGRESS.md และ DECISIONS.md
2. หางานที่ active ใน .agent/feature_list.json
3. รัน make check เพื่อยืนยันว่ารีโพซิทอรีสอดคล้องกัน
4. ทำต่อจาก "ขั้นตอนถัดไป" โดยไม่เปิดประเด็นที่ตัดสินไปแล้วใหม่

## จบกะ
1. รัน make check แล้ว commit สถานะที่เขียว
2. อัปเดต PROGRESS.md: HEAD เทสต์ บล็อกเกอร์ ขั้นตอนถัดไป
3. เพิ่มการตัดสินใจใหม่ลงใน DECISIONS.md
4. ไม่ทิ้งงานที่ค้างไว้ใน working tree

โปรโตคอลควรสั้น เป็นบรรทัดไม่กี่บรรทัดในไฟล์หลัก ไม่ใช่เอกสารยาวเป็นหน้า

สคริปต์ init: เร่งการเริ่มเซสชัน

เพื่อไม่ให้ agent ต้องประกอบภาพรวมเอง ให้มันมีสคริปต์หนึ่งตัวที่ตรวจสภาพแวดล้อมและแสดงสถานะ สคริปต์ควรเป็น idempotent คือรันกี่ครั้งก็ได้ และจบด้วยข้อความที่ชัดเจนว่าพร้อมทำงาน

#!/usr/bin/env bash
set -euo pipefail

echo "== 1. สภาพแวดล้อม =="
command -v uv >/dev/null || { echo "FAIL: ยังไม่ได้ติดตั้ง uv"; exit 1; }
uv sync --frozen

echo "== 2. รีโพซิทอรี =="
if [ -n "$(git status --porcelain)" ]; then
  echo "WARN: working tree ไม่สะอาด"
else
  echo "OK: สะอาด"
fi
echo "HEAD: $(git log -1 --oneline)"

echo "== 3. การตรวจ =="
make check

echo "== 4. สถานะ =="
cat PROGRESS.md

echo "พร้อมทำงาน"

เมื่อมีสคริปต์นี้ โปรโตคอลตอนเริ่มกะต้องการเพียงบรรทัดเดียว: "รัน scripts/init.sh" ใน Claude Code การรันนี้สามารถทำอัตโนมัติด้วย hook ตอนเริ่มเซสชัน (เหตุการณ์ SessionStart) แต่แม้ไม่มี hook agent ก็จะรันสคริปต์ตามคำสั่งในไฟล์ได้

ควรเก็บอะไรไว้ในความจำของ agent และอะไรไม่ควร

ข้อผิดพลาดหลักคือทำให้ความจำกลายเป็นที่ทิ้งขยะ ทุกบรรทัดที่ agent อ่านตอนเริ่มกินที่ในบริบท และสิ่งที่ไม่จำเป็นจะกลบสิ่งสำคัญ

ควรเก็บไม่ควรเก็บ
เป้าหมายปัจจุบันและขั้นตอนถัดไปการทวนโค้ดที่ agent จะอ่านเองได้
การตัดสินใจพร้อมเหตุผลและตัวเลือกที่ถูกปฏิเสธล็อกบทสนทนาทั้งหมดและผลลัพธ์คำสั่ง
hash ของ commit และสถานะเทสต์รายการ dependency เพราะมีอยู่ในไฟล์ manifest แล้ว
บล็อกเกอร์และคำถามที่ยังเปิดอยู่"ทำได้ดีมาก ทุกอย่างทำงาน" โดยไม่ระบุว่าตรวจอย่างไร
ทางตัน: ลองอะไรและทำไมไม่ได้ผลความลับ โทเคน รหัสผ่าน
งานพร้อมเกณฑ์การยอมรับบันทึกเก่าเกี่ยวกับงานที่ปิดไปแล้ว

แยกตามอายุการใช้งานด้วย กฎของโปรเจกต์เปลี่ยนไม่บ่อยและใช้กับทุกงาน จึงควรอยู่ในไฟล์คำสั่งหลัก ส่วนสถานะเปลี่ยนทุกเซสชัน จึงควรอยู่ในไฟล์ความคืบหน้า ถ้าผสมปนกัน ไฟล์คำสั่งหลักจะบวมด้วยบันทึกที่ล้าสมัยอย่างรวดเร็ว

เซสชันแรก: การ initialize เป็นเฟสแยกต่างหาก

ความจำระหว่างเซสชันจะไม่ช่วยอะไร หากเซสชันแรกวุ่นวายไปหมด ภาพที่เห็นบ่อยคือคุณขอว่า "เพิ่มการค้นหา" บนรีโพซิทอรีว่าง และผ่านไปครึ่งชั่วโมงก็พบว่าการตั้งค่าเทสต์ผิด และรูปแบบ migration ไม่ถูกต้อง ฟีเจอร์ค้นหามีแล้ว แต่รากฐานคดเคี้ยว

สาเหตุคือการ implement กับการ initialize เพิ่มประโยชน์คนละอย่าง อย่างแรกเพิ่มจำนวนฟีเจอร์ที่เสร็จในเซสชันนี้ อย่างหลังเพิ่มความเร็วและความน่าเชื่อถือของทุกเซสชันหลังจากนี้ agent มักเอนเอียงไปหาผลที่มองเห็นได้ นั่นคือโค้ด ดังนั้นควรแยก initialization ออกเป็นเซสชันของตัวเอง โดยมีเกณฑ์ว่าเสร็จสี่ข้อ

  • รันได้: make setup และ make dev ทำงานได้จาก clone ที่สะอาด
  • ตรวจได้: มี make test และมีเทสต์จริงอย่างน้อยหนึ่งตัวที่ผ่าน
  • เห็นความคืบหน้าได้: ไฟล์สถานะมีอยู่และอ่านได้
  • รับช่วงงานได้: มีรายการงานพร้อมเกณฑ์การยอมรับ

ถ้าคุณเริ่มโปรเจกต์ใหม่บ่อย ให้สร้างเทมเพลตรีโพซิทอรี ประกอบด้วย Makefile เฟรมเวิร์กเทสต์ โครง AGENTS.md โฟลเดอร์ .agent/ scripts/init.sh linter และ CI การ initialize จะเหลือเพียงรายละเอียดเฉพาะของโปรเจกต์

วิธีตรวจว่าความจำทำงานหรือไม่

ตัวชี้วัดที่ซื่อตรงที่สุดคือเวลาตั้งแต่เริ่มเซสชันใหม่จนถึงการเปลี่ยนโค้ดที่มีความหมายครั้งแรก ถ้าไม่มีสิ่งประดิษฐ์ ปกติจะใช้เวลาสำรวจสิบห้าถึงยี่สิบนาที ถ้ามีการส่งต่องานที่ดี เหลือสองถึงสามนาที วัดหนึ่งครั้งก่อนและหลัง แล้วจะเห็นว่าวินัยนี้คุ้มค่าหรือไม่

วิธีที่สองคือการทดสอบ cold start เปิดเซสชันใหม่ พิมพ์ "ทำต่อ" และถามคำถามห้าข้อ: เป้าหมายปัจจุบันคืออะไร เทสต์อยู่ในสถานะใด มีการตัดสินใจอะไรสำหรับหัวข้อสำคัญและเพราะอะไร อะไรเป็นบล็อกเกอร์ ขั้นตอนถัดไปคืออะไร ถ้า agent ตอบได้ครบทั้งห้าข้อจากไฟล์ โดยไม่ต้องเดา แสดงว่าความจำถูกออกแบบมาถูกต้อง ทุกคำตอบที่ไม่มั่นใจคือฟิลด์ที่ยังขาดในเทมเพลต

ข้อผิดพลาดที่พบบ่อย

  • ไฟล์ความคืบหน้าโตขึ้นเรื่อย ๆ ผ่านไปหนึ่งเดือนจะมีประวัติหลายร้อยบรรทัด ให้เขียนทับเป็นสถานะปัจจุบัน ประวัติอยู่ใน git
  • ไม่มีบรรทัด "ปฏิเสธ" บันทึกการตัดสินใจที่ไม่มีตัวเลือกที่ถูกปฏิเสธจะไม่ป้องกันการถกเถียงซ้ำ
  • agent อัปเดตสถานะ "ตามความรู้สึก" ให้เขียนว่าตรวจอย่างไร คือคำสั่งและผลลัพธ์ ไม่ใช่ "ทุกอย่างทำงาน"
  • การส่งต่องานตอนบริบทเกือบเต็ม ใกล้ขอบหน้าต่าง agent จะรีบอยู่แล้ว ให้เริ่ม handoff ล่วงหน้า ประมาณ 60%
  • working tree ไม่สะอาดตอนจบ การแก้ไขที่ค้างโดยไม่ commit ทำให้เซสชันถัดไปสับสน

สรุป

ความจำของ AI agent ระหว่างเซสชันไม่ได้สร้างจากโมเดล แต่สร้างจากไฟล์ PROGRESS.md เก็บสถานะปัจจุบัน DECISIONS.md เก็บเหตุผลและตัวเลือกที่ถูกปฏิเสธ git commit คือจุดตรวจสถานะพร้อมเจตนา และโปรโตคอลใน AGENTS.md บังคับให้อ่านและอัปเดตทั้งหมดนี้ สคริปต์ init ย่อการเริ่มงานให้เหลือคำสั่งเดียว ส่วนการทดสอบ cold start บอกว่าบันทึกเพียงพอหรือไม่ สมุดบันทึกประจำของ agent และสัญญา bootstrap ถูกอธิบายและนำไปใช้จริงในคอร์สเกี่ยวกับ harness engineering

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

ขอให้ agent จำอะไรไว้ในอนาคตได้ไหม?

agent จะจำได้ก็ต่อเมื่อเขียนลงไฟล์ที่เซสชันถัดไปจะอ่าน ใน Claude Code มีไฟล์ความจำและ CLAUDE.md ให้ใช้ แต่สำหรับสถานะของงานเฉพาะ ไฟล์ความคืบหน้าที่ชัดเจนในรีโพซิทอรีเชื่อถือได้มากกว่า

PROGRESS.md ต่างจาก CHANGELOG อย่างไร?

CHANGELOG อธิบายการเปลี่ยนแปลงให้ผู้ใช้ตามเวอร์ชัน ส่วน PROGRESS.md อธิบายสถานะการทำงานปัจจุบันสำหรับเซสชัน agent ถัดไป และถูกเขียนทับทุกครั้งที่สถานะเปลี่ยน

ความจำของ agent เขียนโปรแกรมต้องใช้ vector database ไหม?

โดยทั่วไปไม่ต้อง สำหรับงานในรีโพซิทอรีเดียว สถานะของงานพอดีกับไฟล์สั้น ๆ ไม่กี่ไฟล์ และ agent อ่านโค้ดได้โดยตรง การค้นหาแบบ vector มีประโยชน์เมื่อต้องค้นเอกสารภายนอกจำนวนมาก

ควร commit ไฟล์สถานะเข้า git หรือไม่?

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

ถ้า agent ลืมอัปเดต PROGRESS.md ตอนจบจะทำอย่างไร?

ทำให้การอัปเดตเป็นส่วนหนึ่งของเกณฑ์ความสำเร็จในโปรโตคอลการจบกะ และตรวจด้วยกลไก เช่น hook หรือสคริปต์ที่เทียบ HEAD ในไฟล์กับ commit ปัจจุบัน

เรียนหัวข้อนี้ผ่านวิดีโอ

หัวข้อนี้สอนอย่างละเอียดพร้อมฝึกปฏิบัติในคอร์ส “Harness Engineering: инженерия надёжности AI-агентов”

ไปที่คอร์ส