Harness Engineering for Coding Agents

01

Bối cảnh & Định nghĩa

Tại sao cần Harness? Agent thực sự là gì?

Vấn đề cần giải quyết

  • Coding agents được giao việc ngày càng tự chủ: viết code, sửa bug, refactor, mở PR, review chéo.
  • Model không hiểu hết ràng buộc kiến trúc, convention nội bộ, ưu tiên kinh doanh.
  • Chỉ dùng model mạnh hơn không đủ — code "nhìn đúng" nhưng vi phạm tinh thần hệ thống.
Làm sao giảm giám sát của con người mà vẫn tin được kết quả agent tạo ra?
Không có Harness: agent viết code "nhìn đúng" — qua review thủ công nhưng vi phạm kiến trúc, tích lũy tech debt.
Có Harness: agent tự phát hiện và sửa vấn đề trước khi tới reviewer — giảm toil, tăng chất lượng.

Agent = Model + Harness Fowler · Trivedy · Osmani

Ba vòng tròn đồng tâm: Model lõi → Builder harness → User harness

Ba lớp: Model lõi (LLM) → Builder harness (Anthropic/OpenAI) → User harness (đội bạn)

Agent = Model + Harness
  • Model — bộ não LLM (Claude, GPT…).
  • Builder harness — tool, sandbox, planner, memory do nhà cung cấp dựng sẵn.
  • User harness — tài liệu, rule, hook, linter, sensor riêng cho codebase của đội bạn.
Nguyên tắc: model trung bình + harness tốt > model tốt + harness tệ.
Harness Engineering = kỹ năng thiết kế User harness phù hợp hệ thống riêng.

"Skill Issue" & The Ratchet HumanLayer · Hashimoto

Reframe: mọi thất bại của agent là vấn đề cấu hình, không phải giới hạn model.

Agent làm saiGiải pháp harness
Không biết conventionBổ sung vào AGENTS.md
Chạy lệnh nguy hiểmThêm blocking hook
Lạc hướng task dàiTách planner / executor
Ship code lỗiNối typecheck back-pressure
Bằng chứng: cùng Claude Opus trên Terminal Bench 2.0 — harness khác nhau đẩy từ top 33 → top 5.

The Ratchet — Vòng siết một chiều

  • 1
    Agent mắc lỗi cụ thể.
  • 2
    Phân tích: harness gap hay model limit?
  • 3
    Cập nhật harness: rule, hook, linter, sensor mới.
  • 4
    Mỗi constraint trace được về một incident thực.
  • 5
    Chỉ siết chặt — không nới lỏng tuỳ tiện.
"Anytime an agent makes a mistake, engineer a solution so it never makes that mistake again." — Mitchell Hashimoto

02

Khung tư duy: Hai trục kiểm soát

Guides ↔ Sensors  ·  Computational ↔ Inferential

Guides (Feedforward) & Sensors (Feedback) Fowler

Guides feedforward vào agent, sensors feedback từ agent, con người steers cả hai

Con người (Steering Loop) liên tục cải thiện cả Guides lẫn Sensors theo thời gian

Feedforward — Guides (chỉ đường)
Định hướng agent trước khi hành động.
ADR, coding standards, AGENTS.md, how-to skills, ref docs, Language Server (LSP), MCP tools.
Feedback — Sensors (cảm biến)
Cho agent tự sửa sau khi hành động.
Lint, type check, test, architecture fitness, AI review — tín hiệu tối ưu cho LLM đọc.

Computational ↔ Inferential Fowler

Tiêu chíComputationalInferential
Bản chấtDeterministic, chạy trên CPUSuy luận ngữ nghĩa qua LLM / GPU
Ví dụUnit test, lint, type check, ArchUnit, dep-cruiserAI code review, LLM-as-judge, semantic diff
Tốc độ & chi phíms → s, gần như miễn phís → phút, tốn token
Độ tin cậyCao, ổn định, lặp lại đượcXác suất, có thể sai
Phạm vi đoCú pháp, cấu trúc, coverageÝ đồ, ngữ cảnh, ngữ nghĩa
Triết lý: ưu tiên Computational tối đa — chỉ dùng Inferential ở nơi Computational bất lực (ý đồ, naming, ngữ cảnh rộng).

03

Thành phần Harness

AGENTS.md · Tools & MCP · Sub-agents · Hooks & Lint

AGENTS.md là mục lục, docs/ là System of Record HumanLayer · OpenAI

Nguyên tắc viết AGENTS.md

Inject mỗi lượt vào system prompt — feedforward mạnh nhất, luôn có mặt.
  • Convention & naming rule.
  • Tool được / không được dùng.
  • Hành động cần phê duyệt (push, drop table…).
  • Cách viết test, tổ chức file theo layer.
~60–100 dòng, viết tay. Mỗi dòng phải "kiếm được vị trí" qua một failure thực — không thêm rule phòng ngừa chung chung.
ETH Zurich (138 agentfile): file LLM tự sinh tăng chi phí 20% mà không cải thiện kết quả. File người viết tay tăng hiệu quả ~4%.

Cấu trúc docs/ — System of Record

AGENTS.md          ← ~100 dòng, bản đồ
ARCHITECTURE.md    ← sơ đồ domain + layer
docs/
├── design-docs/   ← quyết định thiết kế
│   ├── index.md
│   └── core-beliefs.md
├── exec-plans/    ← kế hoạch đang chạy
│   ├── active/
│   └── tech-debt-tracker.md
├── product-specs/ ← spec tính năng
├── references/    ← llms.txt thư viện
├── DESIGN.md
├── QUALITY_SCORE.md
└── SECURITY.md
Linter + CI xác thực cơ học doc luôn fresh, cross-link đúng. Agent "doc-gardening" định kỳ quét doc cũ, tự mở PR sửa.

Tools & MCP — Ít nhưng chất HumanLayer

Quá nhiều tool MCP làm đầy context với descriptions

Tool overload: mỗi MCP tool description chiếm context — agent vào "dumb zone" sớm hơn

10 tool thiết kế tốt > 50 tool chồng chéo.
Tool description = prompt thật — MCP độc hại có thể prompt-inject trước khi agent bắt đầu.
Khi nào KHÔNG dùng MCP: nếu model đã biết CLI (Git, Docker, DB) → gọi thẳng, không cần wrapper.
Progressive tool disclosure: expose tool chỉ khi query khớp — giữ context window sạch.
⚠ Kho skill công khai đã phát tán mã độc. Treat như npm install random-package — review trước khi cài.

Sub-agents — Context Firewall HumanLayer

Sub-agent tạo context isolation

Sub-agent = context firewall — noise của subtask không tích lũy vào parent session

  • Session độc lập cho từng subtask rời rạc.
  • Ngăn intermediate noise làm ô nhiễm parent context.
  • Chroma research: model kém chính xác hơn ở context dài — sub-agent tốt hơn cửa sổ to.
Tối ưu chi phí: Opus cho orchestration, Haiku / Sonnet cho sub-task.
Use case: tìm code definition, trace data flow qua nhiều service, phân tích pattern toàn repo — task nhiều tool call trung gian.
Lưu ý: không nest sub-agent quá sâu — "telephone effect" làm méo ngữ cảnh.

Hooks & Custom Lint — Back-pressure cho LLM HumanLayer · OpenAI

Hook chạy tự động tại lifecycle event — tương tự git hook nhưng linh hoạt.

EventHook
Sau mỗi edit fileTypecheck, lint, format
Trước commitTest, coverage, dep-cruiser
Trước push / PRHuman approval required
Lệnh nguy hiểmBlock rm -rf, DROP TABLE
Back-pressure principle: verification phải context-efficientthành công im lặng, chỉ lỗi mới verbose. Full test mỗi lượt → flood context → agent hallucinate.

Lint message viết cho LLM

Custom linter (do coding agent sinh) thực thi cơ học các bất biến: structured logging, naming, file size limit, layer dependency.
Error message nêu vi phạm + cách sửa cụ thể ngay trong output → đẩy thẳng hướng dẫn khắc phục vào context agent.
# Hook chạy sau mỗi edit
biome format --write . 2>/dev/null
tsc --noEmit 2>&1 \
  | grep -E "error" && exit 1 || exit 0

04

Ba chiều kiểm soát chất lượng

Maintainability · Architecture Fitness · Behaviour

Ba chiều kiểm soát Fowler

Ma trận Guides/Sensors × Maintainability/Architecture Fitness/Behaviour

Trục ngang: Guides ↔ Sensors  ·  Trục dọc: 3 chiều kiểm soát

1 Maintainability
Rõ ràng, ít trùng lặp, dễ sửa. Linter, type checker, SonarQube, jscpd, AI review naming/dead code. Computational mạnh nhất.
2 Architecture Fitness
Layer, dependency, NFR. ADR, C4, ArchUnit / Konsist / dep-cruiser, contract test, OpenAPI lint. Sân nhà của SA.
3 Behaviour
Code làm đúng nghiệp vụ. BDD, acceptance criteria, property-based, mutation test. Nhóm yếu nhất — vẫn cần test thủ công.

Kiến trúc phân lớp cứng — Prerequisite, không phải afterthought OpenAI

Layered domain architecture với cross-cutting concerns qua Providers

Mỗi domain: Types → Config → Repo → Providers → Service → Runtime → UI. Cross-cutting chỉ qua Providers

Dependency một chiều — cấm import ngược; enforce bằng custom linter & structural test.
Với agent, kiến trúc cứng là điều kiện tiên quyết — thứ cho phép tốc độ mà không bị architectural drift.
Thông thường ta trì hoãn điều này đến khi có hàng trăm kỹ sư. Với agent — đó là prerequisite ngay từ đầu.
Enforce qua: custom linter (agent sinh), structural test, "preference invariants" — structured logging, naming, file size limit.

05

Quản lý Context dài

Context Rot · Compaction · Long-horizon execution

Context Rot & Compaction HumanLayer

Triệu chứng: agent lạc hướng, lặp lại lỗi đã sửa, hallucinate ở cuối session dài.

Ba kỹ thuật chống Context Rot

1. Compaction — tóm tắt thông minh context cũ, offload phần thừa ra filesystem.
2. Tool-call offloading — chỉ giữ head/tail output lớn; lưu full ra file, đọc lại khi cần.
3. Context reset — teardown session, rebuild từ hand-off file gọn — gần giống onboard người mới.
Sub-agent response compaction với source citation

Compaction: sub-agent trả bản tóm tắt kèm source citation — parent context nhận thông tin đã chắt lọc

Long-horizon Execution Osmani · HumanLayer

Mỗi hành vi mong muốn → component harness tương ứng

Mỗi gap hành vi của model → thiết kế component harness tương ứng

Ralph Loops: hook chặn lúc agent định kết thúc, re-inject prompt gốc vào context mới. Single-session → multi-session.
Planning: model phân rã goal → plan file → tick từng bước → self-verify qua hook.
Sprint Contract: Generator và Evaluator thoả thuận định nghĩa "done" trước khi viết code — tránh self-evaluation thiên vị tích cực.

06

Vòng đời & Vận hành ở quy mô

Keep Quality Left · Observability · Merge gate · Entropy · Templates

Keep Quality Left — Vòng đời thay đổi Fowler

Feedforward → tự sửa lần 1 → human review → integration → pipeline

Feedforward → Tự sửa lần 1 → Human review → Integration → Post-integration pipeline

  • Trước commit: LSP, AGENTS.md, /how-to-test skill → agent generate.
  • Tự sửa lần 1: eslint, semgrep, dep-cruiser, /code-review (nhanh, rẻ).
  • Human review = một feedback sensor nữa trong pipeline.
  • Post-integration: /architecture-review, mutation test (đắt → chạy sau merge).

Làm app "đọc được" với agent OpenAI

Git worktree isolation: mỗi thay đổi = một app instance riêng, agent tự khởi chạy.
Chrome DevTools MCP: DOM snapshot, screenshot, navigation, event observation, UI validation.
Local observability stack tạm thời: Vector → Victoria Logs / Metrics / Traces → query bằng LogQL / PromQL / TraceQL. Teardown sau khi task xong.
Kết quả: prompt như "không span nào trong 4 critical user journey vượt 2 giây" trở thành verifiable.
App → Vector → Victoria stack → agent query & reason → fix → restart → iterate

App → Vector → stack quan sát → agent query & suy luận → fix → restart → lặp lại

Merge gate tối giản + Post-merge sensors OpenAI · Fowler

Triết lý merge

PR vòng đời ngắn. Flaky test → chạy lại, không block vô thời hạn.
Sửa lỗi rẻ. Chờ đợi đắt. Trong hệ thống throughput agent cao, đây là trade-off đúng.
Điều này sẽ vô trách nhiệm trong throughput thấp — nhưng đặc trưng agent-first workflow là safety net = post-merge sensors.

Ví dụ post-merge sensors

  • Architecture fitness: linter kiểm tra layer dependency trên main sau mỗi merge.
  • Full regression: integration + e2e quá chậm cho PR → chạy mỗi đêm trên main.
  • Entropy detector: background agent tìm drift khỏi golden principles.
  • Drift detection: /find-dead-code, /code-coverage-quality, Dependabot.
  • Runtime signals: latency SLO, error rate, /log-anomalies → gợi ý tự động.
Dịch chuyển từ "ngăn lỗi vào""phát hiện & fix liên tục sau khi vào".

Entropy & Golden Principles OpenAI

Vấn đề

Coding agent copy pattern đã có trong repo — kể cả pattern xấu. Theo thời gian → architectural drift.

Trước đây: 20% thời gian / tuần (mỗi thứ Sáu) dọn "AI garbage" — không scale.

Giải pháp

Golden principles encode trực tiếp vào repo — quy tắc có quan điểm, cơ học, giúp codebase nhất quán.
Background agent chạy định kỳ: quét sai lệch, cập nhật quality score, mở targeted refactoring PR. Hầu hết review xong < 1 phút.

Ví dụ Golden Principles

1. Ưu tiên shared utility package hơn custom helper — giữ bất biến tập trung.
2. Không probe data kiểu "YOLO" — validate tại boundary hoặc dùng typed SDK để agent không build dựa trên cấu trúc đoán mò.
Gu thẩm mỹ của con người được ghi nhận một lần, thực thi liên tục trên từng dòng code — pattern xấu được bắt ngay ngày hôm đó.
"Tech debt giống khoản vay lãi suất cao: trả dần từng phần nhỏ tốt hơn để tích lũy."

Harness Templates theo Topology Fowler

Vì sao cần Harnessability?

  • Không phải codebase nào cũng áp dụng harness hiệu quả.
  • Code legible, navigable, tractable thì harness mới phát huy.
  • Giải pháp: harness template theo topology (loại service).
Data Dashboard
Node.js
CRUD Service
JVM
Event Processor
Golang
Lợi ích: tăng tốc bootstrap service mới — mỗi topology có sẵn 1 bộ guides + sensors đã chuẩn hoá.
Stack các topology với harness template tương ứng

Mỗi topology → 1 bộ guides + sensors sẵn có

Kết luận: trước khi hỏi "harness nên có gì", phải hỏi "codebase của tôi có đáng được harness không". Nếu chưa — refactor cho legible / navigable / tractable trước, rồi dùng template theo topology để khỏi viết lại từ đầu.

07

Tư duy nâng cao

Boring Tech · Co-evolution · Harness-as-a-Service

Boring Tech — Ưu tiên công nghệ "nhàm chán" OpenAI

Dùng công nghệ API ổn định, phổ biến trong training data → agent build mental model đúng, không hallucinate tên method hay option không tồn tại.

Bài toán: chạy 100 API call, tối đa 5 cái cùng lúc.

✗ p-limit (thư viện ngoài)
import pLimit from 'p-limit';
const limit = pLimit(5);
await Promise.all(
  items.map(i => limit(() => callApi(i)))
);
v3→v4→v5 đổi API, ESM-only từ v4
→ agent nhớ API cũ, sinh code fail CI
✓ mapWithConcurrency (built-in)
async function mapWithConcurrency(
    items, fn, limit) {
  const running = new Set();
  for (const item of items) {
    const p = fn(item).then(
      () => running.delete(p));
    running.add(p);
    if (running.size >= limit)
      await Promise.race(running);
  }
  await Promise.all(running);
}
Chỉ dùng Promise — API không đổi bao giờ
→ dễ thêm OTel span, test coverage 100%

Model–Harness Co-evolution Osmani

Vòng lặp training: primitive hữu ích trong harness → chuẩn hoá thành sản phẩm → dùng train model tiếp theo → model mới giỏi dùng primitive đó → lặp lại

Harness và model co-evolve: primitive trong harness hôm nay → capability của model ngày mai

Harness không co lại — chúng dịch chuyển.
Model tốt hơn làm mất hiệu lực scaffolding cũ (dead code), đồng thời tạo thách thức mới.
Ví dụ: Opus 4.6 loại bỏ gần hết context-anxiety. Scaffolding cũ → dead code. Thách thức mới: multi-day memory, multi-agent coordination, design-quality evaluator.
Nguyên tắc: mỗi component mã hoá một assumption về điều model chưa tự làm được. Khi capability cải thiện, xoá component đó đi.

Harness-as-a-Service (HaaS) Osmani

Dịch chuyển nền tảng: từ build trên LLM API trần → build trên harness runtime đã đóng gói sẵn 4 trụ cột.
Các runtime hiện có: Claude Agent SDK · Codex SDK · OpenAI Agents SDK — kế thừa context policy, tool layer, hook system, sandbox.
Con đường áp dụng:
  1. Chọn framework phù hợp use case & stack.
  2. Cấu hình 4 trụ cột: context · control · action · observation.
  3. Tối ưu prompt & tool theo domain — không build lại runtime từ đầu.
Trade-off: mất một phần khả năng tuỳ biến tận đáy, đổi lại tốc độ ra sản phẩm và đứng trên harness đã được vận hành ở quy mô lớn.
Kiến trúc Claude Code 7 layer

Claude Code — harness production 7 layer (tham chiếu kiến trúc HaaS)

Take-aways thống nhất cho team

  1. Coi Harness là sản phẩm — có owner, roadmap, metric riêng. Reframe failures: agent sai → tìm harness gap, không phải đổi model.
  2. AGENTS.md ~100 dòng, là mục lục; docs/ là System of Record — mọi tri thức encode thành markdown có phiên bản.
  3. Hooks & custom lint = back-pressure cho LLM: thành công im lặng, lỗi mới verbose, error message viết cho LLM đọc.
  4. Sub-agent cho subtask dài — bảo vệ parent context khỏi noise (context firewall).
  1. Kiến trúc cứng là prerequisite — không trì hoãn; enforce bằng custom linter & structural test từ ngày đầu.
  2. Ưu tiên Computational, dùng Inferential khi cần; bắt đầu từ Maintainability + Architecture Fitness (ROI cao nhất).
  3. Merge gate tối giản + Post-merge sensors + Golden Principles + background garbage collection → ngăn entropy ở quy mô agent.
  4. Harness là living system: siết theo Ratchet, xoá scaffolding khi model giỏi lên — dead-code harness cũng là tech debt.
"The gap between what models can do and what you see them doing is largely a harness gap." — Addy Osmani  ·  "Xây phần mềm vẫn đòi hỏi kỷ luật — nhưng kỷ luật xuất hiện nhiều hơn trong scaffolding hơn là trong code." — Ryan Lopopolo