Testing
OpenClaw có ba bộ test Vitest (unit/integration, e2e, live) và một số Docker runners.
Tài liệu này là hướng dẫn “cách mình test”:
- Mỗi test suite bao gồm những gì (và những gì nó cố ý không bao gồm)
- Lệnh nào cần chạy cho các workflow phổ biến (local, pre-push, debugging)
- Cách live tests tìm credentials và chọn models/providers
- Cách thêm regressions cho các vấn đề model/provider thực tế
Quick start
Hầu hết các ngày:
- Full gate (cần chạy trước khi push):
pnpm build && pnpm check && pnpm test
Khi các bạn sửa tests hoặc muốn thêm độ tin cậy:
- Coverage gate:
pnpm test:coverage - E2E suite:
pnpm test:e2e
Khi debug các providers/models thực (cần credentials thật):
- Live suite (models + gateway tool/image probes):
pnpm test:live
Tip: khi các bạn chỉ cần một test case bị lỗi, nên thu hẹp live tests qua các biến môi trường allowlist được mô tả bên dưới.
Test suites (chạy cái gì ở đâu)
Hãy nghĩ về các suites như “tăng dần tính thực tế” (và tăng dần flakiness/chi phí):
Unit / integration (mặc định)
- Lệnh:
pnpm test - Config:
vitest.config.ts - Files:
src/**/*.test.ts - Phạm vi:
- Pure unit tests
- In-process integration tests (gateway auth, routing, tooling, parsing, config)
- Deterministic regressions cho các bugs đã biết
- Kỳ vọng:
- Chạy trong CI
- Không cần keys thật
- Nên nhanh và ổn định
E2E (gateway smoke)
- Lệnh:
pnpm test:e2e - Config:
vitest.e2e.config.ts - Files:
src/**/*.e2e.test.ts - Phạm vi:
- Multi-instance gateway end-to-end behavior
- WebSocket/HTTP surfaces, node pairing, và networking nặng hơn
- Kỳ vọng:
- Chạy trong CI (khi được bật trong pipeline)
- Không cần keys thật
- Nhiều phần chuyển động hơn unit tests (có thể chậm hơn)
Live (real providers + real models)
- Lệnh:
pnpm test:live - Config:
vitest.live.config.ts - Files:
src/**/*.live.test.ts - Mặc định: enabled bởi
pnpm test:live(đặtOPENCLAW_LIVE_TEST=1) - Phạm vi:
- “Provider/model này có thực sự hoạt động hôm nay với credentials thật không?”
- Bắt các thay đổi format của provider, quirks tool-calling, vấn đề auth, và hành vi rate limit
- Kỳ vọng:
- Không ổn định trong CI theo thiết kế (mạng thật, chính sách provider thật, quotas, outages)
- Tốn tiền / sử dụng rate limits
- Nên chạy các tập con thu hẹp thay vì “mọi thứ”
- Live runs sẽ source
~/.profileđể lấy các API keys còn thiếu - Anthropic key rotation: đặt
OPENCLAW_LIVE_ANTHROPIC_KEYS="sk-...,sk-..."(hoặcOPENCLAW_LIVE_ANTHROPIC_KEY=sk-...) hoặc nhiều biếnANTHROPIC_API_KEY*; tests sẽ retry khi gặp rate limits
Nên chạy suite nào?
Dùng bảng quyết định này:
- Sửa logic/tests: chạy
pnpm test(vàpnpm test:coveragenếu các bạn thay đổi nhiều) - Sửa gateway networking / WS protocol / pairing: thêm
pnpm test:e2e - Debug “bot của mình bị down” / lỗi provider-specific / tool calling: chạy
pnpm test:livethu hẹp
Live: model smoke (profile keys)
Live tests được chia thành hai layers để mình có thể cô lập các lỗi:
- “Direct model” cho mình biết provider/model có thể trả lời được không với key đã cho.
- “Gateway smoke” cho mình biết toàn bộ pipeline gateway+agent hoạt động cho model đó (sessions, history, tools, sandbox policy, v.v.).
Layer 1: Direct model completion (không có gateway)
- Test:
src/agents/models.profiles.live.test.ts - Mục tiêu:
- Liệt kê các models đã phát hiện
- Dùng
getApiKeyForModelđể chọn models các bạn có credentials - Chạy một completion nhỏ cho mỗi model (và các regressions có mục tiêu khi cần)
- Cách bật:
pnpm test:live(hoặcOPENCLAW_LIVE_TEST=1nếu gọi Vitest trực tiếp)
- Đặt
OPENCLAW_LIVE_MODELS=modern(hoặcall, alias cho modern) để thực sự chạy suite này; nếu không nó sẽ skip để giữpnpm test:livetập trung vào gateway smoke - Cách chọn models:
OPENCLAW_LIVE_MODELS=modernđể chạy modern allowlist (Opus/Sonnet/Haiku 4.5, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.1, Grok 4)OPENCLAW_LIVE_MODELS=alllà alias cho modern allowlist- hoặc
OPENCLAW_LIVE_MODELS="openai/gpt-5.2,anthropic/claude-opus-4-5,..."(comma allowlist)
- Cách chọn providers:
OPENCLAW_LIVE_PROVIDERS="google,google-antigravity,google-gemini-cli"(comma allowlist)
- Keys đến từ đâu:
- Mặc định: profile store và env fallbacks
- Đặt
OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1để bắt buộc chỉ profile store
- Tại sao cái này tồn tại:
- Tách biệt “provider API bị hỏng / key không hợp lệ” khỏi “gateway agent pipeline bị hỏng”
- Chứa các regressions nhỏ, cô lập (ví dụ: OpenAI Responses/Codex Responses reasoning replay + tool-call flows)
Layer 2: Gateway + dev agent smoke (những gì “@openclaw” thực sự làm)
- Test:
src/gateway/gateway-models.profiles.live.test.ts - Mục tiêu:
- Khởi động một in-process gateway
- Tạo/patch một
agent:dev:*session (model override mỗi lần chạy) - Lặp qua models-with-keys và assert:
- Response “có ý nghĩa” (không có tools)
- Một tool invocation thật hoạt động (read probe)
- Các tool probes bổ sung tùy chọn (exec+read probe)
- Các đường dẫn regression OpenAI (tool-call-only → follow-up) tiếp tục hoạt động
- Chi tiết Probe (để các bạn có thể giải thích lỗi nhanh):
readprobe: test ghi một nonce file trong workspace và yêu cầu agentreadnó và echo nonce trả lại.exec+readprobe: test yêu cầu agentexec-write một nonce vào temp file, sau đóreadnó trả lại.- image probe: test đính kèm một PNG được tạo (cat + randomized code) và mong đợi model trả về
cat <CODE>. - Tham khảo implementation:
src/gateway/gateway-models.profiles.live.test.tsvàsrc/gateway/live-image-probe.ts.
- Cách bật:
pnpm test:live(hoặcOPENCLAW_LIVE_TEST=1nếu gọi Vitest trực tiếp)
- Cách chọn models:
- Mặc định: modern allowlist (Opus/Sonnet/Haiku 4.5, GPT-5.x + Codex, Gemini 3, GLM 4.7, MiniMax M2.1, Grok 4)
OPENCLAW_LIVE_GATEWAY_MODELS=alllà alias cho modern allowlist- Hoặc đặt
OPENCLAW_LIVE_GATEWAY_MODELS="provider/model"(hoặc comma list) để thu hẹp
- Cách chọn providers (tránh “OpenRouter everything”):
OPENCLAW_LIVE_GATEWAY_PROVIDERS="google,google-antigravity,google-gemini-cli,openai,anthropic,zai,minimax"(comma allowlist)
- Tool + image probes luôn bật trong live test này:
readprobe +exec+readprobe (tool stress)- image probe chạy khi model quảng cáo hỗ trợ image input
- Flow (high level):
- Test tạo một PNG nhỏ với “CAT” + random code (
src/gateway/live-image-probe.ts) - Gửi nó qua
agentattachments: [{ mimeType: "image/png", content: "<base64>" }] - Gateway parse attachments thành
images[](src/gateway/server-methods/agent.ts+src/gateway/chat-attachments.ts) - Embedded agent forwards một multimodal user message đến model
- Assertion: reply chứa
cat+ code (OCR tolerance: cho phép sai sót nhỏ)
- Test tạo một PNG nhỏ với “CAT” + random code (
Tip: để xem các bạn có thể test gì trên máy của mình (và các provider/model ids chính xác), chạy:
openclaw models list
openclaw models list --json
Live: Anthropic setup-token smoke
- Test:
src/agents/anthropic.setup-token.live.test.ts - Mục tiêu: xác minh Claude Code CLI setup-token (hoặc một pasted setup-token profile) có thể hoàn thành một Anthropic prompt.
- Bật:
pnpm test:live(hoặcOPENCLAW_LIVE_TEST=1nếu gọi Vitest trực tiếp)OPENCLAW_LIVE_SETUP_TOKEN=1
- Token sources (chọn một):
- Profile:
OPENCLAW_LIVE_SETUP_TOKEN_PROFILE=anthropic:setup-token-test - Raw token:
OPENCLAW_LIVE_SETUP_TOKEN_VALUE=sk-ant-oat01-...
- Profile:
- Model override (tùy chọn):
OPENCLAW_LIVE_SETUP_TOKEN_MODEL=anthropic/claude-opus-4-5
Ví dụ setup:
openclaw models auth paste-token --provider anthropic --profile-id anthropic:setup-token-test
OPENCLAW_LIVE_SETUP_TOKEN=1 OPENCLAW_LIVE_SETUP_TOKEN_PROFILE=anthropic:setup-token-test pnpm test:live src/agents/anthropic.setup-token.live.test.ts
Live: CLI backend smoke (Claude Code CLI hoặc các local CLIs khác)
- Test:
src/gateway/gateway-cli-backend.live.test.ts - Mục tiêu: validate Gateway + agent pipeline sử dụng local CLI backend, mà không chạm vào config mặc định của các bạn.
- Bật:
pnpm test:live(hoặcOPENCLAW_LIVE_TEST=1nếu gọi Vitest trực tiếp)OPENCLAW_LIVE_CLI_BACKEND=1
- Mặc định:
- Model:
claude-cli/claude-sonnet-4-5 - Command:
claude - Args:
["-p","--output-format","json","--dangerously-skip-permissions"]
- Model:
- Overrides (tùy chọn):
OPENCLAW_LIVE_CLI_BACKEND_MODEL="claude-cli/claude-opus-4-5"OPENCLAW_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.2-codex"OPENCLAW_LIVE_CLI_BACKEND_COMMAND="/full/path/to/claude"OPENCLAW_LIVE_CLI_BACKEND_ARGS='["-p","--output-format","json","--permission-mode","bypassPermissions"]'OPENCLAW_LIVE_CLI_BACKEND_CLEAR_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE=1để gửi một real image attachment (paths được inject vào prompt).OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="--image"để truyền image file paths dưới dạng CLI args thay vì prompt injection.OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="repeat"(hoặc"list") để kiểm soát cách image args được truyền khiIMAGE_ARGđược đặt.OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE=1để gửi turn thứ hai và validate resume flow.
OPENCLAW_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG=0để giữ Claude Code CLI MCP config enabled (mặc định disable MCP config với một temporary empty file).
Ví dụ:
OPENCLAW_LIVE_CLI_BACKEND=1 \
OPENCLAW_LIVE_CLI_BACKEND_MODEL="claude-cli/claude-sonnet-4-5" \
pnpm test:live src/gateway/gateway-cli-backend.live.test.ts
Recommended live recipes
Các allowlists thu hẹp, rõ ràng là nhanh nhất và ít flaky nhất:
-
Single model, direct (không có gateway):
OPENCLAW_LIVE_MODELS="openai/gpt-5.2" pnpm test:live src/agents/models.profiles.live.test.ts
-
Single model, gateway smoke:
OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
-
Tool calling across several providers:
OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2,anthropic/claude-opus-4-5,google/gemini-3-flash-preview,zai/glm-4.7,minimax/minimax-m2.1" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
-
Google focus (Gemini API key + Antigravity):
- Gemini (API key):
OPENCLAW_LIVE_GATEWAY_MODELS="google/gemini-3-flash-preview" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts - Antigravity (OAuth):
OPENCLAW_LIVE_GATEWAY_MODELS="google-antigravity/claude-opus-4-5-thinking,google-antigravity/gemini-3-pro-high" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
- Gemini (API key):
Lưu ý:
google/...sử dụng Gemini API (API key).google-antigravity/...sử dụng Antigravity OAuth bridge (Cloud Code Assist-style agent endpoint).google-gemini-cli/...sử dụng local Gemini CLI trên máy các bạn (auth riêng + tooling quirks).- Gemini API vs Gemini CLI:
- API: OpenClaw gọi Google’s hosted Gemini API qua HTTP (API key / profile auth); đây là những gì hầu hết người dùng muốn nói khi nói “Gemini”.
- CLI: OpenClaw shells out đến một
geminibinary local; nó có auth riêng và có thể hoạt động khác (streaming/tool support/version skew).
Live: model matrix (những gì mình cover)
Không có “CI model list” cố định (live là opt-in), nhưng đây là các models được khuyến nghị để cover thường xuyên trên dev machine với keys.
Modern smoke set (tool calling + image)
Đây là “common models” run mình mong đợi sẽ tiếp tục hoạt động:
- OpenAI (non-Codex):
openai/gpt-5.2(tùy chọn:openai/gpt-5.1) - OpenAI Codex:
openai-codex/gpt-5.2(tùy chọn:openai-codex/gpt-5.2-codex) - Anthropic:
anthropic/claude-opus-4-5(hoặcanthropic/claude-sonnet-4-5) - Google (Gemini API):
google/gemini-3-pro-previewvàgoogle/gemini-3-flash-preview(tránh các Gemini 2.x models cũ hơn) - Google (Antigravity):
google-antigravity/claude-opus-4-5-thinkingvàgoogle-antigravity/gemini-3-flash - Z.AI (GLM):
zai/glm-4.7 - MiniMax:
minimax/minimax-m2.1
Chạy gateway smoke với tools + image:
OPENCLAW_LIVE_GATEWAY_MODELS="openai/gpt-5.2,openai-codex/gpt-5.2,anthropic/claude-opus-4-5,google/gemini-3-pro-preview,google/gemini-3-flash-preview,google-antigravity/claude-opus-4-5-thinking,google-antigravity/gemini-3-flash,zai/glm-4.7,minimax/minimax-m2.1" pnpm test:live src/gateway/gateway-models.profiles.live.test.ts
Baseline: tool calling (Read + optional Exec)
Chọn ít nhất một per provider family:
- OpenAI:
openai/gpt-5.2(hoặcopenai/gpt-5-mini) - Anthropic:
anthropic/claude-opus-4-5(hoặcanthropic/claude-sonnet-4-5) - Google:
google/gemini-3-flash-preview(hoặcgoogle/gemini-3-pro-preview) - Z.AI (GLM):
zai/glm-4.7 - MiniMax:
minimax/minimax-m2.1
Optional additional coverage (nice to have):
- xAI:
xai/grok-4(hoặc latest available) - Mistral:
mistral/… (chọn một “tools” capable model các bạn đã bật) - Cerebras:
cerebras/… (nếu các bạn có access) - LM Studio:
lmstudio/… (local; tool calling phụ thuộc vào API mode)
Vision: image send (attachment → multimodal message)
Bao gồm ít nhất một image-capable model trong OPENCLAW_LIVE_GATEWAY_MODELS (Claude/Gemini/OpenAI vision-capable variants, v.v.) để thực hiện image probe.
Aggregators / alternate gateways
Nếu các bạn có keys enabled, mình cũng hỗ trợ testing qua:
- OpenRouter:
openrouter/...(hàng trăm models; dùngopenclaw models scanđể tìm tool+image capable candidates) - OpenCode Zen:
opencode/...(auth quaOPENCODE_API_KEY/OPENCODE_ZEN_API_KEY)
Nhiều providers các bạn có thể bao gồm trong live matrix (nếu các bạn có creds/config):
- Built-in:
openai,openai-codex,anthropic,google,google-vertex,google-antigravity,google-gemini-cli,zai,openrouter,opencode,xai,groq,cerebras,mistral,github-copilot - Qua
models.providers(custom endpoints):minimax(cloud/API), cộng với bất kỳ OpenAI/Anthropic-compatible proxy nào (LM Studio, vLLM, LiteLLM, v.v.)
Tip: đừng cố hardcode “all models” trong docs. Danh sách authoritative là bất cứ thứ gì discoverModels(...) trả về trên máy các bạn + bất cứ keys nào available.
Credentials (không bao giờ commit)
Live tests phát hiện credentials theo cách giống như CLI làm. Ý nghĩa thực tế:
-
Nếu CLI hoạt động, live tests nên tìm thấy cùng các keys.
-
Nếu một live test nói “no creds”, debug theo cách các bạn sẽ debug
openclaw models list/ model selection. -
Profile store:
~/.openclaw/credentials/(ưu tiên; những gì “profile keys” có nghĩa trong tests) -
Config:
~/.openclaw/openclaw.json(hoặcOPENCLAW_CONFIG_PATH)
Nếu các bạn muốn dựa vào env keys (ví dụ: exported trong ~/.profile của các bạn), chạy local tests sau source ~/.profile, hoặc dùng Docker runners bên dưới (chúng có thể mount ~/.profile vào container).
Deepgram live (audio transcription)
- Test:
src/media-understanding/providers/deepgram/audio.live.test.ts - Bật:
DEEPGRAM_API_KEY=... DEEPGRAM_LIVE_TEST=1 pnpm test:live src/media-understanding/providers/deepgram/audio.live.test.ts
Docker runners (optional “works in Linux” checks)
Những cái này chạy pnpm test:live bên trong repo Docker image, mounting local config dir và workspace của các bạn (và sourcing ~/.profile nếu mounted):
- Direct models:
pnpm test:docker:live-models(script:scripts/test-live-models-docker.sh) - Gateway + dev agent:
pnpm test:docker:live-gateway(script:scripts/test-live-gateway-models-docker.sh) - Onboarding wizard (TTY, full scaffolding):
pnpm test:docker:onboard(script:scripts/e2e/onboard-docker.sh) - Gateway networking (two containers, WS auth + health):
pnpm test:docker:gateway-network(script:scripts/e2e/gateway-network-docker.sh) - Plugins (custom extension load + registry smoke):
pnpm test:docker:plugins(script:scripts/e2e/plugins-docker.sh)
Các biến môi trường hữu ích:
OPENCLAW_CONFIG_DIR=...(mặc định:~/.openclaw) mounted đến/home/node/.openclawOPENCLAW_WORKSPACE_DIR=...(mặc định:~/.openclaw/workspace) mounted đến/home/node/.openclaw/workspaceOPENCLAW_PROFILE_FILE=...(mặc định:~/.profile) mounted đến/home/node/.profilevà sourced trước khi chạy testsOPENCLAW_LIVE_GATEWAY_MODELS=.../OPENCLAW_LIVE_MODELS=...để thu hẹp runOPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1để đảm bảo creds đến từ profile store (không phải env)
Docs sanity
Chạy docs checks sau khi sửa doc: pnpm docs:list.
Offline regression (CI-safe)
Đây là các “real pipeline” regressions mà không có real providers:
- Gateway tool calling (mock OpenAI, real gateway + agent loop):
src/gateway/gateway.tool-calling.mock-openai.test.ts - Gateway wizard (WS
wizard.start/wizard.next, writes config + auth enforced):src/gateway/gateway.wizard.e2e.test.ts
Agent reliability evals (skills)
Mình đã có một vài CI-safe tests hoạt động như “agent reliability evals”:
- Mock tool-calling through the real gateway + agent loop (
src/gateway/gateway.tool-calling.mock-openai.test.ts). - End-to-end wizard flows validate session wiring và config effects (
src/gateway/gateway.wizard.e2e.test.ts).
Những gì vẫn còn thiếu cho skills (xem Skills):
- Decisioning: khi skills được liệt kê trong prompt, agent có chọn đúng skill không (hoặc tránh những cái không liên quan)?
- Compliance: agent có đọc
SKILL.mdtrước khi sử dụng và tuân theo các bước/args bắt buộc không? - Workflow contracts: các kịch bản multi-turn assert tool order, session history carryover, và sandbox boundaries.
Future evals nên giữ deterministic trước:
- Một scenario runner sử dụng mock providers để assert tool calls + order, skill file reads, và session wiring.
- Một suite nhỏ các kịch bản tập trung vào skill (use vs avoid, gating, prompt injection).
- Optional live evals (opt-in, env-gated) chỉ sau khi CI-safe suite đã có sẵn.
Adding regressions (hướng dẫn)
Khi các bạn fix một vấn đề provider/model được phát hiện trong live:
- Thêm một CI-safe regression nếu có thể (mock/stub provider, hoặc capture exact request-shape transformation)
- Nếu nó inherently live-only (rate limits, auth policies), giữ live test thu hẹp và opt-in qua env vars
- Ưu tiên targeting layer nhỏ nhất bắt được bug:
- provider request conversion/replay bug → direct models test
- gateway session/history/tool pipeline bug → gateway live smoke hoặc CI-safe gateway mock test