ghi chú làm việc · MiniGate · 2026-11-05

Quy trình làm việc với agent: tool, flow, đối tượng và chỗ người phải đứng

Tổng hợp buổi trao đổi về cách tối ưu công cụ test / debug qua CLI từ hiện trạng MiniGate để tái dùng cho dự án sau, và cách tổ chức quy trình để chủ dự án bớt phải quản lý trực tiếp.

Nguồn số liệu: mgctl, cpctl, wsctl, deskctl, minigate, rt trên server test, ngày 2026-11-05. Kết luận là đề xuất, chưa phải quyết định.

00Câu hỏi gốc

Đang có nhiều CLI cho agent (mgctl, cpctl, wsctl, deskctl, minigate, rt) và nhiều flow test khai báo. Muốn tối ưu lại để tái dùng cho dự án sau. Chuỗi câu hỏi đã đi qua:

  1. Cách đưa tool cho AI qua CLI và định nghĩa flow có phải hướng đi hợp lý so với cộng đồng không?
  2. Ngoài tool, các đối tượng khác (env, role, flow, step, fixture, report…) tổ chức thế nào?
  3. Các đối tượng đó định nghĩa ở đâu, có cần structure không?
  4. Có nên sửa tool ngay trong lúc test / debug sản phẩm không?
  5. Người nên tham gia ở bước nào?
  6. Quy trình của cả dự án nên chia pha ra sao: nháp trước rồi lặp hồi quy đến khi khách ổn?

01Hiện trạng tóm tắt

Có 6 CLI và 4 “engine flow” khác nhau cùng một ý tưởng (flow JSON gồm steps, params, expect, shot, dùng testenv) nhưng mỗi cái tự viết schema và runner riêng. Code dùng chung bị chép tay giữa repo: find-common.js giống hệt ở 3 repo, schema.js giống ở desktop và mobile, util.js mỗi repo một bản, testenv.js và mgctl.js lệch dần.

deskctl flowminigate flowwsctl e2emgctl flow
Đối tượngElectron (CDP)Android / iOS (adb, xcrun)Web (Chrome)API + gọi CLI khác
Bước phổ biếnexpect 704 · shot 331 · wait 299 · use 180 · type 146run 583 (chuỗi lệnh con) · expect 534eval 473 (JS thô) · shot 367 · click 362 · sleep 325args 75 · as 66 · expect 63 · save 16
Chỉ phần tử#chat.row.c3 hoặc css=…chat-thread.pinned-bar (có *)CSS trong eval / clickkhông (API)
Bước tái dùnguse + steps/*.jsonkhônguse + steps/*.jsonflow con + cli
Vai tròtestEnvroles A/B + {{testEnv.user}}role (1 lần)as + needs theo testenv
Điều kiện / lặpkhôngkhôngkhôngwhen
ChờtimeoutMs 281 · sleep 27timeoutMs 459sleep 325 · wait 228không cần
  • wsctl e2e đã rò rỉ ra JS. 473 bước eval và 325 sleep nghĩa là DSL không đủ diễn đạt, người viết nhảy xuống code và chờ cứng.
  • minigate flow thực chất là shell script dạng JSON. Tốt cho agent (mỗi bước chạy tay được) nhưng không có lớp step nên 281 lần input tap dính thẳng vào testid.
  • mgctl flow là lớp khác hẳn. Không chạm UI, chỉ điều phối vai trò, params, flow con, gọi CLI khác, lưu kết quả. Đây là lớp đáng giữ nhất.

Phần làm tốt và nên giữ: config + .local.json, testenv theo vai trò, mgctl api đăng nhập như app, bộ data + .runs báo cáo, doctor, quy ước testid module.screen.element dùng chung desktop và mobile.

02Hướng đi có hợp lý so với cộng đồng?

Có. “CLI cho AI + flow khai báo + testenv theo vai trò + bằng chứng mỗi lần chạy” là dòng chính 2025–2026.

  • CLI thay vì tool-call / MCP. Anthropic (bài “code execution with MCP”) và OpenAI Codex đều chỉ ra: agent gọi lệnh rồi tự đọc output tiết kiệm token và dễ ghép hơn nạp hàng chục tool definition. Vercel ra agent-browser dạng CLI vì lý do này.
  • Test như dữ liệu. Maestro (mobile) dùng YAML flow: tapOn, assertVisible, runFlow con. Cấu trúc flow JSON của MiniGate gần như song song.
  • Progressive disclosure cho agent. help ngắn, _doc trong config, skill, doctor: đã có.
  • Evidence và reproducibility. Bộ data + .runs khớp xu hướng.

Chỗ cộng đồng làm khác

  1. Tránh DSL tự chế khi đã có sẵn. Maestro, Playwright, WebdriverIO có format ổn định, agent biết sẵn cú pháp. DSL riêng nên mỏng: giữ lớp nghiệp vụ, uỷ lớp tương tác cho engine chuẩn. Bốn runner tự viết là đi hơi xa.
  2. Một lệnh một việc, in JSON. --json, stdout là kết quả, stderr là log, exit code có nghĩa, không hỏi khi không có TTY. mgctl đã theo, rt (menu + xác nhận) thì chưa.
  3. Test chính tool. Ai test runner? Mobile có 2 file test, còn lại không.
  4. Flaky là bài toán chính. Auto-wait, retry, trace là nơi Maestro / Playwright đầu tư nhiều nhất và DSL riêng phải tự gánh.

03Flow riêng so với Maestro và Playwright

Nhu cầuHiện tại (3 runner UI)Maestro (mobile, YAML)Playwright (web / Electron)Nhận xét
Tìm phần tửtestid, mỗi runner một cú phápid, text, regex, indexgetByTestId / Role / Textengine ngoài có 4–5 cách, ta chỉ có testid
Auto-waitkhông, dùng timeoutMs / sleepcócóchỗ ta tốn công nhất, họ cho sẵn
Assertexpect + text / contains / visible / gone / attr / countassertVisible, assertNotVisible, assertTrue20+ matcherđủ dùng nhưng tự bảo trì
Flow conuse + stepsrunFlow + envhàm / fixturengang nhau
Vai trò, testenvmạnhchỉ envstorageState theo tài khoảnta mạnh hơn, đây là lớp nghiệp vụ
Điều kiện, lặpkhôngrunFlow when, repeatJS đầy đủthiếu, nên có 4 flow na ná (chat-hai-nguoi-0/1/2/3)
Ảnh, trace, reportshot + .runs + Telegramscreenshot, record, JUnit / HTMLtrace viewer, HTML report, videotrace viewer là thứ ta không có
Hai máy / hai vaimobile có roles A/Bkhôngnhiều context trong 1 testPlaywright hơn, Maestro kém ta
Agent biết sẵn cú pháp?không, đọc help mỗi phiêncócóchi phí ẩn của DSL riêng
ElectronCDP tự viết (page.js 363 dòng)khônghỗ trợ chính thứcthay hẳn được lớp CDP
Android / iOSadb / xcrun tự viếthỗ trợ chính thứckhôngthay được lớp input / expect
Giấy phépcủa taApache-2.0Apache-2.0dùng thương mại được

Giữ gì, uỷ gì

Giữ (lớp nghiệp vụ, không ai có): testenv theo vai trò, as / needs, tài khoản bảo vệ, tiền tố [E2E] và dọn dữ liệu; mgctl flow làm bộ điều phối; lệnh đơn cho agent (api, shot, inspect, doctor); quy ước testid.

Uỷ cho engine ngoài (lớp tương tác): web và Electron → Playwright, bước UI dịch 1:1 hoặc bước playwright: <spec> để mgctl flow gọi rồi thu report. Mobile → Maestro cho input / expect, giữ app, shot, net, biometric, notif, log của minigate; hai máy thì mgctl flow điều phối 2 Maestro.

Cái giá: thêm 2 dependency lớn (Playwright kéo browser, Maestro cần Java), agent học 2 cú pháp, dịch lại flow hiện có (desktop ~40, mobile 28, ws vài chục). Đổi lại bỏ được 3 runner tự viết, có auto-wait và trace viewer, dự án sau chỉ mang theo lớp nghiệp vụ mỏng.

Phương án giữa: giữ DSL nhưng chuẩn hoá một schema step chung cho 3 runner UI, thêm auto-wait vào expect để bỏ sleep, đưa when / repeat xuống. Rẻ hơn nhưng vẫn tự nuôi engine.

Khuyến nghị: chọn uỷ, bắt đầu từ wsctl e2e vì rò rỉ nặng nhất và Playwright thay được trọn vẹn.

04Các đối tượng ngoài tool

Tool là động từ, các đối tượng là danh từ, và danh từ quyết định tái sử dụng được hay không. Xếp theo hai trục: thuộc về ai (mọi dự án, một dự án, một repo, một máy, một lần chạy) và đổi nhanh hay chậm.

Đối tượngNghĩaThuộc vềĐổiNằm ởCommit
Quy ướctestid, exit code, stdout/stderr, tên vai trò, [E2E]mọi dự ánrất chậmkit, 1 trangcó
Config lệnhtham số không bí mật của toolrepochậmconfig/<lệnh>.json + _doccó
Override máyghi đè riêng máymáytuỳ*.local.jsonkhông
Môi trườngserver + workspace + URL + vai trò dùng biến nàodự ánchậmcommon config/test-env.jsoncó
Bí mậtmật khẩu, token theo môi trườngdự ánhiếmsecrets/test-env/<env>.envrepo private
Vai tròadmin, chat1, works-staff2, mobile…dự ánchậmmột bảng duy nhất, cùng file envcó
Hồ sơChrome profile, emulator, máy thậtmáytrung bìnhconfig/profiles + localmột phần
Fixturedữ liệu mẫu bất biếnrepochậmfixtures/ cạnh flowcó
Bướcthao tác UI đặt tên: chat.send, auth.loginrepotrung bìnhsteps/<module>.jsoncó
Flowkịch bản nghiệp vụrepo (UI) / common (liên repo)nhanhflows/<module>/<tên>.jsoncó
Bộ datatham số một đợt chạytác vụmỗi đợtwork/<ngày>/<tác vụ>/không
Bằng chứngảnh, log, report.jsonlần chạymỗi lần<bộ data>/.runs/<id>/không
Tri thức agentskill, help, README thư mụcrepochậm.claude/skills, help/có
Hợp đồng APIOpenAPIrepo backendtrung bìnhopenapi/có

Nguyên tắc đặt chỗ: càng chung và càng chậm đổi thì càng lên cao (kit → common → repo); càng riêng và càng nhanh đổi thì càng ra ngoài repo (local → work → .runs).

Quan hệ giữa các đối tượng

flow ──needs──▶ role ──resolve qua──▶ env ──đọc──▶ secret
 │                                      │
 ├──use──▶ step ──dùng──▶ testid (quy ước)
 ├──with──▶ fixture
 ├──chạy trên──▶ profile (máy)
 └──nhận──▶ dataset ──sinh ra──▶ run / evidence
  • Flow không chứa URL, tài khoản, đường dẫn máy. Chỉ tên vai trò và tên fixture.
  • Step là nơi duy nhất biết testid. UI đổi testid thì sửa một chỗ.
  • Dataset tách khỏi flow để một flow chạy nhiều đợt, mỗi đợt có .runs riêng.

Quyết định tổ chức cụ thể

  • Một bảng vai trò cho toàn hệ thống; mobile cần 2 máy thì ánh xạ A → chat1, B → chat2.
  • Đặt tên flow theo module/hành-vi, không theo thiết bị. 4 flow chat-hai-nguoi-0..3 nên là 1 flow mgctl gọi 4 bước trên 2 vai.
  • Tag (smoke, that, quyen, hoi-quy) thay cho hậu tố tên file.
  • Fixture bất biến; thứ flow tạo ra mang [E2E] {run.id} và có bước dọn.
  • Mỗi run ra một report.json cùng schema dù bước chạy bằng engine nào.
  • Mỗi thư mục flows / steps / fixtures có README ngắn; skill chỉ trỏ tới, không chép.

05Định nghĩa ở đâu, có schema không

Schema tập trung trong kit, nội dung phân tán theo chủ sở hữu; có structure cho mọi thứ máy đọc, không cần cho thứ chỉ người và agent đọc.

TầngChứa gìỞ đâuAi sửa
Kitschema từng đối tượng, quy ước, runner lõi, template thư mụcrepo riêng (mg-cli-kit), có versionhiếm, có review
Dự áninstance env, role, profile, flow liên repo, contract, secretsrepo common của dự ánngười vận hành
Repostep, flow UI, fixture, config lệnh, tri thức agent<repo>/cli/dev của app
Ngoài repolocal override, dataset, run*.local.json, work/, .runs/máy, lần chạy

Hiện đã có tầng 2, 3, 4. Thiếu tầng 1: schema đang nằm trong repo app nên mỗi repo một bản. Đưa schema lên kit là thay đổi cấu trúc duy nhất cần làm. Mỗi file instance khai "$schema", runner validate lúc load.

Đối tượngStructureMức chặtLý do
Env, RoleJSON Schemachặt6 CLI cùng đọc
ReportJSON Schema, có versionchặtđiểm nối giữa mọi engine và consumer
Flow, StepJSON Schemachặt ở khung, mở ở bước (oneOf theo driver, x-*)bước UI khác theo driver
Config lệnhschema cạnh configvừanhư rt đang làm
ProfileJSON Schemavừatrộn local nên cần biết field hợp lệ
Fixturechỉ manifestlỏngnội dung tuỳ nghiệp vụ; manifest ghi giấy phép ảnh / font
Datasetsinh từ params của flowtự độngkhông viết tay
Tri thức agentkhôngtự doép schema chỉ gây phiền
Quy ướcvăn bảntự donhưng mỗi quy ước có một check trong doctor
  • Schema phải có version và lệnh migrate, nếu không kit đóng băng.
  • Mở rộng có kiểm soát: additionalProperties:false ở khung, cho phép x-<repo>-* hoặc with tự do trong bước.
  • Kit là repo riêng, không phải thư mục trong common, vì common chứa secrets và dữ liệu MiniGate.
mg-cli-kit/                      # tầng kit
  schemas/ env · role · flow · step · report · profile · config
  conventions.md
  template/                      # mgctl init-cli sinh từ đây

common_minigate/                 # tầng dự án
  config/test-env.json  config/profiles/  flows/<module>/  secrets/test-env/

<repo>/cli/                      # tầng repo
  steps/<module>.json  flows/<module>/*.json  fixtures/ + fixtures.json  config/<lệnh>.json

work/<ngày>/<tác vụ>/            # ngoài repo
  env.json  params.json  .runs/<id>/report.json

06Sửa tool trong lúc test / debug sản phẩm

Nên, nhưng phân tầng. Nhu cầu thật về tool chỉ lộ ra khi đang test; cấm sửa là tự bịt nguồn phát hiện. Hai rủi ro cần chặn: nhiễm kết quả (pass vì sản phẩm đúng hay vì tool vừa đổi cách đo; agent có xu hướng nới expect, tăng timeout, thêm sleep) và trôi thiết kế (mỗi lần kẹt thêm một ngoại lệ).

TầngSửa trong lúc test?Điều kiện
Step, flow, fixtureCó, tự docommit riêng, tách khỏi commit sửa sản phẩm
Lệnh / flag mới CLI repoCó, tối thiểughi gap, có help, chạy lại flow từ sạch
Runner lõi, schema, quy ướcKhông sửa tại chỗghi gap kèm ví dụ, gom sửa theo đợt, nâng version kit

Ba kỷ luật

  1. Tách commit và tách run. Sửa tool xong chạy lại từ sạch; report có field toolVersion.
  2. Sửa tool chỉ được chặt hơn hoặc rộng hơn, không lỏng hơn. Nới ngưỡng, bỏ assert, thêm sleep là che lỗi; ghi gap thay vì sửa. Đưa vào skill / CLAUDE.md cho agent.
  3. Mỗi lệnh sửa có một check đi kèm trong doctor hoặc test của CLI.

Nhịp: trong sprint sửa tầng 1 thoải mái, tầng 2 khi kẹt, tầng 3 chỉ ghi gap. Cuối đợt đọc gaps, gom cái lặp từ 2 repo trở lên lên kit. Test / debug là nơi phát hiện nhu cầu tool, không phải nơi thiết kế tool.

07Người đứng ở đâu

Người ở chỗ đặt ý định và chỗ phán xét; agent ở chỗ thực thi và thu thập. Bốn cổng người bắt buộc đứng, mọi chỗ khác agent tự chạy:

1 · Cổng ý định

Người viết goal cho flow và chọn tag nào là nghiệm thu. Không có cổng này agent test cái dễ đo thay vì cái quan trọng.

2 · Cổng phán xét

Người đọc report tóm tắt và quyết fail thuộc loại nào: lỗi sản phẩm, lỗi tool, flaky. Chỉ người được kết luận.

3 · Cổng dữ liệu thật và bí mật

Người cấp env / secret, duyệt flow chạy trên workspace có người thật, bảo vệ tài khoản.

4 · Cổng thay đổi kit

Người review theo đợt mọi thay đổi schema, runner lõi, quy ước.

BướcNgườiAgent
Quy ước, schema kitquyết định, reviewđề xuất kèm ví dụ từ gaps
Env, role, secretsđịnh nghĩa, cấpchỉ dùng
Mục tiêu flowviết 1–2 câu goaldịch thành steps, expect, fixture
Viết step, flow, fixturexem lần đầu khi là tiêu chí nghiệm thuviết, chạy thử, sửa
Chạy, thu bằng chứngkhôngchạy, sinh report
Phân loại failphán xétđề xuất kèm bằng chứng
Sửa tool tầng repokhôngsửa tối thiểu, ghi gap
Gom gaps lên kitđọc, chọn, bỏgom, nhóm, nháp
Flow dữ liệu thậtduyệt trước, xem ảnh sauchạy, dọn [E2E]
Deploy, releaseconfirmchuẩn bị, chạy sau confirm
  • Người xem ở mức tóm tắt. Phải mở từng ảnh hoặc đọc log thô là tool chưa đạt. Mục tiêu: vài phút cho một đợt vài chục flow.
  • Sự tham gia giảm dần theo độ chín. Flow mới xem kỹ lần đầu xanh, sau chỉ xem khi fail. Tool mới review lúc lên kit, sau tin doctor.

08Quy trình một tính năng (hoặc một request)

#BướcNgườiAgentĐầu raTool
1Ý địnhgoal, vai trò, cái không được xảy ra, tiêu chíhỏi lại chỗ mơ hồ, nháp danh sách flow nghiệm thurequest có goal + danh sách flowrt req new
2Hợp đồngduyệt specOpenAPI, sinh type, mockspec + typemgctl contract
3Flow trước codexem flow lần đầuviết flow từ goal, phải đỏ đúng chỗflow + fixture + datasetflow init, testenv
4Làmkhông, trừ khi blockcode theo spec, chạy test + flow, commit tách tool / sản phẩmcommit Refs, pushprocess-requests
5Nghiệm thuđọc report, phán xét fail, duyệt dữ liệu thậtchạy flow theo tag, sinh report, đề xuất phân loạireport.json + ảnh, Telegrammgctl flow run
6Phát hànhconfirmdeploy, smoke sau deploy, release, thông báotag, versions.json, report smokemgctl deploy / release
7Gom (theo đợt)đọc gaps, chọngom gaps, nháp kit, dọn flow trùngkit version mới, bộ hồi quygaps, doctor
  • Bước 3 trước bước 4 là thay đổi lớn nhất: tiêu chí nghiệm thu được máy hoá trước khi code.
  • Bước 2 cho phép song song backend và client trên spec + mock.
  • Người chỉ xuất hiện ở 1, 3 (lần đầu), 5, 6, 7.
  • Ba điểm ép: không có goal và danh sách flow thì không vào bước 4; report là đầu vào duy nhất cho deploy; flow đã dùng nghiệm thu tự thành hồi quy.
  • Sửa lỗi nhỏ: 1 (mô tả + cách tái hiện) → 3 (một flow tái hiện, phải đỏ) → 4 → 5.

09Quy trình cả dự án

“Nháp → hồi quy → fix → lặp đến khi khách ổn” về cơ bản đúng, với agent càng đúng vì code nháp rẻ. Ba chỗ hay vỡ: “khách thấy ổn” không phải điều kiện dừng; nháp bị khoá thành kiến trúc (rủi ro lớn nhất khi dùng agent); hồi quy phình không kiểm soát. Giữ vòng lặp nhưng đặt vào 5 pha có điều kiện ra.

0

Nền (1–2 tuần)

kit, testenv, quy ước, testid, pipeline report. Làm thật vì mọi pha sau dựa vào.

Ra khi doctor xanh, một flow mẫu chạy được trên cả 3 nền tảng.

1

Nháp rộng

Khách thấy toàn bộ hình hài càng sớm càng tốt. Nháp có chủ đích: mock data, UI trước, backend giả (như mock/* của mobile). Nháp không gọi API thật, không migration, không flow hoi-quy.

Ra khi khách chốt phạm vi và luồng chính; đầu ra là danh sách flow nghiệm thu theo module.

2

Làm thật theo module

Mỗi module đi qua contract → flow đỏ → code → report xanh. Nháp của module được thay, không fix dần.

Ra khi flow nghiệm thu của module xanh và khách duyệt module đó.

3

Ổn định (2–3 vòng, mỗi vòng ~1 tuần)

Hồi quy → fix → hồi quy trên dữ liệu gần thật. Chỉ sửa, không thêm; yêu cầu mới vào backlog vòng sau.

Ra khi bộ hồi quy xanh N lần liên tiếp và khách ký nghiệm thu theo danh sách flow. Quá 3 vòng thì nguyên nhân thường ở pha 1 chốt chưa đủ.

4

Vận hành

Release, smoke sau deploy, gaps theo đợt. Hồi quy có ngân sách: smoke vài phút mỗi deploy, hoi-quy đầy đủ cuối ngày hoặc trước release, flow flaky gắn cach-ly và vào gaps.

liên tục

  • Khách tham gia hai lần với hai câu hỏi khác nhau: pha 1 “đây có phải thứ anh muốn không”, pha 3 “đây có chạy đúng như đã chốt không”. Trộn hai câu là lý do vòng lặp không kết thúc.
  • Pha 0 và 1 khoảng 20% thời gian, pha 2 là phần lớn.

10Việc còn mở để nghĩ tiếp

Mục tiêu đã nêu: tối ưu quy trình làm việc nhóm để chủ dự án không phải tham gia quản lý nhiều. Những quyết định còn chờ:

  1. DSL flow dừng ở lớp nào? Uỷ hẳn lớp tương tác cho Playwright / Maestro, hay phương án giữa (chuẩn hoá schema step, thêm auto-wait)? Bắt đầu từ wsctl e2e.
  2. Flow JSON thuần hay cho phép JS? Đề xuất JSON thuần, logic ở driver.
  3. Kit là repo riêng? Đề xuất có, common là consumer đầu tiên.
  4. Schema report.json là gì, đủ để người đọc vài phút một đợt? Đây là điểm nối cho mọi thứ còn lại, nên làm sớm.
  5. Ai giữ cổng nào khi nhóm lớn hơn một người: cổng ý định và phán xét có thể giao cho PO / QA, cổng dữ liệu thật và kit nên giữ ở người vận hành.
  6. Thứ tự chuyển: deskctl → minigate → wsctl e2e (theo độ gần với mgctl flow), hay wsctl e2e trước (theo mức rò rỉ)?
  7. Kiểm kê bước 1: bảng lệnh nào thuộc lõi hay dự án, trùng ở đâu, để quyết phạm vi kit trước khi thiết kế API.

Điều rút ra lớn nhất: phần mang sang dự án mới là quy ước, schema của env / role / flow / step / report, cấu trúc thư mục và bốn cổng người đứng. Phần ở lại là nội dung của các file đó. Ranh giới tái sử dụng đi theo loại đối tượng, không theo repo.