·

Khi ghép context (ngữ cảnh) cho một AI agent — system prompt, tool definitions, tài liệu tham chiếu, lịch sử hội thoại — hầu hết kỹ sư chỉ quan tâm đến "nội dung nói gì" mà quên mất "nội dung được đóng gói bằng cú pháp gì". Nhưng với LLM (Large Language Model), mọi ký tự cú pháp — dấu #, thẻ <xml>, dấu {, dấu hai chấm YAML — đều được tokenizer (bộ mã hóa token) bẻ thành token thật, tốn tiền thật, chiếm context window thật.

Bài này sẽ giúp bạn nhìn context không chỉ như "văn bản" mà như một cấu trúc dữ liệu có chi phí token đo được. Bạn sẽ học cách chọn đúng format cho đúng tình huống: khi nào plain text đủ dùng, khi nào Markdown là lựa chọn hợp lý, khi nào XML tag đáng giá dù dài dòng, và vì sao JSON — dù rất phổ biến — thường là lựa chọn tệ cho input context nhưng lại là lựa chọn đúng cho output.

Đây là kỹ năng áp dụng cho mọi vai trò trong vòng đời phát triển: kỹ sư backend viết prompt cho agent gọi tool, QA engineer thiết kế test case cho agent xử lý tài liệu dài, product manager review chi phí vận hành AI feature — tất cả đều cần hiểu format nào "rẻ" và format nào "đắt".

How Format Syntax Becomes Token Overhead

Tokenizer không nhìn thấy "cấu trúc", nó chỉ thấy ký tự

Một điều nhiều người mới làm agentic engineering (kỹ thuật xây dựng agent) hiểu lầm: LLM không "hiểu" JSON hay Markdown như một cấu trúc dữ liệu trừu tượng trước khi xử lý. Model nhận vào một chuỗi token được tokenizer (thường là BPE — Byte Pair Encoding) cắt ra từ text thô. Cấu trúc — nested object, heading, tag — chỉ là các pattern ký tự mà model đã học được ý nghĩa qua quá trình huấn luyện. Nhưng trước khi có ý nghĩa, chúng đã là token, và token thì tính tiền.

Điều này dẫn đến một nguyên tắc cốt lõi: mỗi ký tự cú pháp dùng để "trang trí" hoặc "đóng khung" nội dung là một khoản chi phí ẩn, tách biệt hoàn toàn với giá trị thông tin bạn muốn truyền đạt.

Ví dụ minh họa nhanh với ước lượng token (dùng tokenizer kiểu GPT/Claude, xấp xỉ theo quy tắc chung "~4 ký tự tiếng Anh = 1 token", tiếng Việt có dấu thường nặng hơn theo tỷ lệ ~1.5–2 token/từ):

Nội dung thuần:          "user name John status active"        ≈ 6-7 tokens

Cùng nội dung, JSON:
{"user_name": "John", "status": "active"}                       ≈ 14-16 tokens

Cùng nội dung, XML:
<user_name>John</user_name><status>active</status>               ≈ 16-18 tokens

Cùng nội dung, key-value đơn giản:
user_name: John
status: active                                                    ≈ 8-9 tokens

Nội dung thông tin y hệt (2 field, 2 giá trị) nhưng chi phí token chênh nhau tới 2-2.5 lần chỉ vì cú pháp bao bọc. Nhân số này lên với hàng nghìn record trong một context window, hoặc hàng triệu request/ngày trong production, và khoảng cách "vô hại tưởng chừng" này trở thành khoản chi phí vận hành đáng kể.

Ba nguồn gây "token tax" (thuế token) từ cú pháp

  1. Ký tự lặp lại theo cấu trúc — dấu ngoặc, dấu phẩy, dấu ngoặc kép trong JSON; thẻ mở/đóng trong XML; dấu -, *, # trong Markdown. Những ký tự này không mang thông tin nghiệp vụ, chỉ mang thông tin cấu trúc.
  2. Tên field/key lặp lại — trong JSON array có 100 object cùng schema, tên field được lặp lại 100 lần dù giá trị của nó là cố định và có thể suy ra từ context.
  3. Khoảng trắng và định dạng đẹp (pretty-print) — thụt đầu dòng, xuống dòng để dễ đọc cho con người thường bị tokenizer tính là token riêng hoặc gộp vào token liền kề theo cách kém hiệu quả.

Mẹo

  • Đừng tối ưu "trông đẹp cho con người" khi context đó chỉ máy đọc — model không cần thụt lề 4 space để hiểu cấu trúc.
  • Dùng công cụ đếm token thật (tiktoken cho OpenAI, hoặc token counter API của Anthropic) để đo trước khi kết luận cảm tính "format này chắc rẻ hơn". Cảm giác trực quan về độ dài ký tự thường sai lệch với số token thực tế, đặc biệt với tiếng Việt có dấu.
  • Khi thiết kế lại một prompt hoặc context template, hãy paste cả 2-3 phiên bản format vào token counter và so sánh trực tiếp — đừng đoán.

Plain Text and Labeled Key-Value Format

Format rẻ nhất bạn thường bỏ qua

Trước khi nhảy vào Markdown hay JSON theo phản xạ, hãy cân nhắc format đơn giản nhất: plain text tự nhiên, hoặc key-value dạng label: value không có ký tự bao bọc thừa. Đây là format có chi phí token thấp nhất trên mỗi đơn vị thông tin, vì nó gần với cách model được huấn luyện để đọc ngôn ngữ tự nhiên nhất.

Ví dụ so sánh cùng một payload context cho agent:

Customer: Nguyen Van A
Order ID: 48291
Status: shipped
Delivery ETA: 2026-07-12

{
  "customer": "Nguyen Van A",
  "order_id": 48291,
  "status": "shipped",
  "delivery_eta": "2026-07-12"
}

Với dữ liệu phẳng (flat data), không có nesting (lồng cấp), key-value dạng label: value gần như luôn thắng về token. Đây là lựa chọn mặc định tốt cho: system prompt phần "context hiện tại", tóm tắt state của agent, hoặc feed dữ liệu tra cứu (lookup data) vào prompt.

Giới hạn của plain text / key-value

Cách này có giới hạn rõ ràng khi dữ liệu có cấu trúc lồng nhau (nested) hoặc quan hệ nhiều-nhiều. Ví dụ, khi bạn cần biểu diễn "một đơn hàng có nhiều sản phẩm, mỗi sản phẩm có nhiều thuộc tính", key-value phẳng buộc bạn phải dùng prefix lặp lại (item_1_name, item_1_qty, item_2_name, item_2_qty...) — về lâu dài việc này lại tốn token hơn và dễ gây nhầm lẫn cho model khi phải tự suy luận ranh giới giữa các nhóm.

Giải pháp trung gian thường dùng là "key-value có phân đoạn bằng dòng trắng hoặc dấu gạch ngang nhẹ":

Item 1
Name: USB-C Cable 1m
Qty: 2
Price: 89000

Item 2
Name: Wireless Mouse
Qty: 1
Price: 259000

Cách này vẫn rẻ hơn JSON/XML tương đương, nhưng bắt đầu cần một quy ước nhất quán (convention) để model không nhầm ranh giới giữa các item — đây là điểm bắt đầu bạn nên nghĩ tới các format có cấu trúc rõ ràng hơn như Markdown hoặc XML, được trình bày ở các phần sau.

Khi nào nên dùng plain text/key-value

  • Dữ liệu phẳng, không lồng cấp, số lượng field cố định và ít (dưới ~10 field).
  • Context ngắn hạn, dùng một lần trong một lượt gọi (không cần machine-parse lại kết quả).
  • Bạn ưu tiên tối đa việc giảm token trên các luồng có volume cao (agent chạy hàng nghìn lần/ngày với payload tương tự).

Mẹo

  • Với QA engineer thiết kế test data cho agent: dùng key-value phẳng cho fixture đơn giản, tiết kiệm đáng kể token khi chạy hàng loạt test case.
  • Đừng cố nhồi dữ liệu quan hệ phức tạp vào key-value phẳng chỉ để tiết kiệm token — chi phí "model hiểu sai cấu trúc" (dẫn đến output sai, phải retry) luôn lớn hơn chi phí vài chục token tiết kiệm được.
  • Khi field name dài và lặp lại nhiều, cân nhắc viết tắt có giải thích một lần ở đầu context (ví dụ: "Từ đây, qty = quantity, eta = estimated time of arrival") để giảm token lặp lại về sau.

Markdown: Benefits and Hidden Costs

Vì sao Markdown là lựa chọn phổ biến nhất

Markdown là format được dùng nhiều nhất trong system prompt và context engineering hiện nay, vì hai lý do chính đáng: (1) các model lớn (GPT, Claude, Gemini) được huấn luyện với lượng dữ liệu Markdown khổng lồ từ GitHub, docs, forum — nên model "hiểu" heading, list, bold một cách tự nhiên và nhất quán; (2) Markdown giúp phân vùng nội dung rõ ràng cho cả người viết prompt và model đọc, giảm khả năng model nhầm lẫn ranh giới giữa các phần khác nhau của context (instructions, examples, constraints, output format).

Đây là lợi ích thật, không phải cảm tính — nhiều benchmark nội bộ của các team agentic engineering cho thấy system prompt có heading Markdown rõ ràng giúp model tuân theo instruction tốt hơn plain text không phân đoạn, đặc biệt với prompt dài trên 1500-2000 token.

Chi phí ẩn: mỗi ký tự Markdown đều là token

Vấn đề là ký tự Markdown không miễn phí. Hãy nhìn vào ước lượng token cho các thành phần Markdown phổ biến:

## Subsection             → 3–4 tokens (## + space + content)
### Sub-subsection        → 4–5 tokens
**bold text**              → +2 tokens so với text thường (2 dấu ** mở, 2 dấu ** đóng)
- bullet item               → +1 token cho dấu "- " mỗi dòng
| col1 | col2 | col3 |      → +6-8 tokens riêng cho ký tự khung bảng, chưa tính nội dung

Ví dụ cụ thể với một heading thường gặp trong system prompt agent:

## Constraints

Riêng dòng này đã tốn khoảng 3-4 token (##, khoảng trắng, Constraints) — chưa tính nội dung bên dưới. Nếu system prompt của bạn có 15 heading/subheading kiểu này (Role, Goal, Constraints, Tools, Output Format, Examples, Edge Cases...), bạn đã "mất" 45-60 token chỉ cho cấu trúc heading, trước khi viết một chữ nội dung nào. Với context window hạn chế hoặc khi system prompt này được gửi lại ở MỌI lượt gọi (vì không cache được phần thay đổi), số token này nhân lên theo số lượt gọi trong ngày.

Bảng Markdown là "kẻ tốn token" đáng chú ý nhất. Mỗi dòng bảng có ký tự | ở đầu, giữa, cuối — với bảng 5 cột, bạn trả thêm khoảng 6 token/dòng chỉ cho khung bảng, và dòng phân cách header (|---|---|---|---|---|) tốn thêm 10-12 token mà không mang thông tin gì cả. Với bảng dữ liệu có 50 dòng, chi phí khung bảng thuần có thể lên tới 300-400 token lãng phí.

Cách dùng Markdown "tiết kiệm" mà vẫn giữ lợi ích

  • Dùng heading có mục đích thật (phân vùng logic rõ ràng: Role / Task / Constraints / Output Format), không dùng heading trang trí cho từng câu.
  • Hạn chế heading level sâu (### hoặc ####) khi không cần — level sâu vừa tốn token vừa không tăng thêm giá trị phân vùng đáng kể so với heading nông hơn.
  • Với dữ liệu dạng bảng lớn, cân nhắc chuyển sang key-value theo dòng hoặc CSV thô (không có khung |) — CSV giữ được cấu trúc hàng-cột nhưng rẻ hơn Markdown table đáng kể.
  • Bold (**text**) chỉ nên dùng khi thực sự cần nhấn instruction quan trọng (ví dụ: "Never call this tool without user confirmation"), không dùng tùy tiện.

Mẹo

  • Nếu system prompt của bạn được gửi lại giống nhau ở mọi lượt gọi, hãy tận dụng prompt caching (cơ chế cache prompt) của Anthropic/OpenAI — phần chi phí token Markdown "cứng" chỉ tính phí đầy đủ ở lượt đầu, các lượt sau tính phí thấp hơn nhiều. Điều này thay đổi hẳn phép tính "có nên dùng Markdown hay không".
  • Khi review một system prompt cũ, thử đếm số heading và ước lượng token cho riêng phần cú pháp (không tính nội dung) — con số này thường gây bất ngờ.
  • Với PM/QA cần đọc lại prompt để review logic nghiệp vụ, giữ Markdown ở mức "đủ dùng" — đừng đánh đổi khả năng đọc của con người lấy vài chục token, vì chi phí bug do hiểu sai prompt luôn lớn hơn.

XML Tags: When Verbosity Pays Off

XML dài dòng, nhưng "dài dòng có chủ đích"

XML tag (<tag>...</tag>) rõ ràng tốn token hơn Markdown heading cho cùng một đơn vị phân vùng — mỗi tag mở/đóng đều lặp lại tên tag hai lần. Nhưng đây là trường hợp hiếm hoi mà "tốn hơn" lại là lựa chọn đúng, vì lý do không nằm ở số token mà nằm ở độ chính xác của model khi xử lý context dài, nhiều phần, hoặc dễ gây nhầm ranh giới.

Anthropic khuyến nghị dùng XML tag khá nhiều trong prompt engineering cho Claude, đặc biệt vì Claude được huấn luyện và fine-tune với lượng lớn dữ liệu có cấu trúc XML rõ ràng — model bám ranh giới tag rất tốt, gần như không bao giờ nhầm lẫn nội dung bên trong <example> với nội dung bên trong <instructions>, dù cả hai đặt liền kề nhau trong context dài hàng nghìn token.

Khi nào verbosity của XML đáng giá

  1. Ghép nhiều đoạn dài, nhiều loại nội dung khác nhau vào một context. Ví dụ agent nhận vào cùng lúc: tài liệu tham chiếu, lịch sử hội thoại, vài ví dụ few-shot, và instruction cuối. Nếu chỉ dùng Markdown heading, với context dài, model có thể "trôi" ranh giới — nhất là khi một đoạn nội dung bên trong vô tình chứa ký tự # (ví dụ tài liệu kỹ thuật có heading riêng). XML tag không bị nhầm với nội dung bên trong vì tag name thường độc nhất (<reference_document>, <conversation_history>).

  2. Nhiều ví dụ few-shot cần phân biệt rõ input/output. Khi bạn đưa 5-10 ví dụ vào prompt để agent học pattern, việc bọc mỗi ví dụ trong <example> và tách <input>/<output> bên trong giúp model không nhầm ví dụ 3 với ví dụ 4, đặc biệt khi input/output có độ dài lớn.

  3. Cần model trích dẫn ngược lại đúng phần nội dung nào. Nếu bạn yêu cầu agent "trả lời dựa trên nội dung trong <policy_document>, không dùng kiến thức ngoài", tag XML tạo một "container" rõ ràng để model neo vào, giảm hallucination (bịa thông tin) do nhầm nguồn.

Ví dụ minh họa cấu trúc dùng XML hợp lý:

<role>
You are a customer support agent for a fintech app in Vietnam.
</role>

<policy_document>
[... nội dung chính sách hoàn tiền dài 800 token ...]
</policy_document>

<conversation_history>
[... 10 lượt hội thoại trước ...]
</conversation_history>

<examples>
  <example>
    <input>Tôi muốn hủy giao dịch đã chuyển nhầm số tài khoản.</input>
    <output>Xin chào, để hủy giao dịch chuyển nhầm, bạn vui lòng...</output>
  </example>
</examples>

<instructions>
Trả lời câu hỏi mới nhất của khách hàng, chỉ dựa trên policy_document ở trên.
</instructions>

Ở đây, phần token "tốn thêm" do tag (<policy_document>, </policy_document>...) chỉ khoảng vài chục token trên tổng context có thể lên tới 2000-3000 token — chi phí tương đối nhỏ, nhưng lợi ích về độ chính xác phân vùng là rất lớn khi context có nhiều loại nội dung ghép lại.

Khi nào KHÔNG nên dùng XML

Với context ngắn, ít phần, không có nguy cơ nhầm ranh giới (ví dụ: một instruction đơn giản, một câu hỏi, không ví dụ, không tài liệu tham chiếu dài), dùng XML chỉ tốn thêm token mà không mang lại lợi ích tương xứng. Markdown heading hoặc key-value đơn giản vẫn tốt hơn trong trường hợp này.

Mẹo

  • Chọn tên tag ngắn nhưng rõ nghĩa (<doc> thay vì <the_reference_document_content>) — bạn vẫn giữ được lợi ích phân vùng mà giảm token lặp lại ở tag đóng.
  • Đừng lồng quá 3 cấp tag XML — vượt quá mức đó, chi phí token tăng nhanh mà lợi ích phân vùng không tăng tương xứng; nên cân nhắc gộp lại hoặc chuyển một phần sang Markdown bên trong tag ngoài.
  • Với agent xử lý tài liệu dài (RAG — Retrieval-Augmented Generation), luôn bọc từng chunk tài liệu trong tag có ID (<chunk id="3">) để agent trích dẫn nguồn chính xác khi trả lời — điều này còn giúp bạn debug khi agent trả lời sai.

JSON: The Right Tool for Structured Outputs, Not Inputs

Sai lầm phổ biến: dùng JSON cho input context

Rất nhiều kỹ sư quen với JSON từ công việc backend nên mặc định "dữ liệu có cấu trúc → dùng JSON" — kể cả khi nhồi dữ liệu vào context cho LLM. Đây thường là lựa chọn tốn token nhất trong tất cả các format đã nói ở trên, vì JSON yêu cầu dấu ngoặc kép cho MỌI string key và value, dấu phẩy phân tách mọi field, dấu ngoặc nhọn/vuông cho mọi object/array — tất cả đều là token thuần cú pháp.

Quan trọng hơn, JSON không có lợi thế "model được train quen" mạnh như Markdown cho việc đọc hiểu ngữ nghĩa tự nhiên — JSON được model xử lý tốt như một format có cấu trúc chặt, nhưng bản thân cú pháp {}, [], ,, : không giúp model "hiểu nội dung" tốt hơn Markdown hay plain text, nó chỉ giúp máy khác (code) parse lại kết quả dễ dàng.

JSON tỏa sáng nhất ở output có schema

Ngược lại, JSON là lựa chọn đúng đắn khi bạn cần agent trả về structured output (đầu ra có cấu trúc) để code của bạn parse lại và xử lý tiếp — vì lúc này giá trị của JSON không nằm ở "token rẻ" mà ở "máy đọc được 100% chính xác, không cần thêm bước NLP để trích xuất". Cả OpenAI và Anthropic đều cung cấp cơ chế native để ép model trả JSON đúng schema, tránh lỗi cú pháp JSON do model tự viết tay.

Ví dụ OpenAI structured output (dùng response_format với JSON Schema):

from openai import OpenAI

client = OpenAI()

response = client.chat.completions.create(
    model="gpt-4.1",
    messages=[
        {"role": "system", "content": "Extract order information from the support ticket."},
        {"role": "user", "content": ticket_text},
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "order_extraction",
            "schema": {
                "type": "object",
                "properties": {
                    "order_id": {"type": "string"},
                    "issue_type": {
                        "type": "string",
                        "enum": ["refund", "shipping_delay", "damaged_item"]
                    },
                    "priority": {"type": "string", "enum": ["low", "medium", "high"]}
                },
                "required": ["order_id", "issue_type", "priority"],
                "additionalProperties": False
            },
            "strict": True
        }
    }
)

Ví dụ Anthropic tool use cho structured output (dùng tool schema để ép output đúng cấu trúc, cách phổ biến nhất để lấy JSON có kiểm soát từ Claude):

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    tools=[
        {
            "name": "record_order_extraction",
            "description": "Record structured order data extracted from the support ticket.",
            "input_schema": {
                "type": "object",
                "properties": {
                    "order_id": {"type": "string"},
                    "issue_type": {
                        "type": "string",
                        "enum": ["refund", "shipping_delay", "damaged_item"]
                    },
                    "priority": {"type": "string", "enum": ["low", "medium", "high"]}
                },
                "required": ["order_id", "issue_type", "priority"]
            }
        }
    ],
    tool_choice={"type": "tool", "name": "record_order_extraction"},
    messages=[
        {"role": "user", "content": f"Extract order info from this ticket:\n{ticket_text}"}
    ]
)

Cả hai cách đều buộc model trả về JSON hợp lệ theo schema định trước — bạn không phải viết logic parse "cố gắng đoán" khi model lỡ trả sai format, và bạn không phải trả token cho việc model "giải thích" hay thêm text ngoài JSON.

Vậy khi nào JSON hợp lý cho input?

Có một trường hợp ngoại lệ: khi context input của bạn CHÍNH LÀ dữ liệu mà agent cần xử lý bằng logic tương tự code (ví dụ agent debug một API response, hoặc agent cần hiểu chính xác kiểu dữ liệu — số nguyên, boolean, null — mà key-value dạng text dễ gây mơ hồ). Trong các trường hợp này, giữ nguyên JSON gốc (không convert) giúp model không suy luận sai kiểu dữ liệu, và giá trị "chính xác" quan trọng hơn vài chục token tiết kiệm được.

Mẹo

  • Quy tắc thực dụng: input context → ưu tiên plain text/key-value/Markdown/XML; output cần code parse → dùng JSON qua structured output/tool use, đừng yêu cầu model "tự viết JSON trong câu trả lời text thường" (dễ lỗi cú pháp, lại không tiết kiệm token gì).
  • Nếu bạn đang convert dữ liệu JSON có sẵn (từ database, API) thành context cho agent, đừng paste JSON thô — hãy viết một hàm nhỏ convert JSON → key-value/Markdown trước khi đưa vào prompt, tiết kiệm 30-50% token cho phần dữ liệu này.
  • Khi dùng tool use/function calling để lấy structured output, đặt tool_choice ép buộc gọi đúng tool đó (như ví dụ trên) nếu bạn chắc chắn luôn cần output theo schema này — tránh trường hợp model trả lời bằng text tự do thay vì gọi tool.

YAML: A Middle Ground Worth Knowing

YAML — ít cú pháp hơn JSON, vẫn giữ được cấu trúc lồng nhau

YAML là lựa chọn ít được nhắc tới trong các bài viết về prompt engineering, nhưng lại là "điểm cân bằng" đáng chú ý giữa key-value phẳng (rẻ nhưng không lồng cấp được tốt) và JSON (lồng cấp tốt nhưng đắt). YAML dùng thụt lề (indentation) và dấu hai chấm để biểu diễn cấu trúc, không cần dấu ngoặc nhọn, dấu ngoặc kép cho mọi key, hay dấu phẩy phân tách — nhờ đó giảm đáng kể lượng ký tự cú pháp thuần so với JSON, trong khi vẫn biểu diễn được object lồng nhau và array.

So sánh cùng dữ liệu, ba format:

order:
  id: 48291
  customer: Nguyen Van A
  items:
    - name: USB-C Cable
      qty: 2
    - name: Wireless Mouse
      qty: 1
  status: shipped
// JSON tương đương (đắt hơn ~35-45%)
{
  "order": {
    "id": 48291,
    "customer": "Nguyen Van A",
    "items": [
      {"name": "USB-C Cable", "qty": 2},
      {"name": "Wireless Mouse", "qty": 1}
    ],
    "status": "shipped"
  }
}

Chênh lệch đến từ việc YAML không cần dấu ngoặc kép cho string thường, không cần dấu phẩy, không cần lặp lại dấu ngoặc nhọn cho mỗi object trong array. Với dữ liệu có nhiều cấp lồng và nhiều field, khoảng cách token giữa YAML và JSON có thể lên tới 40-50% cho cùng thông tin.

YAML phù hợp nhất ở đâu trong agent context

  • Context cấu hình (config context): mô tả tool definition dạng con người đọc được, policy rule, hoặc "state" phức tạp của agent có nhiều cấp (ví dụ: trạng thái multi-step workflow với các bước con). YAML giữ được cấu trúc rõ ràng mà vẫn dễ đọc khi review.
  • Few-shot example có cấu trúc lồng: khi ví dụ input/output của bạn tự nó là dữ liệu có nhiều field và nested object, viết ví dụ bằng YAML thay vì JSON giúp tiết kiệm token đáng kể trên mỗi ví dụ — và với 5-10 ví dụ trong một prompt, khoản tiết kiệm này nhân lên rõ rệt.
  • System prompt mô tả nhiều tool với schema tham số phức tạp: nếu bạn không dùng cơ chế tool-calling native của API mà mô tả tool ngay trong text prompt (một số framework agent tự build vẫn làm vậy), YAML là lựa chọn rẻ hơn JSON để mô tả input schema của từng tool.

Rủi ro cần lưu ý khi dùng YAML

YAML nhạy với thụt lề — sai một khoảng trắng có thể đổi nghĩa cấu trúc, và vì model sinh text tuần tự, model tự sinh YAML (khi được yêu cầu output YAML) có xác suất lỗi thụt lề cao hơn JSON. Vì vậy, quy tắc quan trọng: dùng YAML cho INPUT context viết tay bởi bạn (nơi bạn kiểm soát được cú pháp), tránh yêu cầu model tự generate YAML làm output nếu output đó cần được code parse chính xác — trường hợp đó JSON qua structured output/tool use vẫn an toàn hơn.

Mẹo

  • Khi viết few-shot examples có nhiều field lồng nhau, thử chuyển từ JSON sang YAML và đo token trước/sau — phần lớn trường hợp bạn sẽ thấy khoản tiết kiệm rõ rệt mà không mất đi tính rõ ràng của cấu trúc.
  • Tránh dùng YAML cho output mà hệ thống của bạn cần parse tự động ở production — độ nhạy với thụt lề khiến việc parse output do model tự sinh kém tin cậy hơn JSON qua structured output.
  • Với PM/QA cần đọc và review nội dung config hoặc test case có cấu trúc phức tạp, YAML thường dễ đọc hơn JSON đáng kể — đây là lợi ích "ngoài token" nhưng cũng nên cân nhắc khi chọn format cho tài liệu nội bộ đi kèm agent.

Tổng kết nhanh cho cả bài: không có format "tốt nhất tuyệt đối" — chỉ có format phù hợp nhất cho tình huống cụ thể. Với input context, thứ tự ưu tiên chung nên là: plain text/key-value (rẻ nhất, dữ liệu phẳng) → Markdown (cân bằng, có phân vùng, model quen thuộc) → YAML (khi cần lồng cấp mà vẫn muốn tiết kiệm) → XML (khi cần phân vùng nghiêm ngặt giữa nhiều loại nội dung dài). JSON nên dành riêng cho structured output thông qua cơ chế native của model provider, không phải cho input context bạn tự viết tay. Hiểu rõ sự khác biệt này là một trong những cách đơn giản nhất để giảm chi phí token mà không đánh đổi chất lượng agent.