Kỹ thuật đồ thị: Cách chạy 1.000 AI Agent song song từ một câu lệnh duy nhất

@0xWast3
TIẾNG ANH1 ngày trước · 22 thg 7, 2026
146K
151
19
13
376

TL;DR

Một bài phân tích chuyên sâu về kỹ thuật đồ thị dành cho AI agent, minh họa cách xác định các phụ thuộc thực tế và sử dụng cơ chế thực thi song song để mở rộng quy mô quy trình làm việc.

Mọi người đang xây dựng hệ thống đa tác tử vào năm 2026 vẫn viết theo đường thẳng. Bước một, rồi bước hai, rồi bước ba - mỗi bước chờ bước trước. Đây là lý do tại sao nó chậm, và cách khắc phục.

wast3 - inline image

Vấn đề không ai kiểm tra

Bạn đã xây dựng một tác tử đa bước. Nó hoạt động. Nhưng nó cũng chậm.

Bạn cho rằng mô hình là nút thắt cổ chai. Không phải vậy.

Nút thắt cổ chai chính là hình dạng bạn đã vẽ. Một chuỗi - bước 1 chờ bước 2, bước 2 chờ bước 3 - buộc thực thi tuần tự ngay cả khi một nửa số bước đó chẳng liên quan gì đến nhau.

"Tóm tắt tài liệu này, sau đó kiểm tra thời tiết" là hai công việc độc lập đội lốt một quy trình làm việc. Tác vụ thời tiết không cần bản tóm tắt. Nó chưa bao giờ cần. Nhưng nếu bạn viết nó như một chuỗi, nó vẫn phải chờ.

Sự chờ đợi lãng phí đó, nhân lên qua hàng tá bước, là nơi mà phần lớn thời gian chạy của bạn biến mất.

Chương 1 - Vòng lặp so với đồ thị

Một vòng lặp là một đơn vị tự cải thiện:

text
1thử một cái gì đó → kiểm tra kết quả → điều chỉnh → thử lại

Đó là nguyên tử. Một tác tử, một số liệu, lặp cho đến khi hội tụ.

Vòng lặp có một chế độ thất bại đã biết: chúng tối ưu hóa chính xác những gì bạn đo lường và không gì khác. Một bot hỗ trợ được tinh chỉnh để đóng ticket nhanh sẽ đóng ticket nhanh - trong khi sự hài lòng lặng lẽ giảm mạnh. Vòng lặp không thể nhìn thấy bên ngoài số liệu của chính nó. Đó là Định luật Goodhart hiện ra trong kiến trúc tác tử của bạn.

Một đồ thị khắc phục điều này bằng thiết kế. Thay vì một vòng lặp theo đuổi một con số, bạn xây dựng một mạng lưới các vòng lặp theo dõi và sửa chữa lẫn nhau. Đầu ra của Nút A cung cấp cho Nút B. Nút C chạy độc lập và kiểm tra cả hai. Không có một số liệu đơn lẻ nào điều khiển toàn bộ hệ thống - cấu trúc mới làm điều đó.

wast3 - inline image

Đối với hệ thống tác tử, điều này có nghĩa là một sự thay đổi cụ thể: dừng viết một tác tử làm mọi thứ từ trên xuống dưới. Hãy thiết kế hình dạng của công việc trước - cái gì phải xảy ra trước cái gì, cái gì có thể chạy cùng lúc, cái gì thực sự cần chờ đợi.

Chương 2 - Nút, cạnh và bài kiểm tra phân tách chúng

Một đồ thị có đúng hai thành phần:

Nút - một đơn vị công việc. Một tác tử, một công việc, một đầu vào, một đầu ra.

Cạnh - một phụ thuộc thực sự. Đầu vào của Nút B yêu cầu đầu ra của Nút A.

Sai lầm hầu như ai cũng mắc phải: coi "và sau đó" như một cạnh theo mặc định.

text
1"Đọc cơ sở mã này và sau đó viết nhật ký thay đổi"
2"Lấy trang giá và sau đó tóm tắt tính năng của đối thủ cạnh tranh"

Hãy đặt một câu hỏi cho mỗi "và sau đó" trong quy trình làm việc của bạn:

Bước tiếp theo có thực sự đọc đầu ra của bước trước không?

Nếu có → cạnh thực sự. Giữ nguyên thứ tự tuần tự.

Nếu không → không có cạnh. Sự chờ đợi là lãng phí. Chạy chúng song song.

Nếu không có dữ liệu nào đi qua ranh giới giữa hai tác vụ, chúng độc lập — và mọi cặp độc lập bạn đang chạy tuần tự là thời gian chạy bạn đang vứt đi một cách miễn phí.

Đây là bài kiểm tra được áp dụng trong mã:

python
1from dataclasses import dataclass
2
3@dataclass
4class TaskNode:
5 id: str
6 prompt: str
7 depends_on: list[str] # ID của các nút mà nút này thực sự cần
8
9def has_real_edge(node_a: TaskNode, node_b: TaskNode) -> bool:
10 """
11 Bài kiểm tra kỹ thuật đồ thị cốt lõi:
12 liệu prompt của node_b có thực sự yêu cầu đầu ra của node_a không?
13 """
14 return node_a.id in node_b.depends_on
15
16# Ví dụ: hầu hết các "chuỗi" sụp đổ thành 2-3 nhóm phụ thuộc thực sự
17nodes = [
18 TaskNode("audit_routes", "Liệt kê tất cả các file route API", []),
19 TaskNode("check_auth", "Kiểm tra phạm vi bao phủ của middleware xác thực", []),
20 TaskNode("fetch_weather", "Lấy thời tiết hôm nay", []),
21 TaskNode("summarize", "Tóm tắt kết quả route + xác thực",
22 depends_on=["audit_routes", "check_auth"]),
23]
24
25# audit_routes, check_auth, fetch_weather KHÔNG có cạnh giữa chúng
26# Chúng chạy song song. Chỉ "summarize" có cạnh thực sự -- nó chờ đợi.

Tác tử "làm A, sau đó B, sau đó C" hiện tại của bạn về mặt kỹ thuật đã là một đồ thị. Nó chỉ là đồ thị tồi tệ nhất có thể - một chuỗi đơn lẻ mà nếu C bị đình trệ, không có gì ở phía sau chạy tiếp.

Chương 3 - Xây dựng đồ thị đầu tiên của bạn

wast3 - inline image

Yêu cầu:

  • Claude Code (phiên bản gần đây hỗ trợ Dynamic Workflows).
  • Gói Max, Team hoặc Enterprise - workflows được bật theo mặc định. Trên Pro, bật thủ công.

Mở một kho lưu trữ thực tế. Không phải ví dụ đồ chơi - lợi ích chỉ xuất hiện ở quy mô thực tế.

Prompt khởi động đồ thị đầu tiên của bạn:

text
1Tạo một workflow để kiểm tra mọi file route trong cơ sở mã này.
2
3Đối với mỗi file route, hãy kiểm tra độc lập:
4- middleware xác thực có mặt
5- xác thực đầu vào trên tất cả các tham số
6- rate limiting được cấu hình
7- xử lý lỗi không làm rò rỉ stack traces
8
9Chạy các kiểm tra này song song trên tất cả các file route —
10chúng không phụ thuộc lẫn nhau.
11
12Sau khi tất cả các file được kiểm tra, tạo một báo cáo tổng hợp
13duy nhất được phân nhóm theo mức độ nghiêm trọng: critical, warning, info.
14
15Bước tổng hợp nên chờ tất cả các kiểm tra hoàn thành.
16Mọi thứ trước bước đó thì không nên chờ.

Hãy chú ý cấu trúc được nhúng trong chính prompt: công việc song song được gọi ra một cách rõ ràng, một phụ thuộc thực sự duy nhất (tổng hợp chờ tất cả các kiểm tra) được đặt tên rõ ràng. Bạn không hy vọng tác tử suy ra đồ thị - bạn đang mô tả nó.

Điều gì xảy ra bên dưới mui xe - một phiên bản đơn giản hóa của sự phối hợp:

python
1import asyncio
2from anthropic import Anthropic
3
4client = Anthropic()
5
6async def audit_route_file(filepath: str) -> dict:
7 """Một nút. Chạy độc lập với mọi file route khác."""
8 response = await client.messages.create(
9 model="claude-sonnet-5",
10 max_tokens=1000,
11 messages=[{
12 "role": "user",
13 "content": f"""Kiểm tra file route này cho:
14 - auth middleware, xác thực đầu vào,
15 rate limiting, xử lý lỗi
16
17 File: {filepath}
18
19 Trả về JSON: {{"file": "", "issues": [], "severity": ""}}"""
20 }]
21 )
22 return {"file": filepath, "result": response.content[0].text}
23
24async def consolidate(results: list[dict]) -> str:
25 """Một cạnh thực sự duy nhất -- chờ mọi nút kiểm tra kết thúc."""
26 response = await client.messages.create(
27 model="claude-opus-4-8",
28 max_tokens=2000,
29 messages=[{
30 "role": "user",
31 "content": f"""Tổng hợp {len(results)} bản kiểm tra route này
32 thành một báo cáo duy nhất được phân nhóm theo mức độ nghiêm trọng:
33
34 {results}"""
35 }]
36 )
37 return response.content[0].text
38
39async def run_graph(route_files: list[str]):
40 # Phân tán -- tất cả các nút độc lập chạy đồng thời
41 audit_tasks = [audit_route_file(f) for f in route_files]
42 results = await asyncio.gather(*audit_tasks)
43
44 # Tập trung -- nút duy nhất có phụ thuộc thực sự
45 report = await consolidate(results)
46 return report
47
48# 40 file route, một prompt, một lượt song song
49results = asyncio.run(run_graph([
50 f"routes/{f}.py" for f in ["auth", "users", "billing", "orders"]
51 # ...thêm 36 file nữa

40 lần gọi API tuần tự ở ~8 giây mỗi lần là hơn 5 phút. Cùng 40 lần gọi được phân tán song song: dưới 15 giây, bị giới hạn bởi file đơn lẻ chậm nhất của bạn, không phải tổng của tất cả chúng.

Chương 4 - Nơi đồ thị thực sự hỏng

Kỹ thuật đồ thị thất bại ở ba nơi có thể dự đoán trước. Hãy biết chúng trước khi bạn gặp phải.

Sụp đổ ngữ cảnh. Phân tán 1.000 nút và cố gắng đưa tất cả 1.000 đầu ra vào một bước tổng hợp, và bạn sẽ vượt quá bất kỳ cửa sổ ngữ cảnh nào trước khi quá trình tổng hợp bắt đầu.

Khắc phục: Phân lớp quá trình tập trung của bạn. Nhóm các nút thành các lô 20-50, tóm tắt từng lô, sau đó tổng hợp các bản tóm tắt - không phải đầu ra thô.

python
1async def layered_consolidate(results: list[dict], batch_size: int = 30):
2 """Tập trung theo lớp -- không bao giờ tổng hợp đầu ra thô ở quy mô lớn."""
3 batches = [results[i:i+batch_size]
4 for i in range(0, len(results), batch_size)]
5
6 batch_summaries = await asyncio.gather(*[
7 summarize_batch(batch) for batch in batches
8 ])
9
10 # Tổng hợp cuối cùng hoạt động trên các bản tóm tắt, không phải 1.000 kết quả thô
11 return await consolidate(batch_summaries)

Độc lập giả. Bạn sẽ cho rằng hai nút độc lập vì prompt của chúng không tham chiếu lẫn nhau - nhưng cả hai đều ghi vào cùng một file, hoặc truy cập cùng một API bị giới hạn tốc độ. Đó là một cạnh ẩn. Khắc phục: kiểm tra các tài nguyên được chia sẻ, không chỉ dữ liệu được chia sẻ. Hai nút có xung đột ghi cần một cạnh ngay cả khi không có phụ thuộc dữ liệu nào.

Lỗi nút im lặng. Trong một chuỗi, một lỗi dừng mọi thứ - gây khó chịu nhưng rõ ràng. Trong một đồ thị, một nút bị lỗi trong số 200 có thể biến mất vào một báo cáo trông có vẻ hoàn chỉnh. Khắc phục: mỗi bước tập trung kiểm tra số lượng nút so với số lượng dự kiến trước khi tổng hợp, và gắn cờ các khoảng trống một cách rõ ràng thay vì lặng lẽ làm việc với dữ liệu một phần.

python
1async def safe_consolidate(results: list[dict], expected_count: int):
2 if len(results) < expected_count:
3 missing = expected_count - len(results)
4 print(f"WARNING: {missing} nodes failed silently. "
5 f"Report will be incomplete.")
6 return await consolidate(results)

Chương 5 - Mở rộng quy mô lên một đội quân thực sự

wast3 - inline image

Khi mẫu hoạt động ở 40 nút, mở rộng quy mô lên hàng trăm chỉ là một thay đổi cấu hình, không phải thiết kế lại - miễn là bạn đã xây dựng đồ thị đúng cách từ Chương 2 trở đi.

Hình dạng sản xuất đầy đủ:

text
1 Orchestrator
2 |
3 +--------+-------+-------+--------+
4 v v v v v
5 Node 1 Node 2 Node 3 ... Node N
6 (song song, không có cạnh giữa bất kỳ nút nào)
7 | | | |
8 +--------+-------+-------+-------+
9 v
10 Batch Summary <- tập trung phân lớp
11 (nhóm 30 nút)
12 v
13 Final Report <- cạnh thực sự duy nhất

Công việc duy nhất của orchestrator: phân rã tác vụ thành các nút, xác định các cạnh thực sự, và điều phối. Nó không tự làm công việc nào - nó vẽ đồ thị.

python
1async def orchestrate(task: str, resources: list[str]):
2 """
3 Nút điều phối -- phân rã, không thực thi.
4 """
5 plan = await client.messages.create(
6 model="claude-opus-4-8",
7 max_tokens=2000,
8 messages=[{
9 "role": "user",
10 "content": f"""Tác vụ: {task}
11 Tài nguyên có sẵn: {resources}
12
13 Phân rã thành một đồ thị:
14 - Liệt kê mỗi nút độc lập (không có cạnh chung)
15 - Liệt kê bất kỳ phụ thuộc thực sự nào giữa các nút
16 - Nhóm các nút thành các lô tập trung nếu số lượng > 50
17
18 Trả về JSON với: nodes, edges, batch_groups"""
19 }]
20 )
21
22 graph = parse_plan(plan.content[0].text)
23
24 # Thực thi các nút độc lập song song
25 node_results = await asyncio.gather(*[
26 execute_node(n) for n in graph["nodes"] if not n["depends_on"]
27 ])
28
29 # Sau đó thực thi các nút phụ thuộc, chỉ tôn trọng các cạnh thực sự
30 final = await execute_dependent_chain(graph["edges"], node_results)
31
32 return final

Đây là sự thay đổi thực sự mà kỹ thuật đồ thị mang lại: bạn không còn là người viết mọi bước, mà trở thành người thiết kế cấu trúc phụ thuộc. Các tác tử điền vào các nút. Bạn sở hữu các cạnh.

Điều gì thay đổi khi bạn suy nghĩ theo đồ thị thay vì đường thẳng

Một tác tử tuyến tính với 40 bước có 40 điểm lỗi tuần tự và độ trễ gấp 40 lần bước đơn lẻ chậm nhất của nó.

Một đồ thị với cùng 40 đơn vị công việc có số điểm lỗi song song bằng số phụ thuộc thực sự bạn có - thường là 3 đến 5 trong hầu hết các quy trình làm việc - và độ trễ bị giới hạn bởi lớp chậm nhất của bạn, không phải tổng số bước.

Đó không phải là một sự tăng tốc nhỏ. Đó là sự khác biệt giữa một quy trình làm việc mất 5 phút và một quy trình mất 15 giây, chạy cùng một công việc cơ bản.

Mô hình chưa bao giờ là nút thắt cổ chai. Đường thẳng bạn đã vẽ mới là.

Đây là một phân tích kỹ thuật về các mẫu phối hợp đa tác tử tính đến tháng 7 năm 2026. Các ví dụ mã chỉ mang tính minh họa - hãy điều chỉnh xử lý lỗi, giới hạn tốc độ và logic thử lại cho phù hợp với môi trường sản xuất của bạn trước khi triển khai ở quy mô lớn.

Cảm ơn bạn đã đọc.

Viết lại trong YouMind

Turn one viral article into a full content workflow

Collect the source, decode the pattern, create assets, draft the story, and distribute from one AI workspace.

Explore YouMind
Dành cho nhà sáng tạo

Biến Markdown của bạn thành bài viết 𝕏 gọn gàng

Khi bạn đăng bài viết dài của riêng mình, việc định dạng hình ảnh, bảng và khối mã cho 𝕏 rất mệt mỏi. YouMind biến cả bản nháp Markdown thành một bài viết 𝕏 gọn gàng, sẵn sàng để đăng.

Thử Markdown sang 𝕏

Thêm pattern để giải mã

Bài viết viral gần đây

Khám phá thêm bài viết viral