Harness Engineering

Model quyết định. Harness thực thi.The model decides. The harness executes.

Mọi thứ quanh model, từ vòng lặp, context, sandbox, quyền đến giao diện và đo lường, là thứ bạn kiểm soát được. Giữ nguyên model, đổi harness, kết quả đã khác hẳn.Everything around the model, from the loop, context, sandbox and permissions to interfaces and measurement, is what you control. Keep the model, change the harness, and results shift.

Chọn cái nàoWhat to pick

Câu hỏi đầu tiên không phải "dùng module nào" mà là "có cần xây không".The first question isn't "which module" but "should I build at all".

Một lần gọi là đủOne call is enoughPhân loại, tóm tắt, trích xuất: gọi API một lần. Không vòng lặp, không tool.Classify, summarise, extract: one API call. No loop, no tools.
Bước đã biết trướcSteps known in advanceViết workflow bằng code, gọi LLM đúng chỗ. Đó không phải agent và không cần là agent.Write a code workflow, call the LLM where needed. Not an agent, and it needn't be.
Harness có sẵn đủ dùngAn existing harness fitsClaude Code hoặc Codex cộng memory, skills, hooks. Đưa agent vào sản phẩm thì dùng Claude Agent SDK.Claude Code or Codex plus memory, skills, hooks. To embed in a product, use the Claude Agent SDK.
Việc cần nhiều bước, số bước không biết trước?
├─ Không ──► gọi API một lần hoặc workflow cố định. DỪNG.
└─ Có ──► Harness có sẵn + cấu hình làm được?
          ├─ Có ──► dùng nó. DỪNG.
          └─ Không ──► tự xây: Agent Loop + Sandbox + Permissions
                ├─ Phiên dài, nhiều file?          ──► + Compaction
                ├─ Có người ngồi cạnh?             ──► + Interactive
                ├─ Chạy không người, theo sự kiện? ──► Headless + Triggers
                ├─ Cần đổi model/nhà cung cấp?     ──► + LLM Providers
                ├─ Nhắc lại cùng điều mỗi phiên?   ──► + Memory
                ├─ Hướng dẫn dài, ít khi cần?      ──► + Skills
                ├─ Codebase lớn có type?           ──► + LSP
                └─ Sắp đổi prompt/model/tool?      ──► + Evals, TRƯỚC khi đổi
Several steps, number unknown in advance?
├─ No ──► single API call or fixed workflow. STOP.
└─ Yes ──► Can an existing harness + config do it?
           ├─ Yes ──► use it. STOP.
           └─ No ──► build: Agent Loop + Sandbox + Permissions
                 ├─ Long sessions, many files?      ──► + Compaction
                 ├─ A human alongside?              ──► + Interactive
                 ├─ Unattended, event-driven?       ──► Headless + Triggers
                 ├─ Need to switch model/vendor?    ──► + LLM Providers
                 ├─ Repeating yourself each session?──► + Memory
                 ├─ Long, rarely-needed instructions?──► + Skills
                 ├─ Large typed codebase?           ──► + LSP
                 └─ About to change prompt/model?   ──► + Evals, BEFORE

Các khái niệmThe concepts

LõiCore

phần không thể thiếuthe parts you can't skip
C1

Agent loop

LõiCore
messages ─► LLM ─► tool_use? ─ no ─► answer, stop
             ▲         │ yes
             │         ▼
       observation ◄─ run tools

Vòng while: gọi LLM, chạy tool nó yêu cầu, nối kết quả, gọi lại, dừng khi không còn tool call.A while loop: call the LLM, run the tools it asks for, append results, repeat until no tool call remains.

Dùng choUse for
Sửa bug nhiều file, tra cứu nhiều bước, tự động hoá thao tác hệ thống.Multi-file bug fixes, multi-step research, system automation.
ĐượcGain
Lõi vài chục dòng; thêm năng lực bằng thêm tool.A few dozen lines of core; new capability means a new tool.
MấtLose
Có thể lặp vô hạn; chi phí khó đoán.Can loop forever; cost is hard to predict.

Đổi khả năng dự đoán lấy khả năng xử lý việc không viết trước được kịch bản.Trades predictability for handling work you can't script in advance.

Nhận biết:Sign: bạn không liệt kê trước được các bước.you can't list the steps up front.

C2

Context & compaction

LõiCore
before: [sys][m1 … m40][m41 … m50]
after:  [sys][summary ][m41 … m50]
                         └ *tail ┘

Gần đầy context window thì tóm tắt phần cũ, giữ nguyên phần đuôi gần nhất.Near the limit, summarise the old part and keep the recent tail verbatim.

Dùng choUse for
Phiên hàng giờ, refactor hàng chục file, agent chạy nền.Hours-long sessions, large refactors, background agents.
ĐượcGain
Phiên gần như không giới hạn; ít token mỗi lượt.Near-unlimited sessions; fewer tokens per turn.
MấtLose
Mất chi tiết; phá prompt cache; tóm tắt sai thì lỗi lan âm thầm.Lost detail; broken prompt cache; a bad summary spreads silently.

Đổi độ trung thực của lịch sử lấy độ dài phiên.Trades fidelity of history for session length.

Nhận biết:Sign: phiên bình thường đã vượt nửa context window.a normal session already passes half the window.

C3

Headless harness

LõiCore
TUI  ┐
CLI  ┼─► harness.run(task) ─► events:
Cron ┘     text, tool_start, tool_end, ask, done

Lõi agent không gắn với giao diện nào; nhận task, phát luồng sự kiện.The agent core with no UI attached; takes a task, emits events.

Dùng choUse for
Chạy cả local lẫn cloud, chạy song song, eval trên code production.Local and cloud alike, parallel runs, evals on production code.
ĐượcGain
Một lõi, nhiều giao diện; kiểm thử không cần UI.One core, many shells; tests without a UI.
MấtLose
Phải thiết kế giao thức sự kiện từ đầu; mọi chỗ hỏi người cần phương án tự động.Event protocol designed up front; every human prompt needs an automated answer.

Đổi công thiết kế ban đầu lấy việc dùng lại một lõi ở mọi môi trường.Trades up-front design for one core reused everywhere.

Nhận biết:Sign: cần gọi agent từ nơi không có người.you need to call the agent where nobody is sitting.

Giao diệnInterfaces

vỏ bọc quanh lõishells around the core
I1

Interactive

Giao diệnInterface
human ─► TUI ─► [queue] ─► gate ─► harness
  ▲                        │ Esc: straight through
  └──── streamed events ◄──┘

TUI có steering queue (tin nhắn chờ chèn ở ranh giới lượt), priority gate (lệnh ngắt đi thẳng) và luồng sự kiện streaming.A TUI with a steering queue (messages injected at turn boundaries), a priority gate (interrupts go straight through) and streamed events.

Dùng choUse for
Pair-programming, việc cần chỉnh hướng, khám phá codebase lạ.Pair-programming, mid-course corrections, exploring unfamiliar code.
ĐượcGain
Sửa hướng sớm đỡ tốn token; người duyệt quyền tại chỗ.Early correction saves tokens; humans approve on the spot.
MấtLose
Chèn sai lúc phá cặp tool_use/tool_result; huỷ giữa chừng để lại trạng thái dở.Bad timing breaks tool_use/tool_result pairs; cancels leave partial state.

Đổi khả năng mở rộng lấy chất lượng nhờ có người lái theo thời gian thực.Trades scale for quality from real-time human steering.

Nhận biết:Sign: người dùng hay muốn nói "khoan, không phải file đó".users keep wanting to say "wait, not that file".

I2

Remote

Giao diệnInterface
CLI ─┐            ┌─► harness #1 ─► PR
Hook ┼─► job queue ┼─► harness #2 ─► PR
Cron ┘            └─► harness #N ─► PR

Chạy không cần người trông, kích hoạt qua CLI, webhook hoặc cron; N phiên song song, mỗi phiên một sandbox.Unattended runs triggered by CLI, webhook or cron; N parallel sessions, one sandbox each.

Dùng choUse for
Tự sửa khi CI thất bại, phân loại issue, báo cáo hằng đêm.Auto-fixing CI, issue triage, nightly reports.
ĐượcGain
Chạy 24/7; thông lượng nhân N.Runs 24/7; throughput times N.
MấtLose
Không ai duyệt quyền; lỗi âm thầm nhân N lần; trigger bị spam thì chi phí bùng nổ.No one approves; silent failures times N; spammed triggers explode cost.

Đổi sự giám sát của con người lấy thông lượng.Trades human oversight for throughput.

Nhận biết:Sign: có trigger rõ ràng và đầu ra kiểm chứng được.a clear trigger and a verifiable output.

Modules

năng lực cắm thêm vào lõicapabilities plugged into the core
M1

LLM providers

Module
loop ─► provider (internal fmt) ─┬─► Anthropic
                                 ├─► OpenAI
                                 └─► local

Lớp trừu tượng chuẩn hoá tin nhắn, tool call, streaming và lỗi giữa các nhà cung cấp.An abstraction normalising messages, tool calls, streaming and errors across vendors.

Dùng choUse for
Định tuyến sang model rẻ, dự phòng khi sập, so sánh trong eval.Routing to cheaper models, failover, eval comparisons.
ĐượcGain
Đổi model bằng một dòng config.Swap models with one config line.
MấtLose
Rơi về mẫu số chung, mất caching, thinking, citations.Lowest common denominator; lose caching, thinking, citations.

Đổi tính năng riêng của từng model lấy sự độc lập nhà cung cấp.Trades vendor-specific features for vendor independence.

Nhận biết:Sign: cần đổi model mà không đụng vào vòng lặp.you need to swap models without touching the loop.

M2

Memory

Module
new session ─► load CLAUDE.md / AGENTS.md
            ─► work ─► (optional) write lessons

Thông tin sống qua các phiên: quy ước dự án, lệnh build/test, bài học cũ.Information that survives sessions: project conventions, build/test commands, past lessons.

Dùng choUse for
Quy ước code, lệnh chính xác, lỗi từng gặp.Code conventions, exact commands, known pitfalls.
ĐượcGain
Không dạy lại mỗi phiên; chỉ vài trăm token.No re-teaching; a few hundred tokens.
MấtLose
Memory cũ được tin như chân lý; injection lọt vào thì sống mãi.Stale memory trusted as truth; injected text persists forever.

Đổi một phần context cố định mỗi lượt lấy việc không phải dạy lại.Trades a fixed slice of context each turn for never re-teaching.

Nhận biết:Sign: sang phiên thứ hai đã phải nhắc lại.you repeat yourself by session two.

M3

Skills

Module
context: [pdf: "read/write PDFs"] [release: …]
             │ relevant?
             ▼
        load skills/pdf/SKILL.md ─► follow

Thư mục hướng dẫn và script; chỉ mô tả nằm sẵn trong context, nội dung nạp khi cần.Folders of instructions and scripts; only the description sits in context, the body loads on demand.

Dùng choUse for
Quy trình nội bộ, định dạng file đặc thù, checklist review.Internal procedures, unusual file formats, review checklists.
ĐượcGain
Hàng chục skill gần như không tốn context.Dozens of skills at near-zero context cost.
MấtLose
Mô tả kém thì không bao giờ được nạp.A weak description means it never loads.

Đổi sự chắc chắn hướng dẫn được đọc lấy context gọn.Trades certainty of being read for a lean context.

Nhận biết:Sign: hướng dẫn dài nhưng chỉ cần cho một nhóm việc.long instructions needed for only one kind of task.

M4

Sandbox

Module
tools ─► [ own fs | net: allowlist | no secrets ]
                         ─► result

Môi trường cô lập để chạy lệnh và sửa file: container, microVM hoặc cloud (Modal là một lựa chọn).An isolated place to run commands and edit files: container, microVM or cloud (Modal is one option).

Dùng choUse for
Chạy code model viết, chạy song song, thao tác có thể phá máy.Running model-written code, parallel runs, risky operations.
ĐượcGain
Thiệt hại nằm trong hộp; mỗi phiên môi trường sạch.Damage stays in the box; clean env per session.
MấtLose
Khởi động lạnh, đồng bộ file và secret phức tạp, tốn compute.Cold starts, tricky file and secret sync, compute cost.

Đổi độ trễ và độ phức tạp hạ tầng lấy giới hạn thiệt hại khi model sai.Trades latency and infra complexity for contained damage.

Nhận biết:Sign: agent có tool bash.your agent has a bash tool.

M5

Permissions

Module
tool_call ─► policy ─┬─ allow ─► run
                     ├─ ask   ─► human / deny if headless
                     └─ deny  ─► reason back to model

Chính sách allow / ask / deny theo tool, đường dẫn, lệnh; khai báo trong config.An allow / ask / deny policy per tool, path and command, declared in config.

Dùng choUse for
git push, rm, migration, API tốn tiền.git push, rm, migrations, paid APIs.
ĐượcGain
Chặn trước khi xảy ra; có dấu vết audit.Blocks before it happens; audit trail.
MấtLose
Hỏi nhiều thì người bấm "đồng ý" theo phản xạ; khớp chuỗi dễ bị lách.Too many prompts train reflex "yes"; string matching is bypassable.

Đổi tốc độ và sự tự chủ của agent lấy an toàn.Trades agent speed and autonomy for safety.

Nhận biết:Sign: tool có tác dụng phụ không hoàn tác được.the tool has irreversible side effects.

M6

LSP server

Module
edit ─► file changed ─► LSP ─► errors
                               ─► into observation

Chạy language server để lấy lỗi, định nghĩa, tham chiếu như IDE.Runs a language server for errors, definitions and references, like an IDE.

Dùng choUse for
Đổi tên toàn codebase, bắt lỗi type ngay sau khi sửa.Codebase-wide renames, catching type errors after edits.
ĐượcGain
Phản hồi lỗi tức thì, chính xác hơn grep.Instant error feedback, sharper than grep.
MấtLose
Tốn RAM, mỗi ngôn ngữ một server, warning gây nhiễu.Memory-hungry, one server per language, noisy warnings.

Đổi một tiến trình vận hành thêm lấy phản hồi tức thì về độ đúng của code.Trades an extra process to run for instant correctness feedback.

Nhận biết:Sign: ngôn ngữ có type checker, codebase vài chục file trở lên.a typed language and a codebase of dozens of files or more.

Đo lườngMeasurement

nền móng cho mọi thay đổithe floor under every change
E1

Evals & observability

Đo lườngMeasurement
change ─► benchmark ─► vs baseline ─► better ─► merge
                                    └ worse ─► replay trace

Benchmarks để chấm, regressions để chạy lại sau mỗi thay đổi, replays để phát lại lần chạy lỗi; trace mọi lượt.Benchmarks to score, regressions to re-run after each change, replays to re-play failures; trace every turn.

Dùng choUse for
Trước khi đổi model, sau khi sửa prompt, điều tra job lỗi.Before model swaps, after prompt edits, investigating failed jobs.
ĐượcGain
Số thay cảm tính. Tác giả khoá học dẫn LangChain: chỉ đổi harness, Terminal-Bench từ khoảng 53% lên 67%.Numbers over gut feel. The course author cites LangChain: harness-only changes took Terminal-Bench from about 53% to 67%.
MấtLose
Bộ task tốt tốn công nhất; phải chạy nhiều lần vì không tất định.Good task sets are the costliest part; non-determinism needs repeat runs.

Đổi tốc độ ra tính năng lúc đầu lấy việc biết chắc mình đang tiến hay lùi.Trades early velocity for knowing whether you're moving forward or back.

Nhận biết:Sign: không trả lời được "thay đổi này tốt hơn hay tệ hơn".you can't say whether a change helped or hurt.

Bảng đánh đổiTrade-off table

Khái niệmConcept Cần từ ngày đầu?Day one? Công xâyBuild effort Thiếu thì hỏng gìRisk if missing Gánh vận hànhOps load
Agent loopCóYesThấpLowKhông có agentNo agentThấpLow
Context & compactionKhi phiên dàiOnce sessions growVừaMediumPhiên chết giữa chừngSessions die midwayThấpLow
Headless harnessCó, nếu sẽ chạy remoteYes, if going remoteVừaMediumViết lại khi lên cloudRewrite for cloudThấpLow
InteractiveTuỳDependsCaoHighNgười không lái đượcHumans can't steerVừaMedium
RemoteKhôngNoVừaMediumKhông mở rộng đượcNo scaleCaoHigh
LLM providersKhôngNoThấpLowKhoá chặt một nhà cung cấpVendor lock-inThấpLow
MemoryKhôngNoThấpLowDạy lại mỗi phiênRe-teachingThấpLow
SkillsKhôngNoThấpLowPrompt phình toBloated promptThấpLow
SandboxCó, nếu có bashYes, with bashVừaMediumPhá máy, lộ dữ liệuBroken host, leaked dataCaoHigh
PermissionsCóYesVừaMediumHành động không hoàn tácIrreversible actionsThấpLow
LSP serverKhôngNoVừaMediumPhát hiện lỗi chậmErrors caught lateVừaMedium
Evals & observabilityTrước thay đổi lớn đầu tiênBefore the first big changeCaoHighKhông biết tiến hay lùiBlind to progressVừaMedium

Anti-patterns

Sai lầmMistakeVì sao saiWhy it's wrongSửa thế nàoFix
Dựng agent cho quy trình cố địnhAn agent for a fixed processThêm chi phí và rủi ro, không được gìExtra cost and risk for nothingWorkflow bằng code, gọi LLM đúng bướcCode workflow, LLM at the right steps
Vòng lặp không giới hạn lượtLoop with no turn limitMột lần kẹt là đốt hết ngân sáchOne stuck run burns the budgetMax turns, ngân sách token, timeoutMax turns, token budget, timeout
Ném exception khi tool lỗiThrowing on tool errorsVòng lặp sập, model mất cơ hội tự sửaLoop crashes; no chance to recoverTrả lỗi dạng observationReturn errors as observations
Lõi dính chặt vào TUICore welded to the TUILên cloud phải viết lạiCloud means a rewriteLõi headless phát sự kiệnHeadless core emitting events
Chạy bash trên máy hostBash on the hostMột lệnh sai là mất dữ liệu hoặc lộ secretOne bad command loses data or secretsSandbox, chặn mạng, không secret thậtSandbox, blocked network, no real secrets
Permission khớp chuỗi lệnh shellPermissions by string matchBị lách bằng ; && subshellBypassed via ; && subshellsParse lệnh trước, deny mặc địnhParse first, deny by default
Compact khi đã chạm trầnCompacting at the ceilingKhông còn chỗ cho lời gọi tóm tắtNo room for the summary callCompact ở 70–80%Compact at 70–80%
Đổi prompt/model sau vài lần thử tayChanging prompt/model after a few manual triesKhông phân biệt được tiến bộ và may mắnCan't tell progress from luckBenchmark trước, chạy nhiều lầnBenchmark first, repeat runs
Job remote tự mergeRemote jobs auto-mergingLỗi âm thầm vào productionSilent errors reach productionĐầu ra là PR để người duyệtOutput a PR for review

Ba câu cần nhớThree things to remember

Model quyết định, harness thực thi; cải tiến harness thường rẻ hơn đổi model.The model decides, the harness executes; improving the harness is often cheaper than switching models.

Xây lõi headless trước; sandbox và permission có mặt từ ngày đầu.Build the headless core first; sandbox and permissions from day one.

Không có eval, mọi thay đổi chỉ là phỏng đoán.Without evals, every change is a guess.