Coding agent của bạn đang phải trả mức giá cao nhất của các mô hình frontier chỉ để giải những câu hỏi trắc nghiệm.
Nên load ghi chú nào? Bước này nên giao cho mô hình lớn hay nhỏ? Tool vừa bị lỗi. Thử lại, sửa, hay bỏ cuộc? Nên chạy test nào trước?
Mỗi câu hỏi đó đều có bốn hoặc năm đáp án khả thi. Và trong hầu hết các thiết lập agent hiện nay, tất cả chúng đều được trả lời bởi mô hình đắt đỏ nhất mà bạn có, với chế độ thinking được bật, đọc toàn bộ context và viết hẳn một đoạn văn trước khi đưa ra quyết định.
Đó chính là chỗ rò rỉ tiền.
Bài viết này sẽ chỉ cho bạn cách bịt lỗ hổng đó. Opus 5.5 đảm nhận phần suy luận khó: lên kế hoạch, viết code, debug. Jev xử lý bốn quyết định xuất hiện ở gần như mọi bước. Harness của bạn chuẩn bị các lựa chọn, kiểm tra đáp án và đưa ra quyết định cuối cùng.
Trong ví dụ thực tế bên dưới, chi phí cho một phiên làm việc (feature session) giảm từ $6.42 xuống còn $2.00. Tức là rẻ hơn 69%, và mọi phép tính đều được trình bày chi tiết trong bài để bạn có thể tự đối chiếu với số liệu của mình.
Bài viết này dành cho bất kỳ ai đang chạy coding agent trên công việc thực tế: Claude Code, harness tự build trên API, hay bất cứ thứ gì ở giữa. Bạn không cần phải viết lại agent của mình. Mọi thành phần trong bài đều có thể gắn vào vòng lặp hiện tại dưới dạng một function call kèm theo cờ (flag) để tắt đi nếu cần. Nếu bạn đã đọc bài viết về Jev + Claude Code của tôi, thì đây là phiên bản nâng cấp: cùng một ý tưởng, nhưng dùng mô hình suy luận mới hơn và áp dụng cho bốn quyết định cụ thể thay vì một nguyên tắc chung.
Bạn sẽ cần một API key của Jev, một API key của Anthropic, và khoảng một tuần log từ agent của chính bạn để làm mốc so sánh.
Bắt tay vào làm thôi.

opus suy luận, jev quyết định.
Vấn đề: Một mô hình gánh hai việc
Chỉ cần quan sát một coding agent làm việc trong mười phút, bạn sẽ thấy nó đang thực hiện hai loại công việc hoàn toàn khác nhau.
Việc thứ nhất là suy luận. Lên kế hoạch cho một tính năng. Viết một hàm. Đọc stack trace và tìm ra lý do tại sao trình phân tích ngày tháng lại lỗi vào năm nhuận. Công việc này mang tính mở. Đáp án không nằm trong một danh sách có sẵn. Ở khâu này, bạn cần mô hình thông minh nhất mà ngân sách cho phép, và Opus 5.5 làm điều đó rất tốt.
Việc thứ hai là ra quyết định. Chọn ra ba ghi chú dự án quan trọng trong số bốn mươi ghi chú. Quyết định xem việc đổi tên biến có thể giao cho một mô hình rẻ hơn không. Chọn hướng xử lý khi npm test bị timeout. Quyết định chạy 12 file test nào trước khi chạy toàn bộ 1,400 file. Những đáp án này đều nằm trong một danh sách. Danh sách đó rất ngắn. Và code của bạn có thể hành động trực tiếp dựa trên đáp án.
Hầu hết các agent đều chạy cả hai việc này qua cùng một mô hình, vì đó là thiết lập mặc định. Vòng lặp gọi Opus, Opus suy nghĩ, Opus trả lời, rồi vòng lặp tiếp tục.
Cách này vẫn hoạt động. Nhưng nó chậm và tốn kém theo kiểu rất dễ bị bỏ qua, vì từng lệnh gọi ra quyết định trông chẳng đáng bao nhiêu. Một lệnh gọi "tôi cần ghi chú nào" có lẽ chỉ tốn khoảng một xu. Nhưng nó xảy ra ở mọi bước, và mỗi lần đều kéo theo toàn bộ context.
Và còn một chi phí thứ hai thậm chí dễ bị bỏ sót hơn: khi agent không biết nên load cái gì, nó sẽ load tất cả. Mọi ghi chú dự án, mọi tài liệu quy chuẩn, mọi quyết định trong quá khứ đều bị nhồi nhét vào từng lệnh gọi. Opus 5.5 đã giúp việc đọc cache trở nên rẻ hơn với mức $0.20 cho mỗi triệu token, nhưng "rẻ nhân với sáu mươi bước nhân với toàn bộ thư mục ghi chú của bạn" thì vẫn cộng dồn thành một khoản lớn.
Giải pháp: Opus suy luận, Jev quyết định, Harness của bạn cầm trịch
Jev là mô hình từ TypeSafe được tạo ra chính xác cho việc thứ hai. Nó không viết văn bản. Bạn cung cấp cho nó context và các câu hỏi đã định kiểu (typed questions) với một tập hợp lựa chọn cố định, và nó trả về xác suất cho từng lựa chọn. Nó phản hồi trong vài mili giây, chi phí đầu vào là $0.042 cho mỗi triệu token, và đầu ra miễn phí.
Điều đó khiến kiến trúc hệ thống trở nên rất dễ mô tả:
Opus 5.5 lo phần suy luận. Lên kế hoạch, viết code, debug, và bất cứ thứ gì mà đáp án không nằm trong danh sách có sẵn.
Jev đưa ra các quyết định nhỏ. Nó chọn từ các phương án mà harness của bạn đã chuẩn bị.
Harness của bạn nắm quyền kiểm soát. Nó xây dựng danh sách lựa chọn, đọc xác suất, áp dụng ngưỡng (threshold), và chuyển ngược về Opus khi Jev không chắc chắn.
Dòng thứ ba là phần mọi người thường bỏ qua, và cũng là phần giúp toàn bộ hệ thống an toàn. Jev không bao giờ tự bịa ra một lựa chọn. Jev không bao giờ có tiếng nói cuối cùng cho những việc bạn không thể hoàn tác. Code của bạn quyết định thế nào là "đủ chắc chắn".
Đây là hàm tiện ích (helper) làm nền tảng cho mọi thứ khác trong bài viết này:
from dataclasses import dataclass
class Decision:
answer: str
prob: float
probs: dict
confident: bool
def jev_choice(context: str, question: str, options: list[str]):
Kết nối phần này với Jev client của bạn: TypeSafe SDK, Vercel AI Gateway,
hoặc package LangChain. Nó phải trả về {option: probability}
cho mọi option bạn truyền vào.
raise NotImplementedError
def decide(context: str, question: str, options: list[str], threshold: float):
probs = jev_choice(context, question, options)
answer = max(probs, key=probs.get)
return Decision(answer, probs[answer], probs, probs[answer] >= threshold)
Hãy để ý xem có gì thiếu trong đó: không có câu hỏi nào yêu cầu Jev tự đánh giá mức độ chắc chắn của nó. Bạn chỉ cần đọc xác suất mà nó trả về. Việc hỏi bất kỳ mô hình nào "bạn có chắc không?" gần như lúc nào cũng nhận được câu trả lời "có". Xác suất mới là tín hiệu trung thực.
Giờ hãy đến với bốn quyết định.

Bốn quyết định bên trong một bước của agent
Quyết định 1: Chọn ghi chú dự án liên quan trước khi load context
Đây là đòn bẩy đơn lẻ mạnh nhất, và cũng là thứ gần như chưa ai xây dựng.
Agent của bạn có một thư mục ghi chú. Một file AGENTS.md, tài liệu kiến trúc, các quy chuẩn, quyết định trong quá khứ, và những cảnh báo kiểu "không bao giờ được đụng vào module thanh toán nếu chưa có migration". Có thể lên tới 30,000 token. Hầu hết các agent load toàn bộ đống này trong mỗi lệnh gọi, vì không ai muốn trở thành kẻ bỏ sót ghi chú quan trọng.
Vậy nên thay vì load tất cả, bạn chỉ cần hỏi Jev một câu đơn giản về từng ghi chú, chạy song song toàn bộ: agent có cần ghi chú này cho tác vụ hiện tại không?
Trước tiên, hãy chia nhỏ ghi chú của bạn thành các chunk theo heading. Mỗi phần của AGENTS.md trở thành một chunk riêng. Mỗi tài liệu kiến trúc trở thành một hoặc nhiều chunk.
import re
def chunk_notes(markdown: str, source: str):
parts = re.split(r"
(?=## )", markdown)
return [{"source": source, "text": p.strip()} for p in parts if p.strip()]
Sau đó chấm điểm từng chunk dựa trên tác vụ hiện tại:
from concurrent.futures import ThreadPoolExecutor
def pick_notes(task: str, notes: list[dict], keep: int = 6, floor: float = 0.55):
def score(note):
probs = jev_choice(
context=f"TASK:
{task}
NOTE ({note['source']}):
{note['text']}",
question="Would an engineer need this note to do the task correctly?",
options=["needed", "not_needed"],
)
return probs["needed"], note
with ThreadPoolExecutor(max_workers=16) as pool:
scored = sorted(pool.map(score, notes), key=lambda s: s[0], reverse=True)
picked = [n for p, n in scored[:keep] if p >= floor]
return picked or [n for _, n in scored[:2]]
Có ba chi tiết quan trọng ở đây.
Luôn load những thứ không thể thương lượng. Một số ghi chú bắt buộc phải có mặt trong mọi lệnh gọi dù thế nào đi nữa: quy tắc bảo mật, "không bao giờ force push", dòng duy nhất chỉ định database nào là production. Hãy gắn thẻ "always" cho chúng và bỏ qua bước chấm điểm.
Giữ một mức sàn và một phương án dự phòng. Nếu không có gì vượt qua mức 0.55, bạn vẫn load hai chunk đứng đầu. Một agent không có context nào còn tệ hơn một agent có hơi thừa context.
Ghi log lại những gì bị loại bỏ. Khi agent mắc lỗi, điều đầu tiên bạn cần kiểm tra là liệu ghi chú có thể ngăn chặn lỗi đó có bị loại mất hay không. Log đó chính là cách bạn tinh chỉnh tham số keep và floor.
Trong ví dụ thực tế, chỉ riêng thay đổi này đã giảm phần ghi chú của mỗi lệnh gọi từ 30,000 token xuống còn 6,000 token. Chỉ tính riêng nó, chi phí của phiên làm việc đã giảm khoảng 24%.
Quyết định 2: Điều hướng các tác vụ phù hợp sang worker nhanh hơn
Không phải bước nào cũng cần đến Opus.
Việc đổi tên một hàm trên tám file thì không. Thêm một trường vào form vốn đã có chín trường tương tự thì không. Cập nhật đường dẫn import thì không. Đây là những thao tác chỉnh sửa tuân theo một pattern đã có sẵn trong codebase.
Vì vậy, trước khi mỗi bước chạy, Jev sẽ phân loại bước đó, và harness của bạn ánh xạ loại đó sang một worker:
ROUTES = {
"rename_or_move": "fast",
"small_edit_following_existing_pattern": "fast",
"new_logic": "opus",
"debugging": "opus",
"design_decision": "opus",
}
def route(step: str, recent_diff: str):
d = decide(
context=f"STEP:
{step}
RECENT CHANGES:
{recent_diff}",
question="What kind of work is this step?",
options=list(ROUTES),
threshold=0.8,
)
if not d.confident:
return "opus"
return ROUTES[d.answer]
Hãy nhìn cách các lựa chọn được viết. Chúng không phải là "dễ" và "khó", và chắc chắn không phải là "mô hình nhỏ có xử lý được không?". Chúng là những loại công việc cụ thể mà code của bạn có thể ánh xạ thành hành động. Đó là quy tắc cho mọi câu hỏi gửi tới Jev: mỗi lựa chọn phải là thứ mà harness của bạn biết cách xử lý.
Và hãy để ý giá trị mặc định. Dưới mức 0.8, bước đó sẽ được chuyển cho Opus. Lỗi điều hướng ở đây chỉ xảy ra theo một hướng: một tác vụ khó bị đẩy sang worker nhanh sẽ khiến bạn mất một bước thất bại và phải thử lại, trong khi một tác vụ dễ bị đẩy sang Opus chỉ tốn thêm một chút tiền. Vậy nên khi còn nghi ngờ, hãy đẩy lên trên.
Với worker nhanh, tôi dùng Haiku 4.5 ở mức $1 cho mỗi triệu token đầu vào và $5 cho mỗi triệu token đầu ra. Trong ví dụ thực tế, 12 trong số 36 bước công việc thực sự được chuyển sang nó.
Quyết định 3: Chọn hướng khắc phục khi tool bị lỗi
Các tool liên tục gặp lỗi. Test bị timeout. Đường dẫn file sai. Package chưa được cài đặt. Lệnh shell dính lỗi quyền truy cập. Linter phàn nàn về một thứ chẳng liên quan.
Hầu hết các agent xử lý việc này theo cách tốn kém nhất có thể: chúng ném toàn bộ lỗi trở lại mô hình lớn và để nó tự nghĩ xem nên làm gì. Đôi khi cách đó đúng. Nhưng thường thì đáp án quá rõ ràng, và Opus tiêu tốn 1,500 token chỉ để nhận ra rằng ENOENT nghĩa là file không tồn tại.
Tệ hơn, các agent bị kẹt trong vòng lặp. Thử lại, lỗi, thử lại, lỗi, và mỗi lần đều phải trả tiền cho một bước suy luận đầy đủ.
Vì vậy, bạn đưa lỗi đó cho Jev kèm theo một tập hợp các hướng khắc phục cố định:
from collections import deque
def tail(text: str, n: int = 4000):
return "".join(deque(text, maxlen=n)) # n ký tự cuối cùng của thông báo lỗi
def recover(tool: str, command: str, error: str, attempt: int):
if attempt >= 3:
return "stop_and_report"
d = decide(
context=f"TOOL: {tool}
COMMAND: {command}
ATTEMPT: {attempt}
ERROR:
{tail(error)}",
question="What is the best next move after this failure?",
options=RECOVERY,
threshold=0.8,
)
return d.answer if d.confident else "escalate_to_opus"
1RECOVERY = [2 "retry_unchanged", # mạng chập chờn hoặc timeout3 "retry_after_install", # thiếu package hoặc tool4 "fix_path_and_retry", # sai đường dẫn file hoặc cwd5 "switch_tool", # tool này không làm được, tool khác có thể6 "escalate_to_opus", # cần debug thực sự7 "stop_and_report", # cần con người can thiệp8]
Giới hạn cứng về số lần thử nằm trong code, không phải trong mô hình. Không một mô hình nào, dù rẻ đến đâu, được phép thử lại mãi mãi.
Mỗi hướng khắc phục được ánh xạ tới một hàm nhỏ trong harness của bạn. retry_after_install dùng regex trích xuất tên package bị thiếu từ thông báo lỗi và cài đặt nó. fix_path_and_retry kiểm tra các đường dẫn đang tồn tại và gợi ý đường dẫn gần khớp nhất. Chỉ có escalate_to_opus là tiêu tiền thật, và nó chỉ được kích hoạt khi lỗi thực sự cần đến tư duy.
Trong ví dụ thực tế, việc này loại bỏ 6 bước thử lại vô ích khỏi phiên làm việc.
Quyết định 4: Chạy các bài kiểm tra trọng tâm trước khi chạy toàn bộ test suite
Bước này tiết kiệm thời gian nhiều hơn là tiền bạc, và thời gian chính là thứ khiến agent mang lại cảm giác nhanh chóng.
Sau mỗi thay đổi, hầu hết các agent đều chạy toàn bộ test suite. Nếu suite của bạn mất bốn phút, agent sẽ ngồi chờ bốn phút sau mỗi lần chỉnh sửa, rồi lại phải đọc qua hàng trăm dòng output để tìm ra lỗi duy nhất thực sự quan trọng.
Cách khắc phục cũng theo pattern giống như phần ghi chú: chấm điểm từng file test dựa trên diff, chạy những file liên quan nhất trước, và chỉ chạy toàn bộ suite khi các bài kiểm tra trọng tâm đã pass.
1def pick_tests(diff: str, test_files: list[str], keep: int = 12):2 def score(path):3 probs = jev_choice(4 context=f"DIFF:\n{diff[:12000]}\n\nTEST FILE: {path}",5 question="Could this change break tests in this file?",6 options=["likely", "unlikely"],7 )8 return probs["likely"], path910 with ThreadPoolExecutor(max_workers=16) as pool:11 scored = sorted(pool.map(score, test_files), key=lambda s: s[0], reverse=True)12 return [p for _, p in scored[:keep]]1314def check(diff: str, test_files: list[str]):15 focused = pick_tests(diff, test_files)16 if not run_tests(focused):17 return False # fail fast, sửa trước khi làm bất cứ điều gì khác18 return run_tests(test_files) # toàn bộ suite vẫn là chốt chặn cuối trước khi commit
Hãy đọc lại dòng cuối cùng đó. Toàn bộ suite vẫn chạy trước khi bất cứ thứ gì được commit. Các bài kiểm tra trọng tâm chỉ là cảnh báo sớm, không phải sự thay thế. Bạn phát hiện phần lớn lỗi trong vài giây thay vì vài phút, và không bao giờ tung ra thứ mà lẽ ra test suite đầy đủ đã chặn lại.
Cũng hãy thêm các bước kiểm tra rẻ tiền trước: type check và lint chỉ trên những file đã thay đổi. Chúng chỉ mất một giây nhưng chặn được một tỷ lệ lỗi đáng ngạc nhiên trước khi bất kỳ test nào chạy.
Kết hợp lại: Vòng lặp của Harness
Đây là cách bốn quyết định trên nằm gọn trong một bước của vòng lặp:
def run_step(task: str, step: str, state):
1. context: chỉ load những ghi chú mà bước này cần
notes = state.always_notes + pick_notes(step, state.notes)
2. routing: chọn worker cho bước này
worker = state.workers[route(step, state.recent_diff())]
result = worker.run(step, notes=notes, history=state.history)
3. recovery: xử lý mọi lỗi tool trong bước này
for failure in result.failures:
action = recover(failure.tool, failure.command, failure.error, failure.attempt)
state.apply_recovery(action, failure)
4. checks: test trọng tâm trước, toàn bộ suite trước khi commit
if result.diff:
state.log_check(check(result.diff, state.test_files))
Và đây là phần của Opus: nó chỉ là lệnh gọi Opus 5.5 bình thường của bạn. Hãy đặt context ổn định lên đầu (system prompt, định nghĩa tool, các ghi chú "always") để nó được lưu cache xuyên suốt các bước, và đặt phần nội dung đặc thù của từng bước xuống cuối.
import os
import anthropic
client = anthropic.Anthropic()
OPUS = os.environ["OPUS_MODEL"] # model id Opus 5.5 của bạn
def opus_step(system: str, notes: list[dict], history: list, step: str):
notes_text = "
".join(n["text"] for n in notes)
return client.messages.create(
model=OPUS,
max_tokens=8000,
system=[{"type": "text", "text": system, "cache_control": {"type": "ephemeral"}}],
messages=history + [{"role": "user", "content": f"NOTES:
{notes_text}
STEP:
{step}"}],
)
Chẳng có gì cao siêu. Khoản tiết kiệm đến từ những gì bạn ngừng gửi cho nó, chứ không phải từ một prompt khéo léo nào cả.
Mổ xẻ một bước
Đây là diện mạo của một bước trong log khi cả bốn quyết định đều đã được áp dụng. Tác vụ: thêm rate limiting vào endpoint đăng ký công khai. Trace này mang tính minh họa, nhưng nó chính là hình dáng bạn sẽ thấy trong log của mình.
step 14 "add a per IP rate limit to POST /signup"
[notes] chấm điểm 41 chunk song song
giữ lại: api/middleware.md (0.94), conventions/errors.md (0.88),
infra/redis.md (0.81), decisions/2025_auth.md (0.62)
loại bỏ: 37 chunk, bao gồm billing, email templates, CI
[route] new_logic (0.91) → opus
[opus] lên kế hoạch thay đổi, viết middleware + config + chỉnh sửa handler
[tool] npm test FAILED "Cannot find module 'bottleneck'"
[recover] retry_after_install (0.97) → npm install, chạy lại
[checks] typecheck các file đã thay đổi: pass
test trọng tâm (12 trên 1,388): pass
toàn bộ suite: pass
Hãy đọc từ trên xuống dưới và đếm xem có bao nhiêu dòng trong số đó trước đây từng là một lệnh gọi Opus đầy đủ. Phần chọn ghi chú: một lệnh gọi lớn, hoặc không chọn gì cả và load mù quáng 30,000 token ghi chú. Phần điều hướng: không có gì, mọi bước đều đổ về Opus. Phần thiếu package: một bước suy luận đầy đủ chỉ để nhận ra rằng thiếu module nghĩa là "cài module đó vào". Phần chọn test: không có gì, chạy toàn bộ suite sau mỗi lần chỉnh sửa.
Giờ thì chỉ còn một dòng trong trace đó là Opus, và đó chính là dòng thực sự cần đến một mô hình frontier: lên kế hoạch và viết rate limiter.
Đó là toàn bộ ý tưởng gói gọn trong một bức tranh. Mô hình đắt tiền dành thời gian của nó cho phần việc mà chỉ nó mới làm được.
Ví dụ thực tế: Con số 69% đến từ đâu
Đây là toàn bộ phép tính cho một phiên làm việc: 60 bước của agent cộng thêm 6 lần thử lại vô ích mà một agent điển hình thường tích lũy dọc đường. Mọi mức giá đều là giá niêm yết công khai hiện tại.
Trước: Opus 5.5 làm mọi thứ
Mỗi bước load 70,000 token context: 15,000 cho system prompt và tool, 30,000 cho toàn bộ thư mục ghi chú, và 25,000 cho cuộc hội thoại tính đến thời điểm đó. Tôi giả định 80% trong số đó là cache hit. Mỗi bước tạo ra khoảng 1,500 token đầu ra, vì chế độ thinking luôn được bật trong Opus 5.5.
cache reads: 56,000 × $0.20/M = $0.0112
fresh input: 14,000 × $4.00/M = $0.0560
output: 1,500 × $20.00/M = $0.0300
mỗi bước = $0.0972
66 bước × $0.0972 = $6.42
Sau: có thêm lớp quyết định
Context giảm xuống còn 46,000 token mỗi bước, vì Jev chọn 6,000 token ghi chú thay vì load cả 30,000. 24 bước thuần túy để ra quyết định được chuyển sang Jev. 6 vòng lặp thử lại biến mất. Và 12 trong số 36 bước công việc còn lại được chuyển sang Haiku 4.5.
Opus 5.5: 24 bước × $0.0742 = $1.78
Haiku 4.5: 12 bước × $0.0169 = $0.20
Jev: 102 lệnh gọi × 5,000 token
× $0.042/M, đầu ra miễn phí = $0.02
tổng cộng = $2.00
Từ $6.42 xuống $2.00. Rẻ hơn 68.8% cho cùng một tính năng.

hãy đặt ngưỡng dựa trên chi phí của một đáp án sai
Và đây là mức đóng góp của từng đòn bẩy, xếp theo thứ tự:
chỉ chọn lọc ghi chú $4.89 tiết kiệm 23.7%
- chuyển quyết định sang Jev $3.13 tiết kiệm 51.2%
- các hướng khắc phục $2.69 tiết kiệm 58.1%
- điều hướng sang worker nhanh $2.00 tiết kiệm 68.8%
Hai lưu ý thẳng thắn về phép tính này.
Thứ nhất, đây là những con số mô phỏng dựa trên các giả định rõ ràng, không phải kết quả đo lường từ hệ thống của bạn. Kích thước context, tỷ lệ cache hit và số lượng quyết định của bạn sẽ khác. Mục đích của việc trình bày từng dòng là để bạn có thể thay bằng số liệu của chính mình. Khi đã đo lường được thực tế trước và sau, hãy dùng con số của bạn, không phải của tôi.
Thứ hai, hãy nhìn xem tiền thực sự chảy đi đâu. 102 lệnh gọi của Jev tổng cộng chỉ tốn hai xu. Khoản tiết kiệm không đến từ việc Jev rẻ ở mỗi lệnh gọi. Nó đến từ tất cả những thứ không còn xảy ra nữa một khi Jev đã ra quyết định: context phình to, các bước suy luận đầy đủ cho câu hỏi trắc nghiệm, vòng lặp thử lại, và những lệnh gọi mô hình lớn cho việc đổi tên biến.
Sao không dùng luôn Haiku cho các quyết định?
Câu hỏi rất hợp lý. Haiku 4.5 vừa rẻ vừa nhanh. Sao phải thêm một mô hình mới?
Có ba lý do.
Nó vẫn viết văn bản. Haiku trả lời bằng text. Bạn phải prompt nó trả lời bằng một trong các lựa chọn của bạn, rồi parse câu trả lời, rồi xử lý những lúc nó tự thêm phần giải thích, chọn một thứ không có trong danh sách, hoặc bọc đáp án vào trong một câu hoàn chỉnh. Jev trả về xác suất cho mọi lựa chọn bạn truyền vào. Chẳng có gì phải parse và không có gì nằm ngoài danh sách.
Bạn nhận được toàn bộ phân phối xác suất, không chỉ một đáp án. Khi Jev trả về needed: 0.52, not_needed: 0.48, bạn biết đó là một pha tung đồng xu và harness của bạn có thể leo thang xử lý. Khi một mô hình text nói "needed", bạn chẳng biết nó có thực sự chắc chắn hay không. Ngưỡng chỉ phát huy tác dụng khi bạn nhìn thấy được xác suất.
Bài toán chi phí khác biệt. Đầu ra của Jev miễn phí và đầu vào là $0.042 cho mỗi triệu token. Việc chấm điểm 41 chunk ghi chú ở mỗi bước nghĩa là 41 lệnh gọi nhỏ mỗi bước. Với Jev, đó chỉ là một phần nhỏ của một xu. Với bất kỳ mô hình text nào, kể cả loại rẻ, đó là 41 lần sinh văn bản với chi phí đầu ra và độ trễ riêng.
Hãy dùng Haiku cho những chỉnh sửa nhỏ, nơi nó thực sự phải viết code. Dùng Jev để chọn từ danh sách. Dùng Opus để tư duy. Mỗi mô hình làm đúng việc nó được sinh ra để làm.
Cách triển khai mà không phá hỏng thứ gì
Đừng bật cả bốn quyết định cùng một lúc. Đây là thứ tự tôi khuyên dùng.
Tuần 1: chế độ shadow. Giữ nguyên agent hiện tại của bạn. Với mỗi quyết định nó đưa ra, hãy hỏi Jev cùng câu hỏi đó và ghi log cả hai đáp án kèm theo xác suất của Jev. Đừng hành động gì dựa trên đáp án của Jev cả.
1def shadow(decision_name, context, question, options, current_answer):2 probs = jev_choice(context, question, options)3 jev_answer = max(probs, key=probs.get)4 log_row(5 decision=decision_name,6 current=current_answer,7 jev=jev_answer,8 prob=probs[jev_answer],9 agree=(jev_answer == current_answer),10 )
Tuần 2: đọc các điểm bất đồng. Chỉ nhìn vào những dòng mà Jev và agent hiện tại của bạn có đáp án khác nhau. Sắp xếp chúng theo xác suất của Jev. Bạn thường sẽ tìm ra một ranh giới rõ ràng: trên một mức xác suất nào đó, Jev đúng với tần suất ngang ngửa Opus. Ranh giới đó chính là ngưỡng của bạn. Những dòng bất đồng đó cũng trở thành tập dữ liệu test của bạn, được tạo ra miễn phí từ traffic thực tế.
Tuần 3: bật tính năng chọn ghi chú. Đây là đòn bẩy lớn nhất và dễ hoàn tác nhất, vì một ghi chú bị bỏ sót sẽ lộ ra rất nhanh trong log của bạn.
Tuần 4: bật tính năng khắc phục và test. Cả hai đều có giới hạn cứng và phương án dự phòng trong code, nên trường hợp xấu nhất chỉ là quay về cách bạn đang làm hiện tại.
Cuối cùng: điều hướng. Lỗi điều hướng là thứ người dùng dễ nhận thấy nhất, vì một tác vụ khó bị đẩy sang worker nhanh sẽ sinh ra code tồi. Hãy bật nó sau cùng, với một ngưỡng thận trọng, và theo dõi tỷ lệ lỗi ở các bước do worker nhanh xử lý.
Đặt mọi quyết định phía sau một cờ bật/tắt để bạn có thể hoàn tác nó chỉ bằng một dòng code.
Thiết lập ngưỡng theo mức độ rủi ro
Dùng chung một ngưỡng cho mọi thứ là một sai lầm. Hãy thiết lập chúng dựa trên hậu quả khi đáp án bị sai.

Một phiên làm việc, cùng kết quả: từ $6.42 xuống $2.00
Rủi ro thấp, dễ hoàn tác: 0.55 đến 0.65. Chọn ghi chú. Sắp xếp thứ tự test. Một đáp án sai chỉ tốn thêm chút context hoặc vài giây.
Rủi ro trung bình: 0.8. Điều hướng và khắc phục. Một đáp án sai khiến một bước thất bại, nhưng harness của bạn sẽ bắt được.
Rủi ro cao, khó hoàn tác: 0.9 hoặc không bao giờ. Xóa file. Force push. Động vào config production. Chạy migration. Lời khuyên chân thành của tôi: đừng để bất kỳ mô hình nào tự đưa ra những quyết định này. Hãy chuyển chúng cho con người, hoặc tối thiểu là cho Opus kèm theo một bước xác nhận.
Bất cứ thứ gì dưới ngưỡng sẽ được đẩy lên cấp cao hơn: về Opus nếu cần suy luận, về con người nếu cần phán đoán.
Khi nào cách này không hiệu quả
Kiến trúc này không phải là phép màu nhân đôi hiệu suất cho mọi khối lượng công việc.
Các tác vụ thuần sinh văn bản gần như không thay đổi. Nếu agent của bạn dành phần lớn thời gian để viết lượng lớn code mới từ một bản spec rõ ràng, thì chẳng có nhiều quyết định để di chuyển. Bạn vẫn tiết kiệm được ở khâu chọn ghi chú, nhưng không nhiều hơn thế.
Dự án nhỏ không cần đến nó. Nếu toàn bộ thư mục ghi chú của bạn chỉ có 2,000 token và test suite chạy trong tám giây, thì chi phí xây dựng hệ thống này chưa đáng để bỏ ra.
Jev không giỏi tự mình đưa ra quyết định cuối cùng. Nó cực kỳ xuất sắc trong việc nhận diện vấn đề và chọn từ một danh sách ngắn. Nó không phải mô hình bạn nên dùng để trả lời câu hỏi đơn lẻ kiểu "pull request này đã sẵn sàng merge chưa?". Hãy chia nhỏ các câu hỏi lớn, chấm điểm từng phần, và kết hợp kết quả trong code của bạn với trọng số do bạn tự định.
Nếu bạn đã có dữ liệu gán nhãn cho một câu hỏi cố định, một mô hình nhỏ do bạn tự host có thể đánh bại Jev về giá. Jev tỏa sáng khi các câu hỏi liên tục thay đổi và bạn không có dữ liệu huấn luyện — điều này mô tả chính xác phần lớn các coding agent.
Những sai lầm tôi khuyên bạn nên tránh
Để mô hình tự viết danh sách lựa chọn. Toàn bộ kiến trúc phụ thuộc vào các lựa chọn mà code của bạn có thể hành động dựa trên đó. Nếu một mô hình tự sinh ra các lựa chọn, bạn lại quay về bài toán parse văn bản tự do.
Hỏi Jev xem nó có chắc chắn không. Thay vào đó, hãy đọc xác suất. Câu trả lời tự đánh giá gần như lúc nào cũng là "có".
Không có phương án dự phòng. Mọi quyết định của Jev đều cần một đường lui cho trường hợp "không chắc", và đường lui đó là Opus hoặc con người, không bao giờ là một sự đoán mò.
Đặt giới hạn thử lại trong prompt thay vì trong code. Một mô hình được dặn "chỉ thử lại 3 lần" thỉnh thoảng vẫn sẽ thử lại 30 lần. Code thì không.
Bỏ luôn toàn bộ test suite. Kiểm tra trọng tâm giúp bạn tăng tốc. Toàn bộ suite giữ bạn trung thực. Hãy giữ cả hai.
Không đo lường gì cả. Nếu bạn không ghi nhận chi phí mỗi phiên làm việc trước khi bắt đầu, bạn sẽ chẳng bao giờ biết mình đã tiết kiệm được 20% hay 70%. Hãy trích xuất dữ liệu sử dụng trong một tuần làm việc bình thường trước đã. Việc này chỉ mất mười phút và đó là con số duy nhất thực sự quan trọng.
Những việc cần làm trong tuần này
Dưới đây là toàn bộ quy trình dưới dạng checklist:
- Ghi nhận một tuần chạy các phiên agent: số bước, token, chi phí, lỗi.
- Tìm ra những quyết định đang ẩn trong vòng lặp của bạn: notes, routing, recovery, tests.
- Viết lại từng quyết định dưới dạng một câu hỏi kèm danh sách các lựa chọn cố định.
- Chạy Jev ở chế độ shadow song song với agent hiện tại của bạn trong một tuần.
- Thiết lập ngưỡng từ nhật ký bất đồng (disagreement log), dựa trên mức độ rủi ro.
- Bật tính năng chọn notes trước, sau đó đến recovery và tests, cuối cùng là routing.
- So sánh chi phí mỗi phiên trước và sau. Đó chính là con số của bạn.
Opus 5.5 là mô hình suy luận tốt nhất tôi từng dùng cho code. Sai lầm nằm ở chỗ bắt nó làm luôn mọi thứ khác.
Hãy để nó suy nghĩ. Để Jev quyết định. Để code của bạn lên ngôi.
Nếu bài viết này hữu ích, hãy theo dõi @cyrilXBT. Mỗi tuần, tôi đều chia sẻ cách xây dựng sản phẩm với các mô hình AI mới nhất, kèm theo những con số thực tế.
Lưu lại bài viết này để có ngay khi bạn bắt tay vào xây dựng nhé.





