Đến đây, bạn đã học qua context hierarchy (thứ bậc context), cách viết lean system prompt, structured context format, kỹ thuật context selection và context layering. Nhưng kiến thức rời rạc chỉ có giá trị khi ghép lại thành một quy trình làm việc thật. Bài này là bài thực hành tổng kết module: chúng ta sẽ cầm một configuration thật — system prompt của một "Code Review Agent" (agent tự động review pull request) — và đi qua toàn bộ vòng đời tối ưu, từ audit đến đo lường tác động, với mục tiêu cụ thể: giảm ít nhất 50% token mà không đánh đổi chất lượng review.
Đây không phải bài tập lý thuyết. Bạn sẽ thấy một system prompt bị "phình to" (bloated) đúng kiểu bạn gặp trong công việc thật — thứ mà một đội ngũ đã tích lũy qua nhiều tháng, mỗi khi có vấn đề lại thêm một đoạn "để chắc ăn". Rồi chúng ta sẽ audit nó, viết lại nó, kiểm chứng chất lượng bằng golden test case, tách nó thành kiến trúc layering, và cuối cùng tính ra con số tiết kiệm thực tế ở quy mô 1.000 lượt gọi. Toàn bộ 5 phase này chính là quy trình bạn sẽ áp dụng lại cho bất kỳ agent nào trong tổ chức của mình.
The Starting Point: A Representative Bloated Configuration
Trước khi tối ưu bất cứ thứ gì, bạn cần một baseline (đường mốc so sánh) thật. Dưới đây là system prompt của "Code Review Agent" — một agent được một đội engineering dùng để tự động review mọi pull request trước khi con người nhìn vào. Đây là kiểu configuration rất phổ biến: viết bởi nhiều người, qua nhiều lần chỉnh sửa, không ai từng ngồi lại đọc toàn bộ một lượt.
## About This Agent
You are an extremely thorough, knowledgeable, and helpful AI code review
assistant. You have been carefully crafted and fine-tuned by our engineering
team to act as a trusted second pair of eyes on every single pull request
that gets opened in our repositories. We built you because we care deeply
about code quality, and we believe that a great code review process is one
of the most important things a healthy engineering organization can have.
Please always keep this mission in mind as you work. You should think of
yourself as a helpful, experienced senior engineer who has seen a lot of
codebases and knows what good code looks like.
## How To Review Code
When you review a pull request, please read through all of the changed
files carefully, one by one. Take your time. Try to understand what the
author of the pull request was trying to accomplish, and then evaluate
whether the code actually accomplishes that goal in a good way. Look for
bugs, obviously, but also look for things that might not be bugs today but
could become bugs later, such as edge cases that aren't handled, or
assumptions that might not always be true. Also pay attention to whether
the code is readable and whether someone else on the team, six months from
now, would be able to understand what this code does and why. If you are
ever unsure about something, it's better to raise it as a question than to
stay silent, because our reviewers would rather see too many comments than
too few. Please be thorough. Please be careful. Please double check your
own findings before reporting them, since false positives waste engineers'
time.
## Our Tech Stack Details
Our main backend service is written in Python 3.11 using the FastAPI
framework. We use PostgreSQL 15 as our primary database, accessed through
SQLAlchemy 2.0 with async sessions. Our frontend is a React 18 application
written in TypeScript, using Vite as the build tool and TanStack Query for
data fetching. We deploy everything on AWS, using ECS Fargate for our
services and RDS for our database. We used to have a legacy PHP monolith
that some of our older services still occasionally reference, although it
is being phased out. We also have a small set of internal tooling written
in Go for CLI utilities. Our CI pipeline runs on GitHub Actions. We use
Terraform for infrastructure as code. Just so you have the full picture,
we also occasionally use Python notebooks for data analysis, though that
is unrelated to the main product codebase.
## Code Style Standards
We care a lot about consistent code style. Please make sure that Python
code follows PEP 8 conventions. Variable and function names should be
descriptive and use snake_case. Class names should use PascalCase. Please
also check that imports are organized properly, with standard library
imports first, then third-party imports, then local imports, each group
separated by a blank line. For TypeScript code, please check that we are
using camelCase for variables and functions, and PascalCase for components
and types. We prefer functional components over class components in
React. We also generally prefer named exports over default exports,
although this is a soft preference rather than a hard rule. Please also
flag any lines that exceed 100 characters, and any functions that seem
excessively long or that seem to be doing more than one thing, since we
value small, focused functions.
## Testing Requirements
Every pull request should ideally include tests for the new behavior it
introduces. We aim for our codebase to maintain at least 80% test
coverage overall, although we understand that not every single line needs
a dedicated test. Please check whether the pull request includes
reasonable test coverage for the changes being made, and flag it if there
are no tests at all for a non-trivial change. We generally use pytest for
our Python tests and Vitest with React Testing Library for our frontend
tests. Please also consider whether the tests that were added actually
test meaningful behavior, rather than just asserting trivial things, since
we've noticed in the past that sometimes tests are added just to satisfy a
coverage requirement without really testing anything useful.
## Security Rules - VERY IMPORTANT
Security is extremely important to us, so please pay very close attention
to this section. VERY IMPORTANT: always check for SQL injection
vulnerabilities, especially anywhere that raw SQL queries are constructed
using string concatenation or f-strings instead of parameterized queries.
This is VERY IMPORTANT and should never be missed. Also VERY IMPORTANT:
check for hardcoded secrets, API keys, passwords, or tokens anywhere in the
code, including in test files and configuration files. Also check for
missing authentication or authorization checks on any new API endpoints,
since we have had incidents in the past caused by endpoints that were
accidentally left unauthenticated. Please also check for potential
cross-site scripting (XSS) issues on the frontend, and make sure that any
user-provided input that gets rendered is properly escaped. This is all
VERY IMPORTANT so please do not skip this section even if you are running
low on time or attention.
## Output Format Instructions
When you finish reviewing, please write up your findings in a clear way.
Try to organize your comments by file, and within each file, try to order
them in a way that makes sense, such as by line number. For each issue you
find, explain what the issue is and why it matters, and if possible,
suggest how it could be fixed. It would also be nice if you could give an
overall summary at the end of your review, mentioning the general quality
of the pull request and whether you think it's ready to merge, needs some
changes, or has serious issues that need to be addressed before it can be
merged at all. Please try to be constructive and encouraging in your tone,
since we want engineers to feel good about the review process, not
discouraged by it.
## Reminder About Our Values
As a final reminder, our engineering team believes strongly in
collaboration, respect, and continuous learning. We believe that code
review is not just about catching bugs, but also about helping each other
grow as engineers. Please keep this spirit in mind throughout your review,
and remember that behind every pull request is a person who put effort
into their work.
Ước tính token ở đây dùng quy tắc nhanh khoảng 4 ký tự tiếng Anh ≈ 1 token mà bạn đã học ở Module 1 — đủ chính xác để so sánh tương đối giữa các phiên bản, không cần tokenizer thật để thấy vấn đề. 847 token cho một system prompt nghe không quá khủng khiếp trên giấy, nhưng hãy nhớ: đây là chi phí cố định phải trả ở mọi lượt gọi, bất kể pull request lớn hay nhỏ, và nó cộng dồn tuyến tính theo số lượt review.
Mẹo
Khi audit một configuration thật trong công việc, đừng chỉ nhìn vào bản mới nhất trên Git — hãy hỏi ai là người viết từng đoạn và vì lý do gì. Rất nhiều đoạn "phình to" xuất phát từ một sự cố cụ thể trong quá khứ ("lần trước agent bỏ sót SQL injection nên ai đó thêm cảnh báo VERY IMPORTANT"). Biết nguồn gốc giúp bạn tự tin cắt bỏ phần dư mà không sợ tái tạo lại lỗi cũ.
Phase 1: Bloat Identification Audit
Đọc lại system prompt trên, bạn sẽ thấy nó không "sai" ở bất kỳ câu nào — mỗi câu đều có ý nghĩa hợp lý khi đọc riêng lẻ. Bloat không phải là những câu sai, mà là mật độ chỉ dẫn (instruction density) quá thấp so với độ dài văn bản. Dưới đây là các dấu hiệu bloat cụ thể có trong ví dụ trên, đây cũng là checklist bạn nên áp dụng cho mọi audit tương tự:
1. Văn phong hoa mỹ, không mang thông tin. Phần "About This Agent" tốn khoảng 120 token chỉ để nói "bạn là một reviewer cẩn thận". Không có một quy tắc hành động (actionable rule) nào trong đó. LLM không cần được "động viên" hay nghe kể về sứ mệnh của công ty để review code tốt hơn — nó cần biết chính xác phải kiểm tra gì.
2. Hướng dẫn dạng văn xuôi thay vì cấu trúc. Phần "How To Review Code" diễn đạt một quy trình 4-5 bước dưới dạng đoạn văn liên tục, không bullet, không số thứ tự. Cùng một nội dung, viết dạng danh sách có thể ngắn hơn 40-50% và dễ parse hơn cho cả người và model.
3. Thông tin dư thừa, không liên quan trực tiếp đến review. Phần "Our Tech Stack Details" liệt kê cả "legacy PHP monolith... đang được phase out" và "Python notebook cho data analysis... không liên quan đến codebase chính". Agent review code không cần biết những chi tiết này để làm tốt việc của nó — đây là thông tin "để cho đầy đủ", đúng kiểu context mà bài về context selection đã cảnh báo.
4. Lặp lại quy tắc đã được enforce ở nơi khác. Phần "Code Style Standards" mô tả lại chi tiết PEP 8, naming convention — những thứ linter (ESLint, Black, Ruff...) đã chặn từ trước khi PR đến agent. Agent không cần nhắc lại quy tắc mà tool khác đã đảm bảo; nó chỉ cần review những gì linter không bắt được.
5. Nhấn nhá "VERY IMPORTANT" lặp đi lặp lại. Phần "Security Rules" dùng "VERY IMPORTANT" bốn lần trong một đoạn ngắn. Việc lặp lại từ nhấn mạnh không làm model chú ý hơn — nó chỉ tốn token. Nếu mọi thứ đều "rất quan trọng", model không còn cách nào phân biệt thứ gì quan trọng hơn thứ khác.
6. Hướng dẫn "phòng hờ" (just-in-case) không áp dụng cho phần lớn trường hợp. Câu "please double check... since false positives waste engineers' time" là một caveat hợp lý nhưng được diễn giải dài dòng, có thể rút về một dòng ngắn.
7. Output format không có cấu trúc rõ ràng. Phần "Output Format Instructions" mô tả bằng lời cách trình bày review, nhưng không đưa ra một template cụ thể. Kết quả: agent phải "đoán" format mỗi lần, dẫn đến output không nhất quán giữa các lần chạy — một vấn đề chất lượng, không chỉ vấn đề token.
8. Nội dung hoàn toàn không cần cho tác vụ. Phần "Reminder About Our Values" là một đoạn văn hóa doanh nghiệp, không chứa bất kỳ chỉ dẫn hành vi cụ thể nào cho việc review code. Đây là ứng viên bị cắt 100%.
Mẹo
Một cách audit nhanh: copy từng đoạn trong system prompt, tự hỏi "nếu xóa câu này, output của agent có thay đổi theo cách đo lường được không?". Nếu câu trả lời là "không" hoặc "chỉ ảnh hưởng đến tông giọng", đó là ứng viên bị cắt hoặc rút gọn. Áp dụng câu hỏi này cho cả 847 token trên, bạn sẽ thấy phần lớn không sống sót qua bài kiểm tra.
Phase 2: Optimization — Rewriting the Configuration
Nguyên tắc viết lại: tối đa mật độ chỉ dẫn, cấu trúc rõ ràng (heading, list, table khi hợp lý), loại bỏ mọi thứ không đổi hành vi output. Không phải "viết ngắn hơn" một cách máy móc — mà là giữ lại đúng thông tin cần cho quyết định, trình bày sao cho model parse nhanh nhất.
## Role
Review pull requests for a Python/FastAPI + TypeScript/React codebase.
Focus: bugs, security, missing tests, readability. Skip style issues
already enforced by linters (PEP 8, ESLint).
## Checklist (in priority order)
1. Correctness — logic errors, unhandled edge cases, wrong assumptions.
2. Security — SQL injection (raw SQL via string concat/f-string),
hardcoded secrets/keys, missing auth checks on new endpoints,
unescaped user input rendered on frontend (XSS).
3. Tests — flag non-trivial changes with no test coverage; flag tests
that assert trivial/no meaningful behavior.
4. Readability — functions doing >1 thing, unclear naming, code a
teammate couldn't understand in 6 months.
## Severity
- BLOCKER: security issue, data loss risk, broken core logic.
- WARNING: missing tests, unhandled edge case, unclear code.
- NIT: minor readability suggestion.
## Output format
### Review Summary
<1-2 sentence verdict: ready to merge / needs changes / blocker(s) found>
### Findings
- [SEVERITY] file:line — issue — suggested fix
## Rules
- One comment per issue, cite file:line.
- No comment without a concrete fix suggestion.
- Do not repeat linter-enforced style rules.
- If no issues found in a checklist category, omit it — do not state
"no issues found" for every category.
Vượt xa mục tiêu 50% ban đầu. Điểm mấu chốt không phải là cắt câu chữ ngẫu nhiên, mà là: gộp "How To Review Code" + "Testing Requirements" + "Security Rules" + "Code Style Standards" thành một checklist có thứ tự ưu tiên; biến "Output Format Instructions" mơ hồ thành một template cụ thể có thể copy-paste; và xóa hoàn toàn hai phần không mang thông tin hành động ("About This Agent", "Reminder About Our Values"). Phần "Our Tech Stack Details" cũng bị rút xuống một dòng duy nhất trong "Role" — chỉ giữ lại thông tin thật sự ảnh hưởng đến cách review (ngôn ngữ, framework), bỏ mọi chi tiết về hệ thống legacy hay tooling không liên quan.
Mẹo
Viết template output format dưới dạng ví dụ cụ thể (như ### Review Summary ở trên) luôn hiệu quả hơn mô tả bằng lời. Model bắt chước cấu trúc ví dụ tốt hơn nhiều so với việc "hiểu" một đoạn văn giải thích cách trình bày — đây cũng là lý do structured context format (bài 03) luôn thắng free-text khi cần output nhất quán.
Phase 3: Quality Validation
Giảm 70.7% token là vô nghĩa nếu chất lượng review giảm theo. Đây là bước dễ bị bỏ qua nhất trong thực tế — nhiều team tối ưu prompt rồi deploy thẳng, chỉ phát hiện chất lượng giảm khi đã có bug lọt qua review trong production. Cách làm đúng: xây một bộ golden test case — tập hợp các PR mẫu có "đáp án" đã biết (issue nào bắt buộc phải được phát hiện) — rồi chạy cả hai phiên bản config qua bộ này trước khi thay thế bản cũ.
"""
Golden test suite for the Code Review Agent system prompt.
Each case is a real (anonymized) PR diff paired with the set of findings
a competent human reviewer would flag. Used to validate that a prompt
rewrite does not regress detection quality.
"""
GOLDEN_TEST_CASES = [
{
"name": "sql_injection_via_fstring",
"diff": '''
def get_user_by_email(email):
query = f"SELECT * FROM users WHERE email = '{email}'"
return db.execute(query)
''',
"must_flag": ["sql_injection"],
"severity": "BLOCKER",
},
{
"name": "missing_auth_on_new_endpoint",
"diff": '''
@app.post("/admin/refund")
async def refund(order_id: str):
return process_refund(order_id)
''',
"must_flag": ["missing_auth_check"],
"severity": "BLOCKER",
},
{
"name": "hardcoded_api_key",
"diff": '''
STRIPE_KEY = "sk_live_51H8x..."
''',
"must_flag": ["hardcoded_secret"],
"severity": "BLOCKER",
},
{
"name": "non_trivial_change_no_tests",
"diff": '''
def calculate_discount(price, tier):
if tier == "gold":
return price * 0.8
if tier == "platinum":
return price * 0.7
return price
''',
"must_flag": ["missing_tests"],
"severity": "WARNING",
},
{
"name": "clean_pr_no_issues",
"diff": '''
def format_currency(cents: int) -> str:
return f"${cents / 100:.2f}"
''',
"must_flag": [],
"severity": None,
},
]
def run_agent(system_prompt: str, diff: str) -> list[str]:
"""Call the model with the given system prompt + diff, return a list
of normalized finding tags (e.g. 'sql_injection', 'missing_tests')
parsed from the review output. Implementation calls the LLM API and
a lightweight tag extractor — omitted here for brevity."""
...
def score_configuration(system_prompt: str, label: str) -> dict:
results = {"label": label, "recall": [], "blocker_misses": []}
for case in GOLDEN_TEST_CASES:
found = set(run_agent(system_prompt, case["diff"]))
expected = set(case["must_flag"])
hit = expected.issubset(found)
results["recall"].append(hit)
if not hit and case["severity"] == "BLOCKER":
results["blocker_misses"].append(case["name"])
recall_rate = sum(results["recall"]) / len(results["recall"])
print(f"[{label}] recall: {recall_rate:.0%}, "
f"blocker misses: {results['blocker_misses']}")
return results
original_results = score_configuration(ORIGINAL_SYSTEM_PROMPT, "original")
optimized_results = score_configuration(OPTIMIZED_SYSTEM_PROMPT, "optimized")
assert not optimized_results["blocker_misses"], (
"Optimized prompt missed a BLOCKER-severity issue — do not ship."
)
assert optimized_results["recall"].count(True) >= original_results["recall"].count(True), (
"Optimized prompt has lower recall than the original — investigate before shipping."
)
Hai assertion cuối chính là "cổng chất lượng" (quality gate): tuyệt đối không đánh đổi issue nhóm BLOCKER, và recall tổng thể của bản tối ưu không được thấp hơn bản gốc. Nếu golden test fail, quay lại Phase 2 — có thể một quy tắc bạn cắt bỏ ("chi tiết tech stack") thật ra ảnh hưởng đến một case cụ thể mà bạn chưa lường tới.
Mẹo
Xây bộ golden test case từ issue thật đã từng lọt qua review trong quá khứ, không phải case tự nghĩ ra. Đây là cách rẻ nhất để biến "kinh nghiệm đau" của team thành một bài kiểm tra tự động, đồng thời đảm bảo bạn không tối ưu prompt theo hướng lặp lại đúng lỗi cũ.
Phase 4: Implementing the Layering Architecture
248 token cho "trường hợp điển hình" là tốt, nhưng không phải mọi PR đều điển hình. Một PR đụng vào authentication hay một PR migrate database cần thêm ngữ cảnh chuyên sâu mà bạn không muốn nhồi vào mọi lượt gọi. Đây chính là lúc áp dụng context layering strategy đã học ở bài 05: tách config thành static layer (luôn nạp), dynamic layer (nạp theo điều kiện của PR) và on-demand layer (chỉ nạp khi có tín hiệu rõ ràng cần).
"""
Assembles the system prompt for the Code Review Agent from layered
context blocks, so that token cost scales with what a given PR actually
needs instead of a fixed worst-case size.
"""
STATIC_LAYER = """
## Role
Review pull requests for a Python/FastAPI + TypeScript/React codebase.
Focus: bugs, security, missing tests, readability. Skip style issues
already enforced by linters.
## Checklist (priority order)
1. Correctness 2. Security 3. Tests 4. Readability
## Severity
BLOCKER / WARNING / NIT
## Output format
### Review Summary
<verdict>
### Findings
- [SEVERITY] file:line — issue — suggested fix
""" # ~180 tokens, present in every call
DYNAMIC_LAYERS = {
"python": "Python specifics: check async/await misuse, "
"SQLAlchemy session leaks, mutable default arguments.",
"typescript": "TypeScript/React specifics: check missing dependency "
"arrays in useEffect, unstable object/array props, "
"any TypeScript `any` used to bypass type errors.",
"go": "Go specifics: check unchecked errors, goroutine leaks, "
"missing context cancellation.",
}
ON_DEMAND_LAYERS = {
"security_deep_dive": (
"Security deep dive (this PR touches auth/payment code): "
"verify authorization checks match the resource owner, not just "
"authentication; check for timing attacks in comparison logic; "
"check for privilege escalation via role/ID parameters."
),
"migration_checklist": (
"Schema migration checklist: verify migration is reversible, "
"does not lock large tables without a maintenance window, and "
"has a corresponding rollback script."
),
}
class ContextAssembler:
def assemble(self, pr_metadata: dict) -> str:
parts = [STATIC_LAYER]
primary_language = pr_metadata.get("primary_language")
if primary_language in DYNAMIC_LAYERS:
parts.append(DYNAMIC_LAYERS[primary_language])
if pr_metadata.get("touches_auth_or_payment"):
parts.append(ON_DEMAND_LAYERS["security_deep_dive"])
if pr_metadata.get("touches_schema_migration"):
parts.append(ON_DEMAND_LAYERS["migration_checklist"])
return "\n\n".join(parts)
def estimate_tokens(self, text: str) -> int:
return len(text) // 4 # quick heuristic, not an exact tokenizer
typical_pr = {"primary_language": "python", "touches_auth_or_payment": False,
"touches_schema_migration": False}
sensitive_pr = {"primary_language": "python", "touches_auth_or_payment": True,
"touches_schema_migration": False}
assembler = ContextAssembler()
print(assembler.estimate_tokens(assembler.assemble(typical_pr))) # ~248
print(assembler.estimate_tokens(assembler.assemble(sensitive_pr))) # ~330
Kết quả: PR "điển hình" vẫn chỉ trả khoảng 248 token như Phase 2, nhưng PR động vào payment/auth tự động được cấp thêm ngữ cảnh chuyên sâu — điều mà bản gốc 847 token cũng không làm tốt hơn, vì phần "Security Rules" của bản gốc là chỉ dẫn chung, không có chiều sâu tương đương "security deep dive" ở đây. Layering không chỉ tiết kiệm token cho trường hợp thường — nó còn cho phép bạn "chi tiêu" nhiều token hơn một cách có chọn lọc đúng chỗ cần, nâng chất lượng review cho những PR rủi ro cao nhất.
Mẹo
Điều kiện kích hoạt on-demand layer nên dựa trên tín hiệu khách quan, dễ tính toán từ metadata của PR (đường dẫn file, tên bảng trong migration, nhãn/tag của PR) — không nên dựa vào việc agent "tự đánh giá" xem PR có nhạy cảm hay không, vì bước tự đánh giá đó lại tốn thêm một lượt gọi và có thể sai.
Phase 5: Measuring the Full Optimization Impact
Con số "70.7% token reduction" thuyết phục trên slide, nhưng thứ thuyết phục người ra quyết định ngân sách là số tiền cụ thể ở quy mô thật. Bước cuối: dựng một báo cáo so sánh baseline và optimized trên khối lượng gọi thực tế của team.
"""
Compares the cost of the original vs. optimized Code Review Agent
configuration at a realistic call volume, using Claude Sonnet pricing.
"""
INPUT_PRICE_PER_MILLION_TOKENS = 3.00 # USD, Claude Sonnet, input tokens
baseline_tokens_per_call = 847
optimized_tokens_per_call = 248
CALLS_PER_MONTH = 1_000
baseline_total_tokens = baseline_tokens_per_call * CALLS_PER_MONTH
optimized_total_tokens = optimized_tokens_per_call * CALLS_PER_MONTH
tokens_saved = baseline_total_tokens - optimized_total_tokens
baseline_cost = baseline_total_tokens / 1_000_000 * INPUT_PRICE_PER_MILLION_TOKENS
optimized_cost = optimized_total_tokens / 1_000_000 * INPUT_PRICE_PER_MILLION_TOKENS
cost_saved = baseline_cost - optimized_cost
print(f"Baseline: {baseline_total_tokens:,} tokens/month -> ${baseline_cost:.2f}")
print(f"Optimized: {optimized_total_tokens:,} tokens/month -> ${optimized_cost:.2f}")
print(f"Saved: {tokens_saved:,} tokens/month -> ${cost_saved:.2f} "
f"({cost_saved / baseline_cost:.1%})")
Nhìn con số $1.80/tháng, phản ứng đầu tiên hợp lý là "quá nhỏ để bận tâm". Nhưng đọc kỹ hơn thì sẽ thấy vài điều quan trọng bị ẩn sau con số nhỏ đó:
- Đây chỉ là chi phí phần system prompt, chưa tính diff code thực tế được gửi kèm mỗi lần gọi (có thể vài nghìn token mỗi PR) và output token. 599.000 token tiết kiệm mỗi tháng là chi phí cố định lặp lại ở mọi lượt gọi, không phụ thuộc PR to hay nhỏ — nó cộng dồn tuyến tính và không có điểm bão hòa.
- 1.000 lượt gọi/tháng là quy mô một team nhỏ. Ở quy mô tổ chức (nhiều team, nhiều repo, agent chạy trên mọi commit chứ không chỉ PR), con số này nhân lên nhanh. Ở 100.000 lượt gọi/tháng, mức tiết kiệm tương tự là $180/tháng chỉ riêng cho một agent.
- Agent này không phải agent duy nhất trong tổ chức. Nếu một tổ chức có 10-20 agent nội bộ (review code, trả lời support, phân tích data...) và mỗi agent đều có mức bloat tương tự, tổng tiết kiệm cộng gộp mới là con số thật sự đáng nhìn vào ngân sách.
- Lợi ích không chỉ là tiền. Giảm 599 token nghĩa là còn nhiều "chỗ trống" hơn trong context window cho diff code thực tế trước khi chạm ngưỡng model bắt đầu suy giảm khả năng chú ý ("lost in the middle" — hiện tượng model bỏ sót thông tin ở giữa context dài). Với PR lớn, đây có thể là yếu tố quyết định việc agent có bắt được bug hay không, quan trọng hơn cả khoản tiền tiết kiệm.
Mẹo
Khi trình bày kết quả tối ưu cho stakeholder không phải kỹ thuật (PM, quản lý), luôn đi kèm hai loại số: số tuyệt đối ở quy mô hiện tại (để họ thấy đúng là nhỏ, tránh mất uy tín vì thổi phồng) và số ngoại suy ở quy mô tăng trưởng dự kiến (để họ thấy giá trị tích lũy theo thời gian). Trình bày một mình con số nhỏ dễ bị đánh giá "không đáng làm"; trình bày một mình con số ngoại suy dễ bị nghi ngờ là phóng đại.
Applying This Methodology to Other Agent Types
Toàn bộ 5 phase bạn vừa làm với Code Review Agent là một playbook lặp lại được cho bất kỳ agent nào có system prompt hoặc context configuration:
- Audit — đọc từng đoạn, hỏi "xóa câu này thì output thay đổi đo lường được không?". Tìm văn phong hoa mỹ, lặp quy tắc, thông tin "để cho đầy đủ", nhấn nhá quá mức.
- Rewrite — chuyển văn xuôi thành checklist/template có cấu trúc, gộp các quy tắc trùng lặp, xóa nội dung không đổi hành vi, viết output format bằng ví dụ cụ thể thay vì mô tả bằng lời.
- Validate — dựng golden test case từ case thật (đặc biệt case đã từng gây sự cố), đảm bảo recall không giảm và không đánh đổi case nghiêm trọng.
- Layer — tách static (luôn cần) / dynamic (cần theo điều kiện phổ biến) / on-demand (cần theo tín hiệu hiếm, rõ ràng).
- Measure — tính tác động ở quy mô gọi thực tế, cả token/tiền và cả lợi ích chất lượng/latency, trình bày cả số hiện tại và số ngoại suy.
Áp dụng cụ thể cho vài loại agent khác thường gặp trong vòng đời phát triển phần mềm:
- Support agent (agent trả lời khách hàng): static layer là giọng điệu thương hiệu và quy tắc leo thang (escalation) chung; dynamic layer là chính sách theo từng sản phẩm/gói dịch vụ khách hàng đang dùng; on-demand layer là lịch sử ticket của khách đó hoặc runbook xử lý sự cố hiếm gặp — chỉ nạp khi phát hiện từ khóa liên quan trong câu hỏi.
- QA agent (agent viết/review test case): static layer là chuẩn viết test chung của team (naming, cấu trúc Arrange-Act-Assert); dynamic layer là đặc thù framework test theo từng repo (pytest vs Jest vs Playwright); on-demand layer là lịch sử flaky test hoặc bug đã từng xảy ra ở khu vực code đang được test.
- Data-analysis agent (agent phân tích dữ liệu): static layer là nguyên tắc phân tích chung (không suy diễn quá mức từ mẫu nhỏ, luôn nêu rõ giả định); dynamic layer là schema của dataset đang phân tích; on-demand layer là tài liệu phương pháp thống kê chuyên sâu — chỉ nạp khi câu hỏi đòi hỏi kỹ thuật cụ thể (A/B testing, time series...).
Điểm chung: dù loại agent nào, chi phí bloat luôn nằm ở cùng những chỗ — văn phong dư thừa, thông tin "để chắc ăn", thiếu cấu trúc output, và một khối context tĩnh cố nạp mọi thứ cho mọi trường hợp. Một khi bạn đã tự tay làm qua đủ 5 phase với một agent thật như bài này, bạn sẽ nhận ra bloat gần như ngay khi đọc lướt qua bất kỳ system prompt nào khác — đó là kỹ năng quan trọng nhất bạn mang ra khỏi module này, quan trọng hơn cả con số 50% trong tiêu đề bài học.
Mẹo
Đừng chờ đến khi context configuration "quá to mới đáng audit". Đưa 5 phase này vào quy trình review định kỳ (ví dụ mỗi quý, hoặc mỗi khi thêm một đoạn instruction mới vào system prompt) — bloat tích lũy dần từng chút một, giống hệt cách nó hình thành trong ví dụ Code Review Agent ở đầu bài, và luôn dễ ngăn hơn là dọn.