Poison Context: khi một giả định sai sống dai trong phiên làm việc
Poison Context khiến agent liên tục dựa vào dữ liệu sai, kết quả cũ hoặc giả định chưa kiểm chứng. Bài viết giải thích cách nhận diện, cô lập và phục hồi context trước khi lỗi lan sang các bước tiếp theo.
Bạn nhờ một coding agent sửa lỗi đăng nhập. Sau vài lượt đọc code, agent kết luận endpoint /auth/session trả về trường accessToken. Kết luận ấy sai: API hiện tại thiết lập cookie HttpOnly. Nhưng thay vì quay lại kiểm tra implementation và response thật, agent tiếp tục sửa frontend, thêm logic lưu token, rồi giải thích mọi test fail dựa trên giả định ban đầu.
Đến lúc này, vấn đề không còn nằm ở một câu trả lời sai. Thông tin sai đã trở thành tiền đề cho các bước tiếp theo, xuất hiện trong bản tóm tắt tiến độ và có thể được ghi vào memory. Context đã bị nhiễm độc.
Trong bài viết về các kiểu hỏng của context dài, Drew Breunig định nghĩa Context Poisoning là hiện tượng một hallucination hoặc lỗi lọt vào context rồi liên tục được tham chiếu lại.1 Tôi dùng Poison Context để chỉ trạng thái của context sau khi điều đó xảy ra: agent đang làm việc trên một tập thông tin có ít nhất một tiền đề sai đủ sức làm lệch những quyết định về sau.
Một lỗi chỉ trở thành Poison Context khi nó được tái sử dụng
Không phải câu trả lời sai nào cũng làm hỏng cả phiên làm việc. Nếu agent đọc nhầm một log, kiểm tra lại ngay và loại bỏ kết luận cũ, lỗi đã được chặn tại chỗ.
Poison Context xuất hiện khi thông tin sai đi qua ba bước:
- Một dữ kiện, giả định hoặc kết luận sai đi vào context.
- Nó không được đánh dấu là chưa kiểm chứng, hoặc được trình bày như một sự thật.
- Các bước sau tái sử dụng nó để lập kế hoạch, gọi tool, sửa code, tóm tắt hoặc ghi memory.
flowchart LR
A[Quan sát hoặc dữ liệu đầu vào] --> B[Diễn giải sai]
B --> C[Được giữ trong context]
C --> D[Quyết định tiếp theo]
D --> E[Tool output hoặc thay đổi mới]
E --> F[Kết quả bị diễn giải theo giả định cũ]
F --> C
Vòng lặp này khó phát hiện vì mỗi bước riêng lẻ vẫn có vẻ hợp lý. Một command fail có thể bị diễn giải theo giả định sai; kết quả diễn giải ấy lại trở thành căn cứ cho lần thử kế tiếp. Agent không nhất thiết lặp nguyên văn lỗi ban đầu, nhưng hướng điều tra đã bị khoá vào một mô hình sai về hệ thống.
Poison Context cũng không đồng nghĩa với context dài. Nghiên cứu Lost in the Middle cho thấy hiệu năng có thể giảm đáng kể khi thông tin liên quan nằm giữa một context dài, ngay cả với những model được thiết kế để nhận long context.2 Đó là hạn chế về khả năng sử dụng thông tin theo vị trí. Với Poison Context, vấn đề chính là tính đúng đắn và sự lan truyền: một dữ kiện sai đang được dùng làm nền tảng suy luận.
Hai hiện tượng có thể xuất hiện cùng lúc. Context càng dài, việc tìm lại nguồn ban đầu và nhận ra một giả định đã bị bác bỏ càng khó. Tuy vậy, tăng context window không tự sửa được dữ kiện sai.
Context bị nhiễm từ đâu?
Trong công việc thực tế, nguồn gây nhiễm thường không kịch tính. Nó có thể là một comment đã cũ, tài liệu mô tả phiên bản trước, kết quả test chạy nhầm environment hoặc một câu nói thiếu điều kiện.
| Nguồn | Ví dụ | Cách lỗi lan truyền |
|---|---|---|
| Hallucination của model | Tự suy ra một field không tồn tại trong API | Kế hoạch và code mới cùng dựa vào field đó |
| Tool output không đầy đủ | Chỉ đọc phần cuối của log | Bỏ sót lỗi gốc rồi chẩn đoán theo lỗi thứ cấp |
| Tài liệu đã cũ | README mô tả kiến trúc trước khi refactor | Code hiện tại bị diễn giải theo cấu trúc cũ |
| Tóm tắt sai | Bỏ mất trạng thái “chưa kiểm chứng” | Phiên sau nhận giả thuyết như một dữ kiện |
| Memory không có provenance | Ghi “service dùng Redis” nhưng không lưu nguồn và thời điểm | Kết luận cũ được áp dụng cho environment khác |
| Kết quả trung gian của agent khác | Agent A suy đoán ownership của endpoint | Agent B coi handoff là bằng chứng đã xác nhận |
| Dữ liệu từ retrieval | Tìm được tài liệu đúng từ khoá nhưng sai version | Contract cũ được đưa vào active context |
| Nội dung có chủ đích xấu | Tool response chứa instruction ẩn | Agent xử lý dữ liệu không đáng tin như instruction |
Trường hợp cuối thuộc phạm vi bảo mật. OWASP mô tả MCP Tool Poisoning là một dạng indirect prompt injection: response từ MCP tool độc hại chứa instruction ẩn, được đưa vào context và có thể khiến agent gọi tool bị hạn chế, đọc dữ liệu nhạy cảm hoặc gửi dữ liệu ra ngoài.3 Cơ chế này cần biện pháp kiểm soát trust boundary và quyền thực thi; không thể chỉ xử lý bằng một câu nhắc model “hãy cẩn thận”.
Ngược lại, phần lớn Poison Context trong một phiên coding là lỗi reliability không có attacker: agent đọc thiếu file, người dùng cung cấp thông tin đã cũ, hoặc một bản tóm tắt biến giả thuyết thành kết luận. Hai nhóm có thể tạo triệu chứng giống nhau, nhưng cách xử lý khác nhau. Nếu nghi ngờ prompt injection, cần cô lập nguồn dữ liệu và chặn action nhạy cảm trước khi tiếp tục điều tra.
Checklist nhận diện Poison Context
Tôi thường không kết luận chỉ từ một câu trả lời kém. Dấu hiệu đáng chú ý là một tiền đề cũ tiếp tục chi phối hành vi dù bằng chứng mới không ủng hộ nó.
Dấu hiệu trong câu trả lời
- Agent khẳng định một chi tiết kỹ thuật nhưng không chỉ ra file, log, response hoặc tài liệu hiện hành làm nguồn.
- Các cụm như “như đã xác định”, “theo kiến trúc hiện tại” hoặc “vẫn dùng cách cũ” xuất hiện mà không truy được lần xác định ban đầu.
- Agent lặp lại cùng một kết luận sau khi tool output đã mâu thuẫn với kết luận đó.
- Một giả thuyết ban đầu biến thành dữ kiện trong summary, plan hoặc handoff.
- Câu trả lời giải thích mọi kết quả theo cùng một giả định, kể cả những kết quả đáng lẽ phải khiến giả định bị bác bỏ.
- Agent trích dẫn một summary do chính nó tạo ra thay cho bằng chứng gốc.
Dấu hiệu trong hành vi
- Agent gọi lại cùng một tool hoặc chạy cùng một hướng kiểm tra mà không thu được bằng chứng mới.
- Nhiều bản sửa liên tiếp chỉ xử lý triệu chứng, trong khi lỗi gốc chưa được tái hiện.
- Agent mở rộng phạm vi sửa để giữ nguyên giả định ban đầu, thay vì kiểm tra lại giả định.
- Agent chỉnh test, mock hoặc fixture cho khớp với implementation mới dù contract thật chưa được xác minh.
- Một phiên mới, dùng context sạch và cùng dữ liệu gốc, đưa ra mô hình hệ thống khác đáng kể.
- Kết quả thay đổi mạnh khi bỏ summary, memory hoặc một tài liệu được retrieve khỏi context.
Không dấu hiệu nào trong số này tự nó chứng minh context đã bị nhiễm. Chúng là lý do để tạm dừng và kiểm tra provenance, không phải lý do để xoá sạch công việc ngay lập tức.
Năm câu hỏi kiểm tra nhanh
- Tiền đề nào đang quyết định hướng xử lý hiện tại?
- Tiền đề đó đến từ quan sát trực tiếp hay từ suy luận của model?
- Nguồn còn hiện hành không, và được ghi nhận vào thời điểm nào?
- Có bằng chứng độc lập nào xác nhận nó không?
- Quan sát nào sẽ đủ để bác bỏ nó?
Câu hỏi cuối đặc biệt hữu ích. Nếu không mô tả được điều kiện bác bỏ, thứ đang được giữ trong context chưa phải một giả thuyết kỹ thuật có thể kiểm tra.
Khi phát hiện: dừng lan truyền trước, sửa context sau
Phản xạ thường gặp là thêm một prompt dài để giải thích rằng agent đã sai. Cách này có thể làm context chứa cả kết luận cũ lẫn kết luận mới, trong khi thứ tự ưu tiên giữa chúng không rõ. Breunig gọi trường hợp các phần trong context mâu thuẫn nhau là Context Clash.1
Tôi ưu tiên quy trình sau:
1. Tạm dừng action có side effect
Không cho agent tiếp tục edit, deploy, gửi message, ghi database hoặc gọi tool có quyền cao. Nếu dữ kiện nền đang sai, thêm action chỉ làm tăng phạm vi ảnh hưởng và chi phí phục hồi.
Bước này không có nghĩa là dừng toàn bộ điều tra. Các thao tác đọc code, xem diff, kiểm tra log và chạy truy vấn read-only vẫn có thể tiếp tục nếu chúng an toàn và cần thiết để xác minh giả định.
2. Gọi tên chính xác tiền đề bị nghi ngờ
Đừng nói chung chung rằng “context có vẻ sai”. Hãy viết thành một mệnh đề có thể kiểm tra, chẳng hạn:
Giả định cần kiểm tra: backend trả
accessTokentrong JSON response của endpoint đăng nhập.
Sau đó liệt kê những quyết định đã phụ thuộc vào giả định này. Việc đó xác định phạm vi ảnh hưởng thay vì xoá toàn bộ tiến độ một cách máy móc:
- logic lưu token ở frontend;
- interceptor gắn header
Authorization; - test mock JSON response;
- summary ghi rằng authentication dùng bearer token.
3. Quay lại bằng chứng trực tiếp
Với code, hãy đọc implementation hiện tại, caller và test liên quan. Với API, kiểm tra schema cùng response thật trong environment phù hợp. Với dữ liệu vận hành, đối chiếu log có timestamp, environment và request ID. Summary của agent chỉ là chỉ mục để tìm lại bằng chứng, không phải bằng chứng tự thân.
Nếu hai nguồn mâu thuẫn, cần ghi rõ provenance:
CLAIM: Login dùng cookie HttpOnly
STATUS: verified
SOURCE: response thực tế từ environment local, 2026-07-17
CONFIRMED_BY: implementation và integration test hiện tại
CONFLICT: README vẫn mô tả accessToken trong JSON
ACTION: không dùng README làm nguồn cho contract hiện tại
Một nguồn gần implementation hơn chưa chắc luôn đúng. Code có thể chưa được deploy, log có thể đến từ instance cũ và test có thể chỉ xác nhận mock. Vì vậy, provenance phải gồm cả version hoặc commit, environment và thời điểm khi những yếu tố này ảnh hưởng tới kết luận.
4. Lập bản đồ phạm vi ảnh hưởng
Sau khi xác định tiền đề sai, hãy truy những gì đã phụ thuộc vào nó:
flowchart TD
A[Tiền đề sai] --> B[Plan]
A --> C[Code hoặc config]
A --> D[Test và mock]
A --> E[Summary hoặc memory]
A --> F[Handoff cho agent khác]
B --> G[Quyết định tiếp theo]
C --> G
D --> G
E --> G
F --> G
Đây là bước dễ bị bỏ qua nhất. Sửa một câu trong summary không đủ nếu giả định sai đã đi vào code, test, cache retrieval hoặc memory dài hạn. Mỗi nhánh cần được xác minh hoặc thu hồi riêng.
5. Cô lập phần context bị nhiễm
Tạo một thread hoặc session sạch cho bước xác minh, chỉ đưa vào mục tiêu, ràng buộc và bằng chứng gốc cần thiết. Breunig gọi cách tách các công việc sang context riêng là context quarantine.4
Session mới không nên nhận nguyên transcript cũ. Nếu cần handoff, hãy chuyển một bản ghi có cấu trúc gồm:
- mục tiêu hiện tại;
- dữ kiện đã kiểm chứng kèm nguồn;
- giả thuyết chưa kiểm chứng;
- dữ kiện đã bị bác bỏ;
- thay đổi đã thực hiện;
- test đã chạy và kết quả;
- phần cần điều tra tiếp.
Context quarantine không tự chứng minh kết luận mới là đúng. Nó chỉ ngăn lịch sử cũ tiếp tục ảnh hưởng tới bước xác minh. Session sạch vẫn phải kiểm tra bằng chứng như bình thường.
6. Khôi phục từ trạng thái đã biết là đúng
Với coding agent, diff và commit giúp phân biệt thay đổi hợp lệ với thay đổi sinh ra từ giả định sai. Anthropic cho biết trong thử nghiệm về agent chạy qua nhiều context window, làm việc theo từng phần nhỏ, dùng commit có mô tả và cập nhật progress file giúp agent khôi phục trạng thái hoạt động mà không phải đoán phiên trước đã làm gì.5
Không phải mọi thay đổi sau thời điểm nhiễm đều phải bỏ. Hãy truy dependency: thay đổi nào dựa trực tiếp hoặc gián tiếp vào tiền đề sai thì cần kiểm tra lại; phần độc lập có thể được giữ nếu vượt qua verification riêng.
Mốc “đã biết là đúng” cũng cần bằng chứng. Một commit cũ không mặc nhiên an toàn chỉ vì nó có trước lúc phát hiện lỗi; hãy xác nhận bằng test, hành vi thực tế hoặc trạng thái vận hành phù hợp.
7. Viết lại state, đừng chỉ nối thêm lời đính chính
Một summary phục hồi nên loại bỏ dữ kiện sai khỏi phần “đã xác nhận”, đồng thời lưu nó trong mục “đã bác bỏ” nếu nguy cơ tái xuất hiện còn cao:
verified:
- claim: "Endpoint đăng nhập thiết lập cookie HttpOnly"
source: "implementation, integration test và response local"
verified_at: "2026-07-17T16:00:00+07:00"
rejected:
- claim: "Endpoint trả accessToken trong JSON"
reason: "Không khớp implementation, test và response đã kiểm tra"
open_questions:
- "README nào vẫn mô tả contract cũ?"
Cách ghi này không yêu cầu model tự nhớ rằng một câu ở hàng chục nghìn token trước đã bị sửa. Trạng thái hiện hành được trình bày trực tiếp, có nguồn và có phân loại.
8. Chạy lại verification từ đầu
Đừng chỉ chạy những test vừa được thêm trong lúc context đã sai. Hãy quay lại hành vi cần đạt và xây lại verification từ contract đã được xác nhận:
- tái hiện lỗi ban đầu;
- kiểm tra request và response thực tế;
- chạy test ở đúng environment;
- kiểm tra những nhánh đã phụ thuộc vào tiền đề sai;
- xác nhận summary, memory và tài liệu không còn phát tán kết luận cũ.
Nếu verification chỉ kiểm tra cấu trúc do chính giả định sai tạo ra, test vẫn có thể pass trong khi hệ thống thực tế không đáp ứng yêu cầu.
Phòng ngừa khi làm việc với agent
Poison Context không thể được loại bỏ hoàn toàn, nhưng có thể ngăn một lỗi nhỏ trở thành tiền đề lâu dài:
- Tách rõ
fact,hypothesis,decisionvàopen questiontrong plan hoặc memory. - Mọi dữ kiện có khả năng thay đổi cần kèm nguồn, timestamp, environment hoặc version.
- Không ghi output của model vào long-term memory trước khi kết quả được kiểm tra và xác nhận.
- Đặt giới hạn phạm vi cho từng phiên; task độc lập nên dùng context riêng.
- Tóm tắt từ bằng chứng gốc, không tóm tắt nối tiếp từ nhiều bản summary cũ.
- Trước action rủi ro cao, yêu cầu kiểm tra lại các tiền đề quyết định action đó.
- Giữ transcript đầy đủ để audit, nhưng chỉ đưa state đã tuyển chọn vào active context.
- Khi handoff, chuyển cả trạng thái xác minh và provenance, không chỉ chuyển kết luận.
- Test kết quả cuối theo hành vi quan sát được, không chỉ kiểm tra rằng code compile hoặc tool call trả về thành công.
- Thiết kế quyền tool theo nguyên tắc least privilege để một context sai không tự động dẫn tới action nguy hiểm.
Với hệ thống agent, nên bổ sung provenance vào từng memory record và tool result. Một record chỉ có nội dung mà không có nguồn, thời điểm, phạm vi hiệu lực và trạng thái xác minh rất khó được thu hồi khi sai. Đây là bài toán quản lý state, không chỉ là bài toán viết prompt.
Cũng cần phân biệt transcript và active state. Transcript là lịch sử phục vụ audit; active state là tập dữ kiện được đưa vào lần suy luận hiện tại. Giữ toàn bộ transcript có thể hữu ích, nhưng không có nghĩa mọi câu trong lịch sử đều nên tiếp tục nằm trong active context với trọng lượng ngang nhau.
Checklist xử lý một phiên đang lệch hướng
Khi nghi ngờ Poison Context, có thể dùng checklist này ngay trong cuộc làm việc:
- Dừng edit và các action có side effect.
- Viết ra tiền đề bị nghi ngờ dưới dạng một mệnh đề kiểm chứng được.
- Xác định tiền đề đến từ quan sát, suy luận, summary, memory hay handoff.
- Xác định các quyết định, thay đổi và summary đã phụ thuộc vào tiền đề đó.
- Kiểm tra lại bằng nguồn hiện hành: code, schema, response, log hoặc tài liệu chính thức.
- Ghi provenance gồm source, timestamp, environment và version khi có liên quan.
- Phân loại từng thông tin thành
verified,unverified,conflictinghoặcrejected. - Nếu có dấu hiệu prompt injection, cô lập nguồn và thu hồi quyền tool nhạy cảm.
- Tạo context sạch cho bước xác minh hoặc phần việc còn lại.
- Chỉ chuyển sang session mới state đã tuyển chọn: dữ kiện đã kiểm chứng kèm provenance, giả thuyết được đánh dấu rõ là chưa kiểm chứng và dữ kiện đã bị bác bỏ nếu cần để ngăn lỗi tái xuất hiện.
- Khôi phục code và state từ mốc đã biết là đúng; rà lại toàn bộ phần phụ thuộc.
- Chạy verification từ đầu theo hành vi thực tế.
- Cập nhật hoặc loại bỏ tài liệu, cache và memory đã phát tán dữ kiện sai.
- Kiểm tra các handoff hoặc agent khác đã nhận kết luận cũ.
- Ghi lại nguyên nhân để cùng kiểu lỗi không quay lại qua retrieval hoặc handoff.
Một context window lớn có thể chứa nhiều lịch sử hơn, nhưng không tự phân biệt được đâu là lịch sử đúng. Khi một phiên làm việc bắt đầu giữ nguyên giả định cũ dù bằng chứng mới mâu thuẫn với nó, thêm context thường chỉ làm dữ kiện sai xuất hiện ở nhiều vị trí hơn. Việc cần làm lúc ấy là quay về bằng chứng, thu nhỏ active context và xây lại state từ những gì đã được xác nhận.
Tài liệu tham khảo
- Drew Breunig (2025). How Long Contexts Fail. dbreunig.com
- Nelson F. Liu, Kevin Lin, John Hewitt, Ashwin Paranjape, Michele Bevilacqua, Fabio Petroni và Percy Liang (2023). Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172
- OWASP Foundation (2026). MCP Tool Poisoning. OWASP Community
- Drew Breunig (2025). How to Fix Your Context. dbreunig.com
- Anthropic (2025). Effective harnesses for long-running agents. Anthropic Engineering