OpenCode là một trong những terminal-based coding agent mã nguồn mở phát triển nhanh nhất, hỗ trợ nhiều LLM provider khác nhau (Anthropic, OpenAI, các model chạy local qua Ollama...) và có hệ sinh thái MCP tương đối trưởng thành. Vì OpenCode thường được dùng theo phong cách "mở terminal, làm việc, đóng terminal" nhiều lần trong ngày, bài toán mất context giữa các lần mở lại càng rõ rệt hơn so với các IDE full-time. Bài này hướng dẫn cấu hình Memory MCP cho OpenCode, cách lưu và truy xuất context session, một ví dụ thực tế về việc resume một refactor kéo dài nhiều ngày, và những hạn chế bạn cần biết trước khi đặt cược quá nhiều vào memory trong OpenCode.
Cài Đặt Và Kết Nối Memory MCP Với OpenCode
OpenCode khai báo MCP server trong file cấu hình opencode.json (đặt ở root project để scope theo project, hoặc ở ~/.config/opencode/opencode.json để scope global). Thêm Memory MCP như sau:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"memory": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-memory"],
"environment": {
"MEMORY_FILE_PATH": "./.opencode/memory.jsonl"
},
"enabled": true
}
}
}
Lưu file, sau đó khởi động lại OpenCode hoặc chạy lệnh reload server trong TUI (thường là /mcp reload hoặc tương đương trong phiên bản bạn dùng — kiểm tra bằng /help nếu tên lệnh khác). Xác nhận server đã lên bằng cách hỏi trực tiếp trong session:
Liệt kê các MCP tool hiện có liên quan tới memory.
Nếu cấu hình đúng, agent sẽ liệt kê được create_entities, search_nodes, read_graph... Nếu không thấy, kiểm tra lại theo thứ tự: đường dẫn command có chạy được độc lập ngoài OpenCode không (npx -y @modelcontextprotocol/server-memory chạy trực tiếp trong terminal), quyền viết vào thư mục chứa MEMORY_FILE_PATH, và log của OpenCode (thường xem được bằng flag --log-level debug khi khởi động).
Mẹo: Luôn tạo thư mục
.opencode/trước khi trỏMEMORY_FILE_PATHvào đó — một số phiên bản server memory sẽ lỗi im lặng (fail silently) nếu thư mục cha không tồn tại, và bạn sẽ chỉ nhận ra khi phát hiện agent "không nhớ gì cả" sau nhiều ngày dùng.
Lưu Trữ Và Truy Xuất Context Của Session Trong OpenCode
Vì OpenCode được dùng theo kiểu mở-đóng session liên tục, quy trình thực dụng nhất là: agent tự capture những gì quan trọng vào cuối mỗi task, và tự recall đầu mỗi session mới thông qua một quy tắc bạn đặt trong file rule của project (AGENTS.md hoặc file rule tương đương mà OpenCode đọc).
Ví dụ đặt rule trong AGENTS.md:
## Memory Protocol
- Đầu mỗi session mới liên quan tới thư mục `services/`, chạy search_nodes
với từ khoá tên service đang làm để lấy context cũ trước khi code.
- Cuối mỗi task hoàn chỉnh, tóm tắt quyết định quan trọng và lưu vào memory
qua add_observations, gắn vào entity đúng service liên quan.
Với rule này, bạn không cần nhắc lại mỗi lần — agent tự động thực hiện quy trình recall/capture như một phần quy trình làm việc chuẩn.
Ví dụ một session thực tế bắt đầu:
Tôi sẽ sửa lỗi retry logic trong service "notification-worker".
Agent (theo rule đã đặt) tự gọi search_nodes với query "notification-worker", tìm ra observation cũ: "notification-worker dùng exponential backoff, max 5 lần retry, cache circuit-breaker state trong Redis key prefix nw:cb:". Nhờ vậy agent không đề xuất lại một cơ chế retry hoàn toàn khác không tương thích với hạ tầng đã có.
Mẹo: Đặt rule capture/recall trong
AGENTS.mdthay vì chỉ nhắc bằng miệng mỗi lần — rule viết sẵn được nạp tự động vào mọi session, đảm bảo hành vi nhất quán cho dù người gõ prompt là bạn hay đồng nghiệp khác dùng chung project.
Ví Dụ Thực Tế: Tiếp Tục Một Refactor Kéo Dài Nhiều Ngày Mà Không Cần Brief Lại Agent
Giả sử bạn đang refactor một module thanh toán từ đồng bộ sang bất đồng bộ, dự kiến mất 3-4 ngày làm việc rải rác. Ngày 1, sau khi lên kế hoạch, ghi lại toàn bộ plan vào memory:
Ghi vào memory entity "refactor-async-payment" (entityType: "decision") các
observation sau:
1. Mục tiêu: chuyển PaymentService.charge() từ gọi đồng bộ sang publish event
lên queue "payment.charge.requested".
2. Đã hoàn thành: định nghĩa event schema, viết producer.
3. Chưa làm: viết consumer, migrate 3 nơi gọi charge() trực tiếp trong
OrderController, AdminRefundController, CronReconciliation.
4. Rủi ro cần lưu ý: CronReconciliation gọi charge() trong transaction DB,
cần đảm bảo publish event xảy ra sau commit, không phải trước.
Ngày 3, mở OpenCode lên trong một session hoàn toàn mới, không cần giải thích lại gì:
Tiếp tục refactor "refactor-async-payment", đọc lại tiến độ và cho tôi biết
việc gì đang chưa xong.
Agent gọi open_nodes với tên "refactor-async-payment", đọc lại đúng 4 observation trên, tóm tắt lại chính xác việc "viết consumer và migrate 3 nơi gọi trực tiếp" vẫn đang chờ, kèm cả lưu ý về rủi ro transaction. Bạn tiếp tục công việc như thể chưa từng gián đoạn — đây chính là giá trị lớn nhất của memory trong một agent theo phong cách phiên làm việc ngắt-nối liên tục như OpenCode.
Khi hoàn thành, cập nhật lại observation (không tạo entity mới) để tránh graph phình to với các entity trùng lặp về cùng một refactor:
Cập nhật entity "refactor-async-payment": đã hoàn tất toàn bộ, consumer đã
deploy, 3 nơi gọi trực tiếp đã migrate xong ngày hôm nay. Đánh dấu observation
"chưa làm" cũ là đã lỗi thời và xoá nó.
Mẹo: Với refactor nhiều ngày, luôn tạo đúng MỘT entity đại diện cho cả refactor và cập nhật observation của nó theo thời gian, thay vì tạo entity mới mỗi ngày — nếu không bạn sẽ có
refactor-async-payment-day1,-day2,-day3rải rác, làmsearch_nodestrả về kết quả rối và mâu thuẫn nhau.
Những Hạn Chế Cần Biết Của Memory MCP Trong OpenCode
Trước khi phụ thuộc hoàn toàn vào memory, cần nắm rõ vài hạn chế thực tế:
- Không có cơ chế conflict-resolution tự động khi nhiều OpenCode instance chạy song song trên cùng một
MEMORY_FILE_PATH(ví dụ hai terminal cùng mở, cùng ghi). Vì file lưu dạng JSON Lines append-only, ghi đồng thời có thể dẫn tới race condition ở tầng filesystem tuỳ hệ điều hành. Thực tế nên tránh chạy nhiều instance ghi cùng một file memory đồng thời. - Không có giới hạn kích thước tích hợp — nếu không dọn dẹp, file
.jsonlsẽ phình to vô hạn theo thời gian, vàread_graph(đọc toàn bộ) sẽ ngày càng tốn token hơn. Với dự án chạy lâu, nên đặt lịch review/prune định kỳ. - Model của OpenCode có thể khác Claude (tuỳ provider bạn cấu hình) — hành vi "tự động gọi tool memory đúng lúc" phụ thuộc rất nhiều vào khả năng tool-calling của model đang chọn. Với model yếu hơn (ví dụ một số model open-source chạy local), agent có thể quên gọi
search_nodesdù bạn đã đặt rule — nên định kỳ nhắc trực tiếp trong prompt thay vì chỉ tin vào rule ngầm. - Không có UI trực quan để browse graph — mọi thao tác xem/sửa đều qua việc hỏi agent hoặc mở trực tiếp file
.jsonlbằng text editor, khá thô sơ so với các công cụ note-taking chuyên dụng.
Mẹo: Nếu team dùng nhiều loại model khác nhau qua OpenCode (ví dụ đổi qua đổi lại giữa Claude, GPT, và model local), hãy test riêng khả năng gọi tool memory đúng lúc của từng model — đừng giả định hành vi đồng nhất, vì đây là nguyên nhân phổ biến khiến người dùng nghĩ "memory bị hỏng" trong khi thực ra là model đang dùng không chủ động gọi tool.
Mẹo Hay Khi Dùng Memory MCP Với OpenCode
- Luôn commit file rule (
AGENTS.mdhoặc tương đương) có đoạn "Memory Protocol" vào repo — coi đó là tài sản chung của team, không phải thói quen cá nhân. - Với refactor dài ngày, tạo entity theo tên task cụ thể (không theo ngày) và cập nhật observation liên tục — tránh tạo nhiều entity trùng lặp.
- Backup file
.jsonltrước các milestone quan trọng (ví dụ trước khi release) bằng một dòng lệnh đơn giản trong script CI hoặc pre-commit hook.
Mẹo: Thêm một bước kiểm tra định kỳ: mỗi 2 tuần, yêu cầu agent
read_graphtoàn bộ rồi hỏi "có observation nào mâu thuẫn nhau không?" — chính agent có thể tự phát hiện phần lớn các conflict trong dữ liệu nó tự ghi ra.