Tiếp tục một task AI sau khi mất context
Câu hỏi bài này trả lời: phiên mới chưa thấy cuộc trò chuyện trước; đọc gì để biết mục tiêu, phần còn dở và bước tiếp theo, rồi kiểm thế nào để không tin một checkpoint đã cũ?
Cần biết trước: tiêu chí hoàn tất, Python và cách đọc diff. Bài dùng lại lab CSV của bài đó; chỉ thư viện chuẩn, đã thử Python 3.14 trên macOS arm64.
Một checkpoint tốt làm rõ việc phải làm tiếp và bằng chứng cần kiểm lại. Nó không cần chép toàn bộ chat. Anthropic mô tả harness chạy dài dùng artifact tiến độ, danh sách tính năng và kiểm đầu phiên để giảm việc đoán trạng thái. Đó là kinh nghiệm trong một harness cụ thể, không bảo đảm mọi agent sẽ hiểu đúng tài liệu bàn giao.
Giữ gì trong checkpoint?
| Phần | Nội dung hữu ích | Lỗi tránh |
|---|---|---|
| Mục tiêu và tiêu chí | Kết quả người dùng cần; tiêu chí chưa đạt | Chỉ ghi “đã sửa gần xong” |
| Scope | File được sửa, phần ngoài phạm vi | Mở rộng sang refactor/deploy |
| Quyết định | Lựa chọn hiện tại và lý do | Lưu mọi phương án đã bỏ |
| Diff | File/hành vi đã đổi và cách đối chiếu | Cho rằng tên file chứng minh nội dung |
| Evidence | Lệnh, exit, log, phiên bản và snapshot file/test | Chỉ ghi “tests pass” |
| Blocker | Điều thiếu và ai/cái gì gỡ được | Biến chưa kiểm thành pass |
| Next step | Một việc cụ thể để tiếp tục | Nhiều việc không có thứ tự |
Đặt checkpoint trong repository hoặc artifact store mà người/agent tiếp theo truy cập được. Nếu checkpoint nằm trong working tree chưa commit, người dùng ở máy khác chỉ thấy nó sau khi thay đổi đã được chuyển sang máy đó theo quy trình của nhóm. Không dựa vào memory riêng của một provider để giữ kiến thức chung.
Bài context engineering của Anthropic phân biệt compaction với structured note-taking. Với task coding, đường dẫn tới file/evidence giúp phiên mới nạp đúng phần cần dùng; đây là cách áp dụng cho ví dụ dưới, không đòi mọi task phải có cùng bộ file.
Case: xuất CSV còn lỗi R5
Tạo thư mục trống. Chép export_csv.py, fixtures.py và verify_behavior.py từ lab tiêu chí hoàn tất. Chọn bản no_header_when_empty: tên đặc biệt, Unicode và timestamp đều đúng; danh sách rỗng lại không có header. Mục tiêu là sửa bản đó, giữ tiêu chí R1–R6; không đổi fixture/verifier.
Lưu make_checkpoint.py cạnh ba file. Nó chạy phép kiểm thật trước khi ghi snapshot, gồm cả source, fixture và verifier. Snapshot có hash log để bắt log bị thay; hash là dấu nhận biết thay đổi, không phải chữ ký hay bằng chứng chống người sửa cả checkpoint lẫn file.
import hashlib
import json
import subprocess
import sys
from pathlib import Path
FILES = ("export_csv.py", "fixtures.py", "verify_behavior.py")
def digest(path):
return hashlib.sha256(Path(path).read_bytes()).hexdigest()
command = ["verify_behavior.py", "no_header_when_empty"]
result = subprocess.run([sys.executable, *command], capture_output=True,
text=True, timeout=20, check=False)
Path("last-check.log").write_text(result.stdout + result.stderr, encoding="utf-8")
checkpoint = {
"schema": 1,
"goal": "Xuất CSV đáp ứng R1–R6, kể cả danh sách rỗng",
"criteria": ["header", "thứ tự dòng", "UTC ISO", "quoting", "empty", "UTF-8"],
"scope": {"edit": ["export_csv.py"],
"keep": ["fixtures.py", "verify_behavior.py"],
"outside": ["Excel/BOM", "phân quyền", "deploy"]},
"decision": "Giữ csv.writer và timestamp UTC; header không phụ thuộc có dữ liệu",
"diff": "Bản no_header_when_empty có if users bao quanh writer.writerow(HEADER)",
"snapshot": {name: digest(name) for name in FILES},
"verification": {"command": command, "exit": result.returncode,
"passes": result.returncode == 0, "log": "last-check.log",
"log_sha256": digest("last-check.log"),
"python": sys.version.split()[0]},
"blockers": [],
"next_step": ("Review diff và phạm vi sau kiểm local" if result.returncode == 0
else "Sửa header bản no_header_when_empty rồi chạy lại verifier"),
"done": False,
}
Path("checkpoint.json").write_text(json.dumps(checkpoint, ensure_ascii=False, indent=2),
encoding="utf-8")
print(f"checkpoint written exit={result.returncode} done=false")
Trường diff là ghi chú ngắn tại thời điểm bàn giao ban đầu. Sau sửa phải đọc diff thật và cập nhật ghi chú; script chỉ tạo snapshot/evidence, không hiểu diff ngữ nghĩa. passes=true chỉ nói verifier local xanh, done vẫn false để còn review phạm vi. Scope/criteria trong JSON là hướng dẫn, không phải quyền filesystem.
python3 make_checkpoint.py
Reader mới: đọc checkpoint rồi đối chiếu file thật
Lưu resume.py. Reader không import module của phiên trước, không đọc chat hay provider memory. Nó kiểm cấu trúc/path/command cố định, so snapshot và luôn chạy lại verifier, kể cả snapshot chưa đổi. Chỉ command của lab được chấp nhận; không thực thi tùy ý chuỗi trong checkpoint.
import hashlib
import json
import subprocess
import sys
from pathlib import Path
FILES = {"export_csv.py", "fixtures.py", "verify_behavior.py"}
state = json.loads(Path("checkpoint.json").read_text(encoding="utf-8"))
verify = state["verification"]
if (state["schema"] != 1 or set(state["snapshot"]) != FILES
or verify["command"] != ["verify_behavior.py", "no_header_when_empty"]
or verify["log"] != "last-check.log"):
print("rejected checkpoint contract")
sys.exit(2)
def digest(path):
return hashlib.sha256(Path(path).read_bytes()).hexdigest()
for name in (*FILES, "last-check.log"):
if not Path(name).is_file() or Path(name).is_symlink():
print("missing or unsafe evidence file")
sys.exit(2)
changed = any(digest(name) != value for name, value in state["snapshot"].items())
changed = changed or digest("last-check.log") != verify["log_sha256"]
print("snapshot changed: revalidate" if changed else "snapshot unchanged: revalidate")
print("goal:", state["goal"])
print("next:", state["next_step"])
result = subprocess.run([sys.executable, *verify["command"]], capture_output=True,
text=True, timeout=20, check=False)
print(result.stdout, end="")
print(result.stderr, end="", file=sys.stderr)
print(f"current exit={result.returncode}; checkpoint exit={verify['exit']}; done=false")
sys.exit(result.returncode)
python3 resume.py
Phiên mới thấy lỗi empty, exit 1, và bước sửa header. Nó chưa được phép đổi criterion thành “file có tồn tại”. Trên task thật, còn phải đọc instructions, trạng thái working tree và diff để tránh ghi đè thay đổi của người khác; simulator nhỏ không thay các bước đó.
Sửa đúng một nhánh rồi thử lại
Khối này chỉ đổi đúng bản lỗi; không sửa hai bản lỗi khác của bài trước hoặc verifier. File .before là bản nguồn riêng của lab dùng cho phép thử regression, không là bản sao dữ liệu thật.
python3 - <<'PY'
from pathlib import Path
path = Path("export_csv.py")
source = path.read_text(encoding="utf-8")
Path("export_csv.before").write_text(source, encoding="utf-8")
old = " if users:\n writer.writerow(HEADER)"
assert source.count(old) == 1
path.write_text(source.replace(old, " writer.writerow(HEADER)"), encoding="utf-8")
print("patched one header branch")
PY
python3 resume.py
Reader báo source đổi và rerun xanh cả bốn ca. Không dùng checkpoint cũ làm bằng chứng cho bản mới; ghi checkpoint mới sau khi đã review diff. Trong lab, so đúng phần thay đổi rồi cập nhật ghi chú:
python3 make_checkpoint.py
python3 - <<'PY'
import json
from pathlib import Path
path = Path("checkpoint.json")
state = json.loads(path.read_text(encoding="utf-8"))
state["diff"] = "Header của no_header_when_empty đã đưa ra ngoài if users; fixture/verifier giữ nguyên"
path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
PY
python3 resume.py
Checkpoint xanh, source đã regression
Khôi phục bản lỗi mà không đổi checkpoint xanh. Phiên mới phải thấy stale và lỗi hiện tại; exit trong checkpoint vẫn 0 không giúp test mới vượt qua.
python3 - <<'PY'
from pathlib import Path
Path("export_csv.py").write_text(Path("export_csv.before").read_text(encoding="utf-8"), encoding="utf-8")
PY
python3 resume.py
Thử command ngoài contract bằng dữ liệu vô hại: reader phải từ chối trước khi chạy; không chèn shell command thật để minh họa.
python3 - <<'PY'
import json
from pathlib import Path
path = Path("checkpoint.json")
state = json.loads(path.read_text(encoding="utf-8"))
Path("checkpoint.before").write_text(json.dumps(state), encoding="utf-8")
state["verification"]["command"] = ["unexpected-verifier.py"]
path.write_text(json.dumps(state), encoding="utf-8")
PY
python3 resume.py
Cuối lab đưa source về bản sửa, bỏ artifact trước đây và ghi checkpoint/evidence mới:
python3 - <<'PY'
from pathlib import Path
path = Path("export_csv.py")
source = path.read_text(encoding="utf-8")
old = " if users:\n writer.writerow(HEADER)"
assert source.count(old) == 1
path.write_text(source.replace(old, " writer.writerow(HEADER)"), encoding="utf-8")
Path("export_csv.before").unlink()
Path("checkpoint.before").unlink()
PY
python3 make_checkpoint.py
python3 - <<'PY'
import json
from pathlib import Path
path = Path("checkpoint.json")
state = json.loads(path.read_text(encoding="utf-8"))
state["diff"] = "Header của no_header_when_empty đã đưa ra ngoài if users; fixture/verifier giữ nguyên"
path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
PY
python3 resume.py
Checkpoint cuối có ghi chú diff đúng bản đã sửa, evidence hiện tại và một next step. Không cần đánh done=true chỉ để checkpoint trông sạch; việc review hoặc môi trường chưa kiểm phải được giữ rõ.
Giới hạn và vệ sinh dữ liệu
- Lab chứng minh reader process mới có thể xác định lỗi/bước tiếp từ file. Nó không mô phỏng khả năng hiểu ngôn ngữ của một session LLM mới, hoặc đo hiệu quả qua nhiều model.
- Hash phát hiện thay đổi byte, không xác nhận người tạo, nội dung đúng hoặc quyền thực thi. Không tin checkpoint từ nguồn lạ; allowlist command cũng không ngăn file verifier đã bị thay thành mã khác. Quyền đọc/chạy phải do môi trường thực thi kiểm soát.
- Source không đổi vẫn có thể gặp dependency, runtime hay dịch vụ bên ngoài đổi. Ghi môi trường và rerun; fixture/verifier đổi phải review vì “xanh” có thể do mất tiêu chí.
- Chỉ giữ dữ liệu giả, path tương đối và kết luận kỹ thuật. Không ghi token, chuỗi kết nối, ticket/khách thật hay raw log chứa payload riêng; lưu evidence cần hạn chế quyền ở nơi thích hợp, rồi checkpoint trỏ đến nó.
- Với shared working tree, hash đơn lẻ không tạo snapshot nhất quán hoặc khóa file. Dừng nếu file tiếp tục đổi lúc kiểm; khi bàn giao giữa máy cần phiên bản/snapshot chung theo quy trình của nhóm.
Ba bài tập chưa thử trong lab: sửa fixture rồi resume để kiểm stale; thay log rồi resume; chuyển folder sang môi trường sạch chỉ từ checkpoint và file đã ghi. Học tiếp chọn context và review code AI. Nguồn Anthropic đọc ngày 2026-10-03.