Harness rốt cuộc là code gì? Tôi viết nó ở đâu? Tôi kiểm soát được phần nào? Và nếu dùng Claude/GPT làm model thì tôi có thể tự xây Harness đến đâu?
Bạn không sửa được “bộ não” của GPT, nhưng bạn có thể quyết định nó được làm gì
Giả sử bạn dùng:
- GPT của OpenAI
- Claude của Anthropic
- Gemini của Google
Bạn không thể vào bên trong model và sửa cách nó suy luận.
Nó giống như thuê một nhân viên cực kỳ thông minh từ bên ngoài.
Bạn không thể phẫu thuật não anh ta.
Nhưng bạn hoàn toàn có thể quyết định:
- đưa cho anh ta tài liệu gì;
- cho anh ta dùng máy tính nào;
- cho phép truy cập dữ liệu nào;
- cho phép gọi API nào;
- yêu cầu quy trình làm việc ra sao;
- khi nào phải hỏi người dùng;
- khi nào phải kiểm tra kết quả;
- khi nào phải dừng.
Đó chính là phần bạn có thể xây.
Và phần này chính là thứ người ta thường gọi là Harness.
1. Hãy bỏ từ “Harness” sang một bên
Nếu bạn là developer, tôi thậm chí khuyên bạn đừng bắt đầu bằng định nghĩa Harness.
Hãy bắt đầu bằng câu hỏi:
“Nếu tôi muốn biến một LLM thành một nhân viên AI, tôi phải viết thêm những code gì?”
Ví dụ bạn muốn xây một AI coding agent.
Bạn có model:
Claude / GPT
Nhưng model không tự:
đọc file
sửa file
chạy terminal
đọc error
sửa tiếp
Bạn phải xây lớp ở giữa.
Your application
│
▼
┌─────────────┐
│ Harness │ ← Bạn viết
└──────┬──────┘
│
▼
GPT/Claude ← Bên thứ 3
│
▼
Tool / Environment
Cái hộp Harness kia thực chất là code của bạn.
Đây là điểm quan trọng nhất.
2. Harness đơn giản nhất có thể chỉ là... một vòng while
Nghe có vẻ khó hiểu vì cái tên rất kêu.
Nhưng về bản chất, một Agent tối giản có thể trông gần như thế này:
while (!finished) {
const response = await callLLM(messages, tools);
if (response.toolCall) {
const result = await executeTool(response.toolCall);
messages.push(response);
messages.push(result);
continue;
}
finished = true;
}
Đây chính là một Agent Loop.
Model nói:
“Tôi cần đọc file
login.ts.”
Harness:
executeTool("read_file", "login.ts");
Kết quả quay lại model.
Model:
“Tôi tìm thấy bug. Tôi muốn sửa dòng 42.”
Harness:
executeTool("edit_file", ...);
Sau đó:
“Chạy test.”
Harness:
executeTool("run_test", ...);
Test fail.
Kết quả quay lại model.
Model suy nghĩ tiếp.
3. Đây chính là lúc “Harness” hết trừu tượng
Nếu bạn là frontend developer, hãy nhìn nó như một application bình thường.
Bạn có:
UI
↓
Agent Controller
↓
LLM API
↓
Tool Executor
↓
Environment
Bạn hoàn toàn có thể viết:
AgentController.ts
ContextManager.ts
ToolExecutor.ts
PermissionManager.ts
Memory.ts
Validator.ts
Không có gì thần bí cả.
Harness là tên gọi ở cấp độ kiến trúc cho những thứ này.
4. Bạn kiểm soát được gì?
Rất nhiều.
Thứ nhất: Prompt
Bạn có thể quyết định system prompt.
Ví dụ:
Bạn là coding agent.
Quy tắc:
1. Không tự ý xóa file.
2. Trước khi sửa code phải đọc file.
3. Sau khi sửa phải chạy test.
4. Nếu test fail, phân tích nguyên nhân.
5. Không commit code nếu chưa được phép.
Model vẫn là Claude/GPT.
Nhưng cách bạn hướng dẫn nó là của bạn.
5. Bạn kiểm soát Tools
Đây mới là phần cực kỳ quan trọng.
Bạn có thể nói:
“Model được phép làm những việc này.”
Ví dụ:
const tools = [
readFile,
searchCode,
editFile,
runTest
];
Bạn không cung cấp:
deleteDatabase()
sendEmail()
transferMoney()
thì model không có những khả năng đó.
Nó có thể nói:
“Tôi muốn gửi email.”
Nhưng Harness:
“Không có tool gửi email.”
Hết.
6. Và bạn còn kiểm soát cách Tool hoạt động
Ví dụ model gọi:
delete_file("important.txt")
Bạn có thể viết:
if (isImportantFile(file)) {
return requireUserConfirmation();
}
Hoặc:
if (path.includes(".env")) {
throw new Error("Access denied");
}
Hoặc giới hạn:
Agent chỉ được đọc:
/project/src
Không được truy cập:
/Users
/etc
/private
Đây là quyền hạn của Agent.
Và bạn kiểm soát nó.
7. Đây là điểm rất khác với Model
Bạn có thể hình dung:
| Thành phần | Bạn kiểm soát? |
|---|---|
| GPT/Claude model bên trong | ❌ Gần như không |
| System prompt | ✅ |
| Context | ✅ |
| Tools | ✅ |
| Tool permissions | ✅ |
| Agent loop | ✅ |
| Memory | ✅ |
| Retry | ✅ |
| Timeout | ✅ |
| Validation | ✅ |
| Logging | ✅ |
| Khi nào dừng | ✅ |
| Khi nào hỏi user | ✅ |
Vì vậy:
Model là thứ bạn thuê. Harness là thứ bạn xây.
8. Nhưng Harness không chỉ là Prompt
Đây là hiểu nhầm rất dễ xảy ra.
Ví dụ bạn viết:
Đừng bao giờ xóa database.
Đó mới chỉ là instruction.
Model vẫn có thể hiểu sai.
Một Harness tốt sẽ có thêm cơ chế kỹ thuật:
function executeTool(tool) {
if (tool.name === "delete_database") {
return askUserForConfirmation();
}
return tool.execute();
}
Lúc này:
Prompt nói “không được xóa”.
và:
Code cũng không cho phép xóa.
Đây là hai lớp bảo vệ khác nhau.
9. Bạn kiểm soát Agent Loop nhiều đến mức nào?
Rất nhiều.
Ví dụ Harness của bạn có thể quy định:
Agent được chạy tối đa 30 bước.
Nếu:
step > 30
→ dừng.
Bạn có thể đặt:
timeout = 5 minutes
Hoặc:
Nếu cùng một tool được gọi 5 lần liên tiếp
→ nghi ngờ agent đang loop
→ dừng
Hoặc:
Nếu test fail 3 lần
→ hỏi người dùng
Đây đều là logic của Harness.
10. Bạn kiểm soát Context
Đây cũng là một quyền rất lớn.
Giả sử project có:
100.000 file
Bạn không thể ném tất cả vào model.
Harness có thể:
User request
↓
Search relevant files
↓
20 files
↓
lọc
↓
5 files
↓
LLM
Bạn quyết định:
- đưa cái gì vào;
- lấy cái gì ra;
- tóm tắt cái gì;
- giữ lại cái gì.
Đây chính là Context Management.
11. Bạn kiểm soát Memory
Ví dụ Agent phát hiện:
Project sử dụng pnpm.
Harness có thể lưu:
{
"packageManager": "pnpm"
}
Lần sau Agent chạy:
pnpm test
thay vì:
npm test
Memory này không nằm bên trong GPT.
Nó nằm trong hệ thống của bạn.
Có thể là:
Redis
PostgreSQL
Vector Database
JSON
File
Tùy bạn thiết kế.
12. Bạn kiểm soát “khi nào Agent được phép suy nghĩ tiếp”
Đây là một phần rất thú vị.
Ví dụ:
LLM → Tool → Result
Bạn có thể quyết định:
Cách A
Luôn đưa kết quả về LLM.
Cách B
Nếu tool thành công → tiếp tục.
Nếu tool thất bại → retry.
Cách C
Nếu thao tác nguy hiểm → hỏi người dùng.
Cách D
Nếu test pass → kết thúc.
Ví dụ:
Tool result
│
┌────────┼────────┐
↓ ↓ ↓
PASS FAIL DANGER
│ │ │
↓ ↓ ↓
Done LLM Ask user
Đây chính là orchestration.
Và bạn kiểm soát nó.
13. Bạn còn kiểm soát “Definition of Done”
Đây là thứ rất quan trọng mà người dùng bình thường ít thấy.
Bạn có thể nói:
Agent chỉ được coi là hoàn thành khi:
✓ Code đã sửa
✓ Unit test pass
✓ Lint pass
✓ Build pass
✓ Không còn error
Nếu:
Code sửa xong
nhưng:
npm run build
→ FAIL
thì Harness không cho Agent kết thúc.
Nó bắt Agent quay lại.
sửa
↓
build
↓
FAIL
↓
sửa tiếp
↓
build
↓
PASS
↓
DONE
Đây là một trong những nơi Harness tạo ra khác biệt cực lớn.
14. Vậy Claude Code/Codex có Harness không?
Có.
Nhưng Harness cụ thể bên trong sản phẩm của họ là implementation của họ, và người dùng không nhất thiết nhìn thấy toàn bộ.
Bạn có thể coi:
Claude Code
không đơn giản chỉ là:
Claude API
mà là một hệ thống lớn hơn:
Claude Code
│
├── Agent loop
├── Context management
├── Tool execution
├── File system
├── Terminal
├── Permission
├── State
├── Error handling
├── Verification
└── Claude model
Claude là một phần.
Claude Code là sản phẩm bao quanh Claude.
15. Nhưng bạn cũng có thể tự xây một “Claude Code mini”
Đây mới là phần đáng quan tâm nếu bạn là developer.
Bạn không cần train model.
Bạn chỉ cần:
LLM API
+
Tool definitions
+
Agent loop
+
Permission
+
Context
+
Verification
Ví dụ:
MyCodingAgent/
│
├── agent.ts
├── llm.ts
├── tools/
│ ├── readFile.ts
│ ├── editFile.ts
│ ├── search.ts
│ └── terminal.ts
│
├── context/
│ └── manager.ts
│
├── permission/
│ └── manager.ts
│
└── validation/
└── testRunner.ts
Đó đã là một Harness tương đối rõ ràng rồi.
16. Và đây là lý do Harness có thể trở thành một nghề/kỹ năng riêng
Nếu bạn chỉ biết gọi:
openai.chat(...)
thì bạn mới đang sử dụng model.
Nếu bạn có thể thiết kế:
LLM
↓
Context
↓
Tool selection
↓
Execution
↓
Observation
↓
Retry
↓
Validation
↓
Memory
thì bạn đang làm Agent Engineering.
Và phần lớn công việc nằm xung quanh model, chứ không nhất thiết nằm trong model.
17. Một ví dụ rất thực tế với background Frontend
Giả sử bạn muốn xây:
AI Agent tự review Pull Request.
Bạn không cần train AI.
Bạn dùng Claude/GPT.
Harness của bạn có thể làm:
GitHub PR
↓
Harness
↓
Lấy diff
↓
Tìm các file liên quan
↓
Đưa code vào LLM
↓
LLM phân tích
↓
Nếu phát hiện vấn đề
↓
Harness kiểm tra lại
↓
Tạo comment GitHub
Bạn kiểm soát:
1. Model
Claude / GPT
→ bên thứ ba.
2. Context
PR diff
+
related files
+
coding conventions
→ bạn quyết định.
3. Tools
getPR()
getFile()
searchCode()
runTest()
createComment()
→ bạn viết.
4. Permission
Không được merge PR.
Chỉ được comment.
→ bạn viết.
5. Loop
Review
↓
Need more context?
↓ yes
Get file
↓
Review again
→ bạn viết.
6. Verification
Có chắc đây là bug?
→ chạy test / rule kiểm tra.
→ bạn viết.
Đấy chính là Harness.
18. Vì vậy, nếu bỏ chữ “Harness” đi...
Tôi nghĩ cách hiểu dễ nhất cho developer là:
Harness = toàn bộ phần code bạn xây để điều khiển một LLM khi biến nó thành một Agent.
Nó không nhất thiết là một package.
Không nhất thiết là một framework.
Không nhất thiết là một class.
Không nhất thiết có một file tên:
harness.ts
Thậm chí project của bạn có thể không bao giờ xuất hiện chữ Harness.
Nhưng nếu bạn có:
Agent Controller
Context Manager
Tool Executor
Permission Manager
Memory
Validator
State
thì về mặt kiến trúc, bạn đang xây Harness.
19. Và đây mới là điều đáng chú ý
Bạn nói:
“Model do bên thứ 3 cung cấp, tôi không thể can thiệp.”
Đúng.
Nhưng chính điều đó lại làm Harness trở nên thú vị.
Bạn không cần sở hữu bộ não.
Bạn có thể thuê:
GPT
Claude
Gemini
và cạnh tranh bằng cách bạn tổ chức bộ não đó.
Ví dụ:
Team A
Claude
+
Prompt đơn giản
+
3 tools
+
Không validation
Team B
Claude
+
Context tốt
+
20 tools
+
Permission
+
Memory
+
Retry
+
Test
+
Verification
Cả hai dùng cùng model.
Nhưng Agent của Team B có thể làm việc tốt hơn rất nhiều.
20. Nếu bạn muốn đi sâu vào AI từ góc độ lập trình viên
Đừng học Harness như một thuật ngữ riêng.
Hãy học theo thứ tự này:
① LLM API
↓
② Tool Calling
↓
③ Agent Loop
↓
④ Context Management
↓
⑤ State / Memory
↓
⑥ Permission / Sandbox
↓
⑦ Planning
↓
⑧ Verification
↓
⑨ Evaluation
↓
⑩ Multi-Agent
Đến khoảng ① → ⑦, bạn sẽ tự nhiên hiểu:
“À, hóa ra tất cả những thứ này ghép lại chính là Harness.”
Và lúc đó từ Harness sẽ không còn trừu tượng nữa.
Nó chỉ là tên gọi cho “cái hệ thống mà tôi, với tư cách developer, xây xung quanh LLM để biến nó thành một nhân viên AI có thể làm việc thực sự.”
All rights reserved