Bài 2 — Thiết lập môi trường và cấu trúc project
Agent chạy được trong demo nhưng vỡ trận khi lên production thường vì nền móng ẩu: khóa API rò rỉ, không quản version, không tách config. Bài này dựng nền chuẩn.
Các bước thiết lập
- Tạo virtual env để cô lập dependency:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install openai-agents anthropic python-dotenv
- Quản lý khóa bằng file
.env(KHÔNG commit lên git):
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
Thêm .env vào .gitignore ngay lập tức. Rò một khóa là mất tiền và mất uy tín.
- Nạp biến môi trường ở điểm khởi động:
from dotenv import load_dotenv
load_dotenv() # đọc .env vào os.environ
- Kiểm tra kết nối trước khi làm gì phức tạp:
import anthropic
client = anthropic.Anthropic()
msg = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=64,
messages=[{"role": "user", "content": "Nói xin chào"}],
)
print(msg.content[0].text)
Nếu dòng này chạy được, khóa và mạng OK. Nếu lỗi 401 → sai khóa; 429 → hết quota hoặc rate limit.
Cấu trúc project gợi ý
my-agent/
.env # khóa, không commit
.gitignore
config.py # đọc config, chọn model, timeout
tools/ # mỗi tool 1 file, dễ test
weather.py
crm.py
agents/ # định nghĩa các agent
triage.py
runtime.py # vòng lặp / Runner + logging
tests/ # test tool độc lập với model
Nguyên tắc vàng: tool phải test được mà không cần gọi model. Nếu get_weather chỉ chạy được khi có LLM, bạn đã trộn lẫn hai tầng.
Vì sao tách tool khỏi model lại đáng giá
Một agent thực chiến có thể có 5-15 tool. Nếu logic tool (gọi CRM, ghi DB, tính toán nghiệp vụ) trộn chung với logic gọi LLM, bạn rơi vào ba vấn đề: kiểm thử phải tốn token và chậm, lỗi khó khoanh vùng (do model hay do tool?), và không tái sử dụng được tool cho agent khác. Khi tách riêng, mỗi tool là một hàm Python thuần: input rõ ràng, output rõ ràng, test bằng pytest trong mili-giây, không phụ thuộc mạng. Bạn kiểm chứng tool đúng 100% trước, rồi mới ghép vào agent — lúc đó nếu agent trả lời sai, bạn biết chắc vấn đề nằm ở prompt/định nghĩa tool chứ không phải bug trong hàm.
# tools/weather.py — thuần Python, không dính LLM
def get_weather(city: str) -> str:
# gọi API thời tiết thật ở đây
return f"Thời tiết {city}: 30 độ, nắng"
# tests/test_weather.py
def test_get_weather():
assert "30 độ" in get_weather("Đà Nẵng")
config.py mẫu
import os
MODEL = os.getenv("AGENT_MODEL", "claude-sonnet-4-5")
MAX_TOKENS = int(os.getenv("AGENT_MAX_TOKENS", "1024"))
REQUEST_TIMEOUT = float(os.getenv("AGENT_TIMEOUT", "30"))
Đừng rải hằng số khắp code. Tập trung ở một chỗ để đổi model chỉ cần đổi 1 biến môi trường — cực kỳ hữu ích khi so sánh chi phí/chất lượng giữa các model. Trong thực chiến bạn sẽ thường xuyên A/B: chạy cùng bộ test với một model mạnh và một model rẻ, đo chênh lệch chất lượng và chi phí, rồi chọn model rẻ nhất mà vẫn đạt ngưỡng chất lượng. Config tập trung khiến việc so sánh này chỉ tốn vài giây thay vì phải sửa rải rác khắp code.
Checklist môi trường sẵn sàng
- [ ] Virtual env đã kích hoạt, package đã cài đúng phiên bản (ghi lại vào
requirements.txtbằngpip freeze). - [ ]
.envchứa khóa, đã vào.gitignore. - [ ] Ping thử cả OpenAI và Anthropic thành công.
- [ ] Có
config.pytập trung model/timeout/max_tokens. - [ ] Tool tách file riêng, có ít nhất 1 test chạy không cần model.
- [ ] Có logging in ra từng tool call (name + input + output rút gọn).
Sai lầm thường gặp
- Hard-code khóa trong code: sớm muộn cũng lộ. Luôn dùng biến môi trường.
- Commit
.env: kiểm tragit statustrước commit đầu tiên; nếu lỡ, phải rotate khóa ngay. - Không pin phiên bản package: SDK agent thay đổi nhanh; không
pip freezethì "máy tôi chạy được" là câu nói dối kinh điển. - Không đặt timeout: một request treo có thể khóa cả worker; luôn set timeout.
- Trộn logic tool với logic gọi model: khiến không viết được unit test cho tool.
- Không phân biệt lỗi 401 và 429: 401 là sai khóa (sửa cấu hình), 429 là hết quota/quá tải (chờ và thử lại) — xử lý khác nhau.