Chuyển đến nội dung chính
Trí tuệ Nhân tạo
Mô hình Ngôn ngữ Lớn
AI Agents

Hướng dẫn Kỹ thuật Harness cho Agent: Thu hẹp khoảng cách giữa Mô hình và Hành động

Tìm hiểu cách xây dựng harness cho AI agent tùy chỉnh với Python, vòng lặp ReAct và trạng thái bền vững.
Tim Lu's photo
Tim Lu
Đã cập nhật

Khám phá cùng AI

ChatGPTClaudePerplexity

Tạo tài khoản miễn phí của bạn

Luyện tập và Lộ trình tiến trình của bạn.

Tiếp Tục Với Google
Bằng cách tiếp tục, bạn chấp nhận Điều khoản sử dụng, Chính sách bảo mật và việc dữ liệu của bạn được lưu trữ tại Hoa Kỳ.

Hãy tưởng tượng chạy đúng cùng một mô hình ngôn ngữ lớn (LLM) hai lần, nhưng mỗi lần lại dùng hai harness hoàn toàn khác nhau. Lần chạy thứ nhất hoàn thành gọn gàng một tác vụ tái cấu trúc phức tạp. Lần thứ hai dừng lại và thất bại hoàn toàn. Mô hình không thay đổi, nhưng phần giàn dựng bao quanh mô hình thì có.

Tóm lại, kỹ thuật harness cho agent là thực hành xây dựng logic bao quanh, truy cập hệ thống tệp, bộ nhớ và các quy tắc giúp một LLM hành động đáng tin cậy. 

Trong hướng dẫn kỹ thuật harness cho agent này, tôi sẽ chỉ bạn cách dựng một thiết lập Python tối thiểu với vòng lặp Reason and Act (ReAct), công cụ và hook. Bạn cần Python 3, pip đã cài trên máy, và quen thuộc cơ bản với việc thực hiện gọi API LLM.

Agent Harness Engineering là gì?

Agent harness engineering là thực hành xây dựng hạ tầng, cấu hình và logic thực thi bao bọc quanh một mô hình ngôn ngữ lớn, biến nó từ một trình tạo văn bản LLM tĩnh thành một AI agent tự chủ

Agent harness engineering là cấu hình kiến trúc biến một trình tạo văn bản tĩnh thành một “người làm việc” tự chủ. 

Phương trình cốt lõi rất đơn giản: agent = model + harness. Harness bao gồm lời nhắc hệ thống, định nghĩa công cụ, không gian làm việc hệ thống tệp, logic điều phối và các hook quan sát.

Addy Osmani chuẩn hóa khái niệm này trong bài viết tháng 4/2026 trên O'Reilly về quy trình AI. Anh định nghĩa harness là mọi đoạn mã, cấu hình và logic thực thi không phải bản thân mô hình: bề mặt làm việc của bạn với tư cách là nhà phát triển, tách biệt với API của nhà cung cấp. 

Khi mới xây dựng quy trình machine learning, tôi đổ lỗi cho mô hình mỗi khi agent bịa đặt một phụ thuộc Python. Tôi học được qua thực tế rằng phần lớn lỗi là do cấu hình. 

Cùng một phiên bản mô hình với một harness tốt sẽ vượt trội rõ rệt so với chính nó khi dùng một harness tệ.

Bậc thang kỹ thuật AI

Chúng ta có thể chia phát triển AI thành các lớp kiểm soát riêng biệt. 

Kỹ thuật harness nằm chính giữa hệ phân cấp này.

Lớp

Kiểm soát điều gì

Hành động ví dụ

Kỹ thuật nhắc (prompt)

Văn bản tức thời

Tinh chỉnh hướng dẫn

Kỹ thuật ngữ cảnh

Dữ liệu nạp vào mô hình

Tối ưu pipeline RAG

Kỹ thuật harness

Công cụ vật lý của agent

Thêm công cụ Bash

Kỹ thuật vòng lặp

Các bước điều phối

Thay đổi luồng ReAct

Kỹ thuật đồ thị

Phối hợp đa agent

Xây nút định tuyến

  • Kỹ thuật nhắc (prompt) quyết định các hướng dẫn văn bản tức thời.
  •  Kỹ thuật ngữ cảnh quản lý chính xác các bản ghi cơ sở dữ liệu hoặc schema API bạn đưa vào lời nhắc. 
  • Kỹ thuật harness quyết định cách agent thật sự thực thi một script pandas hoặc đọc một CSV cục bộ. 

Bánh cóc: mọi sai lầm đều thành quy tắc

Tư duy định hình kỹ thuật harness cho agent là hiệu ứng bánh cóc. 

Khi agent mắc lỗi, bạn thiết kế một cách khắc phục để nó không bao giờ lặp lại lỗi đó. Một harness tốt là sự nén của quá trình thử-sai.

Thay vì để agent lặp lại sai lầm, bạn thêm một dòng vào AGENTS.md, viết một hook mới, hoặc siết chặt mô tả công cụ. 

Bạn không chỉ theo bản năng chuyển sang mô hình mới; thay vào đó, bạn xây dựng một kho tư liệu cho phép truy vết các lỗi cụ thể và cách bạn đã gia cố chống lại chúng.

Thành phần cốt lõi của một AI Agent Harness

Các thành phần cốt lõi của một AI agent harness là hệ thống tệp, công cụ, bộ nhớ, hook và các hệ thống quản lý ngữ cảnh cho phép mô hình hoạt động. 

Những phần này phối hợp để biến các cuộc gọi API rời rạc thành một vòng phản hồi liên tục. Tôi muốn đưa bạn một sơ đồ rõ ràng trước khi bắt đầu viết mã.

Thành phần

Nhiệm vụ

Triển khai Python

Hệ thống tệp

Trạng thái bền vững

Thư mục workspace/ cục bộ

Công cụ

Hành động trong môi trường

Hàm Python cho Bash

Bộ nhớ

Ngữ cảnh dự án

Một tệp AGENTS.md

Hook

Cưỡng chế/kiểm soát

Script kiểm tra trước khi commit

Nén

Quản lý ngữ cảnh

Logic tóm tắt

Hệ thống tệp và Git: trạng thái bền vững

Một mô hình chỉ có thể xử lý thông tin trong cửa sổ ngữ cảnh hạn chế của nó. Hệ thống tệp cung cấp một không gian làm việc ổn định để đọc dữ liệu, ghi kết quả trung gian và phối hợp qua nhiều phiên.

Thêm kiểm soát phiên bản Git cung cấp lưới an toàn cần thiết. Agent có thể theo dõi tiến độ, tạo nhánh để thử nghiệm với các siêu tham số khác nhau và tự động quay lui mã hỏng. 

Công cụ: trao “đôi tay” cho agent

Vòng lặp ReAct vận hành theo chu kỳ suy luận, hành động qua một lần gọi công cụ và quan sát kết quả. Mô tả công cụ tạo thành giao diện trực tiếp giữa mô hình và môi trường. Mô tả mơ hồ sẽ tạo ra hành vi mơ hồ.

Bash là một công cụ đa dụng tuyệt vời. Thay vì xây sẵn một hàm Python cụ thể cho mọi hành động có thể có, Bash cho phép agent dựng đúng lệnh nó cần ngay tức thì. Bạn phải cô lập các lệnh này cẩn thận để tránh gây hại hệ thống.

Bộ nhớ: AGENTS.md và bơm nạp tri thức

Agent của bạn cần bộ nhớ theo dự án để hiểu các quy ước cục bộ. Một tệp AGENTS.md là tài liệu markdown phẳng ở thư mục gốc repo, được đưa vào lời nhắc hệ thống ở mỗi lượt. Nó định nghĩa tech stack, quy tắc định dạng và các hành động bị cấm.

Giữ tệp này dưới 60 dòng. Hãy coi nó như checklist của phi công thay vì hướng dẫn phong cách toàn diện. Bạn có thể đọc hướng dẫn AGENTS.md đầy đủ để có ví dụ sâu hơn. Bạn cũng nên cân nhắc công cụ Model Context Protocol (MCP) cho tri thức sau mốc cắt.

Hook: lớp cưỡng chế

Hook là các script nhỏ chạy tại những thời điểm vòng đời cụ thể. 

Bạn có thể chạy hook trước khi gọi công cụ, sau khi chỉnh sửa tệp hoặc trước khi commit Git. Xem hướng dẫn về Claude Code Hooks để biết các mẫu hook nâng cao.

Nguyên tắc thiết kế chính cho hook là: thành công thì im lặng, thất bại thì chi tiết. Một lần kiểm tra kiểu pass sẽ không tạo ra đầu ra nào. 

Một lỗi sẽ bơm chính xác văn bản lỗi vào lại vòng lặp agent để tự sửa.

Nén ngữ cảnh: chống mục nát ngữ cảnh

Mục nát ngữ cảnh xảy ra khi khả năng làm theo hướng dẫn suy giảm do cửa sổ ngữ cảnh bị lấp đầy bởi lịch sử hội thoại dài. Một giàn dựng AI agent vững chắc phải chủ động quản lý điều này. Đọc thêm về cửa sổ ngữ cảnh để hiểu các giới hạn.

Bạn có thể giảm ngữ cảnh bằng cách tóm tắt các tin nhắn cũ. Bạn có thể đẩy các đầu ra công cụ lớn xuống đĩa và chỉ giữ tham chiếu ngắn trong lời nhắc. 

Cuối cùng, bạn có thể cô lập các tiểu tác vụ ngốn token vào một subagent với ngữ cảnh mới.

Xây dựng một Agent Harness tối thiểu bằng Python

Xây dựng AI agent harness bao gồm viết mã điều phối Python kết nối vòng lặp ReAct, công cụ và hook lại với nhau. 

Hãy rõ ràng về mối quan hệ trước khi viết mã: harness.py chính là agent, và bạn tự khởi chạy nó bằng python harness.py như bất kỳ script nào khác. 

Mô hình là một API từ xa không bao giờ “nhìn thấy” tệp này; nó chỉ nhận lời nhắc hệ thống, lịch sử tin nhắn và schema công cụ mà script của bạn gửi đến.

Mỗi đoạn mã trong phần này là một phần của một tệp, harness.py, và 4 phần đầu sẽ xây nó từ trên xuống dưới. 2 phần cuối (hook và nén) nâng cấp nó, và vì vòng lặp thực thi ngay khi Python chạm tới, định nghĩa hàm của chúng phải nằm phía trên vòng lặp; mỗi phần sẽ chỉ rõ chính xác vị trí mã của nó.

Thiết lập tài khoản và cấu trúc dự án

Để xây dựng, bạn cần một tài khoản nhà phát triển với nhà cung cấp bạn chọn. Các gói người dùng phổ thông (như ChatGPT Plus hoặc Claude Pro) không cấp quyền truy cập API.

  1. Thiết lập Anthropic/OpenAI: Đăng ký tại bảng điều khiển nhà phát triển của nhà cung cấp và thiết lập hồ sơ thanh toán trả theo mức dùng. Tạo khóa API và xuất nó vào môi trường cục bộ dưới tên ANTHROPIC_API_KEY (hoặc OPENAI_API_KEY).
  2. Phương án cục bộ: Nếu bạn muốn tránh hoàn toàn chi phí API, bạn có thể chạy Ollama cục bộ. Ollama cung cấp một endpoint cục bộ mà bạn có thể truy vấn không cần khóa API.

Trong ví dụ này, chúng ta sẽ dùng Anthropic, vì vậy hãy cài gói Anthropic Python bằng pip install anthropic.  

Tiếp theo, tạo khung dự án. Đặt tên mọi tệp ngay từ đầu là quan trọng: vòng lặp của chúng ta sẽ đọc AGENTS.md khi khởi động, nên tệp đó phải tồn tại trước khi vòng lặp chạy.

agent-harness/
├── AGENTS.md        # Project memory (we write this first)
├── harness.py       # The ReAct loop, tools, and hooks
└── workspace/       # The only directory the agent may touch

Thư mục workspace/ là sandbox của agent. Mọi thứ agent đọc, ghi hoặc thực thi đều diễn ra bên trong nó, không bao giờ ở thư mục gốc dự án của bạn.

Viết AGENTS.md và bơm nó vào lời nhắc hệ thống

Chúng ta viết AGENTS.md trước vòng lặp vì vòng lặp phụ thuộc vào nó. 

Tạo tệp ở thư mục gốc dự án và thêm chi tiết stack cụ thể cùng ranh giới kiến trúc của bạn:

# Project Context
Stack: Python 3.11, Pytest
Workspace: All commands run inside the workspace/ directory.

# Rules
1. Never use rm -rf. Use standard rm with specific file names.
2. Never write tests inside the main application file.
3. When you finish the task, reply with a plain-text summary and no tool call.

Vòng lặp của chúng ta sẽ coi "mô hình phản hồi mà không yêu cầu công cụ" là tín hiệu hoàn thành tác vụ, nên chúng ta nói rõ cho mô hình cách báo hiệu hoàn tất. 

Các quy tắc tham chiếu cơ chế vòng lặp riêng của bạn chính là chìa khóa cho kỹ thuật harness. Tệp bộ nhớ và mã điều phối được thiết kế cùng nhau.

Giờ hãy bắt đầu harness.py bằng cách tạo tệp này làm lời nhắc hệ thống và chuẩn bị workspace:

import subprocess
from pathlib import Path

import anthropic

client = anthropic.Anthropic()

WORKSPACE = Path("workspace")
WORKSPACE.mkdir(exist_ok=True)

# Project memory: AGENTS.md lands in the system prompt on every turn
system_prompt = Path("AGENTS.md").read_text()

Bởi vì SDK gửi system_prompt trong mọi cuộc gọi API, các quy tắc trong AGENTS.md được bơm lại ở mỗi lượt. Mô hình không thể “quên” chúng như cách nó quên hướng dẫn giữa hội thoại.

Định nghĩa công cụ: trao “đôi tay” cho vòng lặp

Chúng ta định nghĩa 2 công cụ: run_bash để thực thi đa dụng và write_file để tạo tệp. 

Công cụ thứ hai có vẻ thừa vì Bash có thể ghi tệp bằng heredoc, nhưng một write_file chuyên biệt cho chúng ta một sự kiện chỉnh sửa sạch để hook hậu chỉnh sửa có thể bám vào sau này. 

Những quyết định thiết kế harness như thế này luôn xoay quanh những gì bạn muốn quan sát và cưỡng chế.

Mô tả công cụ là giao diện, và chất lượng của chúng trực tiếp điều khiển hành vi của agent:

  • Mơ hồ: "Chạy bash." Agent sẽ dùng cho mọi thứ, bao gồm ghi các tệp Python nhiều dòng qua heredoc mong manh với escape lỗi.
  • Cụ thể: "Chạy lệnh bash bên trong workspace/. Dùng để liệt kê tệp, chạy script và chạy test. Không dùng để tạo tệp Python; thay vào đó dùng write_file." Agent sẽ phân luồng công việc đến đúng công cụ mà không cần nhắc thêm.

Tiếp tục trong tệp harness.py, giờ ta có thể định nghĩa schema công cụ ở dòng tiếp theo:

TOOLS = [
    {
        "name": "run_bash",
        "description": (
            "Run a bash command inside the workspace/ directory and return "
            "its stdout, stderr, and exit code. Use it to list files, run "
            "scripts, and run tests. Do not use it to create Python files; "
            "use write_file instead."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "command": {"type": "string", "description": "The bash command to run."}
            },
            "required": ["command"],
        },
    },
    {
        "name": "write_file",
        "description": (
            "Create or overwrite a file inside the workspace/ directory. "
            "Provide a path relative to workspace/ and the full file content."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "Path relative to workspace/."},
                "content": {"type": "string", "description": "Full file content."},
            },
            "required": ["path", "content"],
        },
    },
]

Khối tiếp theo định nghĩa các hàm Python thực sự sẽ thực thi các lệnh này. 

Lưu ý các tính năng an toàn đã được xây dựng: timeout cứng để lệnh bị kẹt không làm treo harness, mã thoát được đưa vào mọi kết quả để agent phân biệt thành công/thất bại, và kiểm tra đường dẫn để write_file() không thoát khỏi sandbox.

def run_bash(command: str) -> str:
    result = subprocess.run(
        command,
        shell=True,
        capture_output=True,
        text=True,
        cwd=WORKSPACE,
        timeout=60,
    )
    output = (result.stdout + result.stderr).strip()
    return f"exit code: {result.returncode}\n{output or '(no output)'}"


def write_file(path: str, content: str) -> str:
    target = (WORKSPACE / path).resolve()
    if WORKSPACE.resolve() not in target.parents:
        return "Error: path escapes the workspace/ directory."
    target.parent.mkdir(parents=True, exist_ok=True)
    target.write_text(content)
    return f"Wrote {len(content)} characters to {path}."


TOOL_EXECUTORS = {"run_bash": run_bash, "write_file": write_file}

Phần dự phòng or '(no output)' không phải để làm đẹp. 

Một lệnh như touch data.csv thành công trong im lặng, và trả về chuỗi rỗng sẽ không cho mô hình quan sát gì. 

Luôn cho agent một tín hiệu rõ ràng, ngay cả khi là sự im lặng.

Vòng lặp agent ReAct

Cốt lõi của harness của chúng ta là một vòng lặp for Python tiêu chuẩn với giới hạn số vòng lặp. 

Mỗi lượt gọi API, kiểm tra mô hình có yêu cầu công cụ không, thực thi mọi công cụ được yêu cầu, và đưa kết quả về như một tin nhắn duy nhất. 

Khối này nằm ở cuối harness.py, vì nó bắt đầu chạy ngay khi Python chạm tới.

	messages = [
	    {
	        "role": "user",
	        "content": "Create a fizzbuzz.py script in the workspace, "
	                   "then run it to verify the output.",
	    }
	]

	MAX_STEPS = 15

	for step in range(MAX_STEPS):
	    print(f"--- Iteration {step + 1} ---")

	    response = client.messages.create(
	        model="claude-sonnet-5",
	        max_tokens=2000,
	        system=system_prompt,
	        messages=messages,
	        tools=TOOLS,
	    )

	    # Append the model's turn to the history
	    messages.append({"role": "assistant", "content": response.content})

	    # Stop condition: the model answered without requesting a tool
	    if response.stop_reason != "tool_use":
	        final_text = "".join(b.text for b in response.content if b.type == "text")
	        print(f"Task complete: {final_text}")
	        break

	    # Execute EVERY tool call in this turn, collecting the results
	    tool_results = []
	    for block in response.content:
	        if block.type != "tool_use":
	            continue
	        print(f"Agent calling {block.name}: {block.input}")
	        output = TOOL_EXECUTORS[block.name](**block.input)
	        tool_results.append(
	            {"type": "tool_result", "tool_use_id": block.id, "content": output}
	        )

	    # All tool results for one assistant turn go back in ONE user message
	    messages.append({"role": "user", "content": tool_results})
	else:
	    print("Stopped: hit the maximum iteration cap without finishing.")

Hai chi tiết trong vòng lặp này ngăn các sự cố thực sự. 

Thứ nhất, một lượt của mô hình có thể chứa nhiều lời gọi công cụ, và API Anthropic yêu cầu mọi kết quả của lượt đó phải được trả về trong một tin nhắn người dùng. 

Thứ hai, cấu trúc for/else báo khi agent chạm trần số vòng lặp, vì vậy một lần chạy bị treo sẽ thất bại ồn ào thay vì kết thúc trong im lặng.

Cấu trúc rõ ràng này giúp bạn thấy chính xác mô hình dừng suy nghĩ ở đâu, Python tiếp quản để chạy lệnh ở đâu, và đầu ra được đưa trở lại vòng lặp như thế nào.

Thêm hook hậu chỉnh sửa

Hook bắt lỗi trước khi chúng kết chuỗi thành các vấn đề cấu trúc lớn hơn. 

Trong harness của chúng ta, một hook là hàm kiểm tra một lần gọi công cụ đã hoàn tất và trả về văn bản bổ sung để nối vào kết quả công cụ. 

Thành công trả về chuỗi rỗng; thất bại trả về báo cáo chi tiết.

Thêm hàm này vào harness.py phía trên vòng lặp ReAct, cạnh các executor công cụ. Vòng lặp bắt đầu chạy ngay khi Python chạm tới, vì vậy mọi thứ nó gọi phải được định nghĩa sẵn.

def post_edit_hook(tool_name: str, tool_input: dict) -> str:
    """Run pytest after any edit to a Python file. Silent on success."""
    edited_python = (
        tool_name == "write_file" and tool_input.get("path", "").endswith(".py")
    )
    if not edited_python:
        return ""

    tests = subprocess.run(
        ["pytest", "--tb=short", "-q"],
        capture_output=True,
        text=True,
        cwd=WORKSPACE,
        timeout=120,
    )
    # Exit code 5 means "no tests collected", which is fine for our purposes
    if tests.returncode in (0, 5):
        return ""
    return f"\n\n[HOOK] pytest failed after this edit:\n{tests.stdout}"

Đấu nối nó vào vòng lặp chỉ là một dòng thay đổi bên trong khối thực thi công cụ:

output = TOOL_EXECUTORS[block.name](**block.input)
output += post_edit_hook(block.name, block.input)  # hooks run after every tool call

Không có hook, agent ghi một tệp hỏng, thấy Wrote 412 characters to fizzbuzz.py, và tự tin tiếp tục. 

Có hook, cùng kết quả công cụ đó mang theo chính xác traceback của pytest. Ở lượt tiếp theo, agent đọc lỗi và tự sửa bug, không cần nhắc thêm.

Nén ngữ cảnh cơ bản

Để chống mục nát ngữ cảnh, theo dõi độ dài danh sách messages và tóm tắt các lượt cũ khi nó dài quá. 

Có một cái bẫy: bạn không thể cắt lịch sử ở điểm bất kỳ, vì một block tool_use của assistant và tin nhắn tool_result ghép cặp của nó phải ở cùng nhau. Tách cặp sẽ gây lỗi API ngay lập tức.

Hàm nén của chúng ta di chuyển điểm cắt lên trước cho đến khi rơi vào ranh giới an toàn. Xây dựng phần này phía trên harness.py:

COMPACTION_THRESHOLD = 20
KEEP_RECENT = 6


def is_tool_result(message: dict) -> bool:
    return (
        message["role"] == "user"
        and isinstance(message["content"], list)
        and any(
            isinstance(b, dict) and b.get("type") == "tool_result"
            for b in message["content"]
        )
    )


def compact(messages: list) -> list:
    if len(messages) <= COMPACTION_THRESHOLD:
        return messages

    # Never orphan a tool_result from its tool_use: slide the cut forward
    cut = len(messages) - KEEP_RECENT
    while cut < len(messages) and is_tool_result(messages[cut]):
        cut += 1

    old, recent = messages[1:cut], messages[cut:]
    transcript = "\n".join(f"{m['role']}: {str(m['content'])[:500]}" for m in old)

    summary = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=500,
        messages=[{
            "role": "user",
            "content": "Summarize this agent transcript. Preserve the task, "
                       "decisions made, files created, and any unresolved "
                       f"errors:\n\n{transcript}",
        }],
    )

    return [
        messages[0],  # always keep the original task verbatim
        {
            "role": "user",
            "content": f"[Earlier progress, summarized by the harness]\n"
                       f"{summary.content[0].text}",
        },
        *recent,
    ]

Thêm một dòng ở đầu vòng lặp ReAct, trước cuộc gọi API:

messages = compact(messages)

Chúng ta dùng mô hình nhỏ, rẻ hơn để tóm tắt vì nén chạy thường xuyên và cần tốc độ. 

Chúng ta cũng giữ nguyên văn tin nhắn nhiệm vụ ban đầu thay vì tin vào bản tóm tắt sẽ bảo toàn nó.

Harness giờ đã hoàn chỉnh. 

Trước khi tiếp tục, hãy kiểm tra rằng harness.py của bạn đọc theo thứ tự từ trên xuống dưới như sau:

  1. Import, client, WORKSPACE và system_prompt
  2. Danh sách schema TOOLS
  3. Các executor: run_bash(), write_file() và TOOL_EXECUTORS
  4. Hook: post_edit_hook()
  5. Mã nén: COMPACTION_THRESHOLD, KEEP_RECENT, is_tool_result() và compact()
  6. Vòng lặp ReAct, luôn ở cuối

Để bạn hình dung vòng lặp API cuối cùng trông thế nào sau khi thêm phần hook và nén, đây là vòng lặp hoàn chỉnh:

messages = [
    {
        "role": "user",
        "content": "Create a fizzbuzz.py script in the workspace, "
                   "then run it to verify the output.",
    }
]

MAX_STEPS = 15

for step in range(MAX_STEPS):
    print(f"--- Iteration {step + 1} ---")

    # Compaction: summarize old turns before they rot the context
    messages = compact(messages)

    # The API call: model, memory, history, and tools travel together
    response = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=2000,
        system=system_prompt,   # AGENTS.md text, re-injected every turn
        messages=messages,      # the full (possibly compacted) history
        tools=TOOLS,            # the schemas from the tools section
    )

    # Append the model's turn to the history
    messages.append({"role": "assistant", "content": response.content})

    # Stop condition: the model answered without requesting a tool
    if response.stop_reason != "tool_use":
        final_text = "".join(b.text for b in response.content if b.type == "text")
        print(f"Task complete: {final_text}")
        break

    # Execute EVERY tool call in this turn, collecting the results
    tool_results = []
    for block in response.content:
        if block.type != "tool_use":
            continue
        print(f"Agent calling {block.name}: {block.input}")
        output = TOOL_EXECUTORS[block.name](**block.input)
        output += post_edit_hook(block.name, block.input)  # hooks run after every tool call
        tool_results.append(
            {"type": "tool_result", "tool_use_id": block.id, "content": output}
        )

    # All tool results for one assistant turn go back in ONE user message
    messages.append({"role": "user", "content": tool_results})
else:
    print("Stopped: hit the maximum iteration cap without finishing.")

Giờ hãy chạy agent từ thư mục gốc dự án bằng python harness.py.

Script gửi tác vụ từ danh sách messages đến API. 

Harness thực hiện công việc và bạn sẽ thấy mỗi vòng lặp in ra trong terminal:

--- Iteration 1 ---
Agent calling write_file: {'path': 'fizzbuzz.py', 'content': 'def fizz(n):...'}
--- Iteration 2 ---
Agent calling run_bash: {'command': 'python fizzbuzz.py'}
--- Iteration 3 ---
Task complete: fizzbuzz.py is written and prints the correct sequence.

Chương trình thoát khi mô hình trả lời mà không gọi công cụ, hoặc khi chạm trần 15 vòng lặp. 

Để giao tác vụ khác cho agent, thay đổi chuỗi content trong danh sách messages ban đầu; một harness sản xuất sẽ đọc từ input() hoặc đối số dòng lệnh.

Cải thiện Agent Harness của bạn: Bánh cóc vận hành

Bánh cóc là quá trình liên tục chẩn đoán lỗi của agent và cập nhật harness để ngăn chúng.

Một harness chỉ cải thiện thông qua việc tiếp xúc nghiêm túc với các trường hợp biên thực tế.

Hãy cùng đi qua một chu trình lỗi và sửa hoàn chỉnh dựa trên một dự án tối ưu tuyến đường thực tế. 

Hãy tưởng tượng agent của bạn cứ nhập một thư viện định tuyến nội bộ đã ngừng dùng tên là legacy_route_math thay vì phiên bản cập nhật. 

Agent viết script, test thất bại, và nó mắc kẹt trong vòng lặp cố sửa cú pháp thay vì đổi thư viện.

Chẩn đoán ở đây khá đơn giản. 

Agent đơn giản là không biết thư viện đã lỗi thời. Đây là một quy tắc thiếu, không phải lỗi của mạng nơ-ron nền tảng.

Sửa 1 cập nhật lớp bộ nhớ, thêm quy tắc này vào AGENTS.md:

# Rules
1. Never use rm -rf. Use standard rm with specific file names.
2. Never write tests inside the main application file.
3. When you finish the task, reply with a plain-text summary and no tool call.
4. Do not import legacy_route_math; it is deprecated. Use routes_v2 instead.

Sửa 2 thêm một hook cưỡng chế vĩnh viễn. 

Quy tắc là lời khuyên cho agent, hook là mệnh lệnh. Sửa này chỉ vài dòng và có thể thêm cạnh post_edit_hook(), miễn là nằm trước vòng lặp ReAct.

def deprecated_import_hook(tool_name: str, tool_input: dict) -> str:
    if tool_name != "write_file":
        return ""
    if "import legacy_route_math" in tool_input.get("content", ""):
        return (
            "\n\n[HOOK] Blocked pattern: legacy_route_math is deprecated. "
            "Rewrite this file using routes_v2 instead."
        )
    return ""

Đăng ký nó cạnh hook pytest trong khối thực thi công cụ:

output += post_edit_hook(block.name, block.input)
output += deprecated_import_hook(block.name, block.input)

Đây là cách tự sửa hiện ra trong bản ghi sau khi cả hai sửa được áp dụng. 

Agent ghi tệp, hook kích hoạt, và ngay lượt sau sửa import mà không cần con người can thiệp:

--- Iteration 3 ---
Agent calling write_file: {'path': 'optimizer.py', ...}
  [HOOK] Blocked pattern: legacy_route_math is deprecated...
--- Iteration 4 ---
Agent calling write_file: {'path': 'optimizer.py', ...}   # now imports routes_v2
--- Iteration 5 ---
Task complete: Rewrote optimizer.py using routes_v2 and verified the tests pass.

Điều này quan trọng vì nó quay lại vấn đề mục nát ngữ cảnh. Các phiên rất dài với ngữ cảnh suy giảm rồi sẽ bỏ qua quy tắc bộ nhớ. 

Quy tắc trong AGENTS.md ngăn lỗi hầu hết thời gian, và hook đảm bảo rằng khi quy tắc bị trượt, lỗi không gây hư hại. 

Mỗi thất bại bạn chẩn đoán nên khiến bạn hỏi 2 câu: quy tắc nào bị thiếu, và kiểm tra nào sẽ bắt được nó dù sao?

Thực hành tốt nhất cho Agent Harness Engineering

Thực hành tốt nhất tập trung vào việc giữ cấu hình gọn và thiết kế cho nâng cấp mô hình trong tương lai. 

Mục tiêu là xây giàn đỡ hỗ trợ mô hình mà không làm nó quá tải. 

Tôi đã học được vài bài học khó trong khi xây dựng nhiều kỹ năng agent và kiến trúc.

Giữ AGENTS.md ngắn và “xứng đáng”

Nhắm tối đa 60 dòng cho tệp ngữ cảnh của bạn. 

Mỗi quy tắc phải truy ngược về một lỗi thực tế, có ghi nhận mà bạn đã trải qua. Nếu bạn không thể nhớ tình huống dẫn đến quy tắc, thì đáng để xóa nó đi.

Kỷ luật này quan trọng vì AGENTS.md phải trả phí ở mỗi lượt. 

Một hướng dẫn 300 dòng tiêu tốn token ở mỗi cuộc gọi API và làm loãng các quy tắc quan trọng, vì mô hình tuân theo 10 quy tắc sắc bén tốt hơn nhiều so với 80 quy tắc mơ hồ. 

Thêm ngày tháng thậm chí giúp cho thực hành tiếp theo tôi khuyến nghị.

Thiết kế cho tính lỗi thời

Harness cần tái kiến trúc liên tục khi các mô hình nền cải thiện khả năng gốc. 

Hãy xây các thành phần để bạn có thể gỡ bỏ chúng dễ dàng.

Mẫu hook trong hướng dẫn này được cố ý làm mô-đun vì lý do đó. 

Mỗi hook là một hàm riêng rồi được thêm vào bằng một dòng. Nếu bạn cho hook “nghỉ hưu”, bạn chỉ xóa một dòng trong vòng lặp. 

Không có gì khác trong vòng lặp thay đổi. 

So với logic kiểm tra được dệt trực tiếp vào vòng lặp ReAct, nơi việc gỡ một kiểm tra lỗi thời đòi hỏi kiểm thử lại toàn bộ đường điều phối.

Điều có vẻ là chiếc nạng cần thiết hôm nay sẽ trở thành gánh nặng không cần thiết vào quý sau. 

Khi có mô hình mới phát hành, hãy chạy lại các ca lỗi cũ với từng hook bị vô hiệu lần lượt, và coi bất kỳ hook nào không còn bắt được gì là ứng viên xóa. 

Xem Claude Code Best Practices để biết thêm mẹo kiến trúc.

Bắt đầu đơn giản rồi gia tăng độ phức tạp

Một vòng lặp ReAct trần với hệ thống tệp và một công cụ Bash đã rất thực tiễn. 

Hãy cưỡng lại mong muốn xây sẵn một hệ đồ thị phức tạp dùng các framework nặng. Bánh cóc chỉ hoạt động theo một chiều, từ lỗi quan sát được đến sửa chữa có mục tiêu. Sửa chữa “đoán trước” đi ngược chiều đó.

Chỉ thêm hook tùy chỉnh sau khi bạn đã thấy đúng lỗi biện minh cho chúng. Để biết thêm về cấu trúc hệ thống cơ bản, hãy xem hướng dẫn về LLM agents.

Ghi nhật ký mọi thứ agent làm

Bạn không thể “bánh cóc” những gì bạn không thấy. 

Vòng lặp của chúng ta đã in ra mỗi lần gọi công cụ, và đó là khả năng quan sát tối thiểu: khi một lần chạy thất bại, bản ghi in ra là tài liệu chẩn đoán của bạn.

Khi harness trưởng thành, hãy ghi toàn bộ lịch sử tin nhắn của mỗi phiên vào một tệp JSON đóng dấu thời gian khi kết thúc. 

Các bản ghi thất bại trở thành bộ hồi quy của bạn; sau mỗi thay đổi harness, phát lại các tác vụ từng thất bại và xác nhận sửa chữa vẫn hiệu lực. 

Đây là tương đương bộ test của kỹ sư harness, và nó phân biệt một harness biết cải thiện với một cái chỉ đơn thuần thay đổi.

Lời kết

Kỹ thuật harness cho agent là thực tế để biến mô hình AI thành công cụ làm việc hữu ích. 

Khoảng cách giữa những gì các mô hình ngày nay có thể làm về mặt lý thuyết và những gì bạn thực sự thấy trong sản xuất phần lớn là khoảng cách harness.

Kỷ luật này không phải là học một framework cụ thể. 

Harness AI agent phù hợp cho codebase của bạn được định hình hoàn toàn bởi lịch sử lỗi riêng, được xây dựng dần qua phương pháp bánh cóc.

Sẵn sàng đưa những khái niệm này vào thực tế? 

Hãy xem lộ trình kỹ năng AI Agent Fundamentals của DataCamp để tiếp tục xây dựng hệ thống sẵn sàng sản xuất. Bạn cũng có thể khám phá Hướng dẫn Claude Agent SDK để có thêm ví dụ mã thực hành. 

Bạn cũng có thể muốn xem lộ trình kỹ năng AI for Software Engineering.

Câu hỏi thường gặp về kỹ thuật harness cho agent

Sự khác biệt giữa mô hình và agent harness là gì?

Một mô hình tạo văn bản dựa trên đầu vào lời nhắc. Một agent harness là hạ tầng bao quanh cung cấp cho mô hình công cụ, bộ nhớ và quy tắc để thực thi tác vụ trong một môi trường.

Tại sao tôi nên dùng tệp AGENTS.md?

Tệp AGENTS.md bơm các quy tắc và ngữ cảnh theo dự án vào lời nhắc hệ thống. Nó ngăn mô hình đoán mò tech stack của bạn hoặc vi phạm các quy ước mã hóa nội bộ.

Vòng lặp ReAct là gì?

Vòng lặp Reason and Act (ReAct) là khung trong đó agent suy nghĩ về vấn đề, gọi một công cụ để hành động và quan sát kết quả trước khi suy nghĩ tiếp. Nó lặp cho đến khi tác vụ hoàn thành.

Hook ngăn thất bại của agent như thế nào?

Hook chạy các script tùy chỉnh tại những thời điểm vòng đời cụ thể, như chạy bộ test sau khi chỉnh sửa tệp. Nếu test thất bại, hook đưa lỗi trở lại cho agent để tự sửa ngay.

Mục nát ngữ cảnh trong AI agent là gì?

Mục nát ngữ cảnh xảy ra khi lịch sử hội thoại quá lớn và mô hình bắt đầu bỏ qua chỉ dẫn hoặc lạc mục tiêu. Bạn khắc phục bằng cách tóm tắt các tin nhắn cũ để giải phóng không gian.


Tim Lu's photo
Author
Tim Lu
LinkedIn

Tôi là một nhà khoa học dữ liệu có kinh nghiệm về phân tích không gian, học máy và đường ống dữ liệu. Tôi đã làm việc với GCP, Hadoop, Hive, Snowflake, Airflow và các quy trình khoa học/kỹ thuật dữ liệu khác.

Chủ đề
Trí tuệ Nhân tạo
Mô hình Ngôn ngữ Lớn
AI Agents

Khóa học hàng đầu trên DataCamp

Khóa học

Phát triển ứng dụng LLM với LangChain

3 giờ
51.8K
Khám phá cách xây dựng các ứng dụng tích hợp AI bằng cách sử dụng LLM, prompt, chain và agent trong LangChain.
Xem chi tiếtBắt Đầu Khóa Học

Tạo tài khoản miễn phí của bạn

Luyện tập và Lộ trình tiến trình của bạn.

Tiếp Tục Với Google
Bằng cách tiếp tục, bạn chấp nhận Điều khoản sử dụng, Chính sách bảo mật và việc dữ liệu của bạn được lưu trữ tại Hoa Kỳ.
Xem thêm
Liên quan

blog

Claude Opus 4.6: Tính năng, Điểm chuẩn, Bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu ở mã hóa tác tử và lập luận phức tạp. Thêm vào đó, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem thêm