Courses
Giao một việc cho một tác nhân, nó làm ổn. Giao ba việc, rồi xem chuyện gì xảy ra ở lần bàn giao thứ hai: nó quên những gì đã tìm được ở bước một, chấm cao bản thảo của chính mình, và tuyên bố hoàn thành trong khi đầu ra vẫn còn dở dang.
Cuộc tranh luận quanh mô hình đó bùng nổ giữa tháng 7/2026, khi "graph engineering" xuất hiện trên X (trước đây là Twitter) và dòng thời gian ngay lập tức chia đôi: một bên tuyên bố vòng lặp tác nhân đã chết, bên kia gọi thuật ngữ này là mồi nhử trại nội dung.
Quan điểm của tôi là nhãn "graph engineering" có hay không tùy bạn, còn cách tiếp cận bên dưới thì không, và tôi sẽ cố gắng biện minh cho điều đó trước khi viết bất kỳ dòng mã nào.
Phần lớn những gì bạn xây trong tháng này vẫn nên là một vòng lặp đơn, và cách nhanh nhất để lãng phí một tuần là vẽ sơ đồ 6 hộp cho một việc chỉ cần 1.
Graph Engineering trong một nốt nhạc
Một đồ thị tác nhân có 3 phần:
- Nút thực hiện công việc.
- Cạnh quyết định bước chạy tiếp theo.
- Một đối tượng dùng chung di chuyển giữa các nút, mang theo mọi thứ đã tạo ra đến lúc đó.

Ảnh: Tác giả. Ba phần thể hiện trên pipeline ta xây sau: 3 nút được đặt tên, một cạnh pass, một cạnh retry, và một đối tượng state gom topic, notes, draft, và verdict.
Khai báo cả 3 phần ngay từ đầu, thay vì để một tác nhân đơn tự ứng biến lộ trình, chính là điều thuật ngữ graph engineering mô tả.
Hướng dẫn này xây pipeline hoạt động gồm nhà nghiên cứu, người viết, và người phản biện bằng Python với LangGraph, bao gồm một cạnh có điều kiện trả các bản thảo trượt về để sửa.
Bạn cần Python, pip, và quen thuộc cơ bản với các mô hình ngôn ngữ lớn (LLM) hoặc tác nhân AI. Nếu tác nhân còn mới với bạn, khóa Giới thiệu về AI Agents của chúng tôi bao quát các khái niệm bài viết này giả định, và hướng dẫn tác nhân LangGraph bao quát phần thực hành.
Graph Engineering là gì?
Graph engineering là thực hành làm cho luồng điều khiển của một hệ tác nhân trở nên tường minh trong mã, thay vì phó mặc cho mô hình tự quyết.
Bạn khai báo có những người thợ chuyên trách nào, những chuyển tiếp nào giữa họ được phép, và thông tin gì sẽ đi theo những chuyển tiếp đó.
Tác nhân vẫn suy luận tự do, nhưng là bên trong một nút thay vì trên toàn bộ công việc.
Câu cuối đó là toàn bộ điểm khác biệt.
Trong một vòng lặp, bạn đặt mục tiêu và ngưỡng chất lượng, và tác nhân tự chọn lộ trình để đạt được. Trong một đồ thị, bạn cố định lộ trình và các trạm kiểm, nên mức tự chủ của mô hình bị giới hạn bởi cấu trúc bạn có thể đọc trong một diff.
Nhãn gọi này rộ lên trên X vào tháng 7/2026, nhưng không bắt đầu từ đó. Itamar Friedman của CodiumAI (nay là Qodo) đã mô tả sự dịch chuyển "từ prompt engineering sang flow (/graph) engineering" từ tháng 2/2024, và bài AlphaCodium của nhóm ông đưa ra các con số.
Độ chính xác pass@5 của GPT-4 trên bộ CodeContests (validation) tăng từ 19% với một prompt thiết kế tốt lên 44% với luồng nhiều giai đoạn. Cả hai điều kiện đều là 5 lần thử mỗi bài, không phải bắn đơn.
Điều xảy ra tháng 7/2026 là khuếch đại.
Ngày 18/7, Peter Steinberger hỏi trên X: "Chúng ta vẫn nói về loops hay đã chuyển sang graphs?", một tuần sau khi Mike Masson đăng chiếc thang gồm prompt, context, harness, loop, graph. Câu hỏi thu hút 3,1 triệu lượt xem, và cụm từ nó lan truyền vốn đã được dùng từ trước.
Phản biện đến nhanh. Harrison Chase, đồng sáng lập LangChain từ đội đứng sau LangGraph, hỏi liệu toàn bộ có phải "cơ bản chỉ là langgraph?"
Dale Everett phản biện từ hướng ngược lại, cho rằng một loop luôn là một đồ thị một nút, nên sự phấn khích tháng 7 là khám phá lại điều cũ. Bài nhìn lại của chính LangChain, 3 Năm Graph Engineering với LangGraph, có quan điểm tương tự, đóng khung đồ thị tác nhân như một mẫu họ đã xây suốt 3 năm.
Nên tôi xếp thuật ngữ này vào dạng viết tắt hữu ích.
Điều nó mang lại là một cái tên chung cho các câu hỏi thiết kế vốn trước đây chôn trong tài liệu framework, và một cái tên xứng đáng khi bạn tranh luận về kiến trúc trong một pull request.
Graph engineering không phải là gì
Graph engineering mô tả cấu trúc thực thi, tách nó khỏi hai thứ mượn từ vựng của nó.
Knowledge graph và GraphRAG mô tả dữ liệu.
Chúng biến tài liệu thành thực thể và quan hệ để hệ thống truy hồi có thể lần theo các kết nối giữa sự kiện; công cụ, lưu trữ, và chỉ số đánh giá đều khác.
Cho nhánh nghĩa đó, hướng dẫn của chúng tôi về dùng knowledge graph để triển khai ứng dụng RAG là điểm khởi đầu đúng, cùng giới thiệu lý thuyết đồ thị bao quát toán học nằm dưới cả hai.
Điều thứ hai nó không phải là một năng lực mới.
LangGraph, Agent Development Kit (ADK) của Google, và Microsoft AutoGen đều phát hành điều phối đa tác nhân trước khi nhãn gọi này viral, nên nếu bạn từng viết một StateGraph thì bạn đã làm điều này rồi.
Nhiều độc giả sẽ nhận ra họ đã làm graph engineering cả năm dưới tên gọi "pipeline LangGraph của tôi".
Nấc thang kỹ thuật AI
Mỗi lớp của kỹ thuật AI nắm quyền kiểm soát một thứ lùi xa khỏi mô hình thêm một bước.
Cách hữu ích để đọc bảng này là cột bên phải, nó cho bạn biết điều gì thực sự hỏng khi bạn bỏ qua một bậc nhưng vẫn cố xây đè lên.
| Lớp | Bạn kiểm soát gì | Điều gì hỏng nếu bỏ qua |
|---|---|---|
| Prompt | Cách diễn đạt yêu cầu | Mô hình trả lời câu hỏi bạn không hỏi |
| Context | Những đầu vào nào đến được mô hình | Nó suy luận tốt trên tài liệu sai |
| Harness | Công cụ, bộ nhớ, quyền truy cập file và API | Nó không chạm được gì ngoài cửa sổ chat |
| Loop | Chu trình lặp cho đến khi xong | Nó dừng sớm, hoặc không bao giờ dừng |
| Graph | Thợ nào chạy tiếp, và chạy trên cái gì | Một tác nhân cố làm 4 tác nhân và quên mất 3 |
Bỏ qua một bậc là cách phổ biến nhất khiến dự án graph thất bại, và thất bại hiếm khi hiển hiện.
Ba nút thiếu tin cậy nối với nhau không tự trung bình thành một hệ tin cậy.
Chúng tạo ra một hệ hỏng ở nhiều chỗ hơn, tốn kém hơn mỗi lần hỏng, và khó chẩn đoán hơn vì đầu ra lỗi giờ cách nút gây lỗi hai lần bàn giao.
Ba khối xây dựng của một đồ thị tác nhân
Bất kỳ đồ thị tác nhân nào, dù có 3 nút hay 30, cũng phân rã thành nút, cạnh, và state dùng chung.
Một khi bạn có thể gọi tên 3 phần đó trong codebase, hầu hết framework điều phối đều trở nên dễ đọc mà không cần tài liệu.
Nút: người thợ
Một nút là một đơn vị công việc có tên và một trách nhiệm duy nhất.
Nó có thể là một cuộc gọi LLM với prompt chuyên biệt và bộ công cụ riêng, hoặc chỉ là một hàm Python truy vấn cơ sở dữ liệu, kiểm định schema, hay ghi file.
Dành cuộc gọi mô hình cho các bước cần phán đoán ngữ nghĩa.
Nếu một quy tắc có đáp án đã biết, hãy đặt nó trong Python, nơi nó chạy trong micro giây, không tốn phí, và trả về cùng một kết quả hai lần.
Đây là bài test tôi dùng để quyết định có nên tách nhỏ: thử mô tả nút trong một câu không có liên từ.
Một nút "lấy nguồn và quyết định liệu đã đủ hay chưa" đã trượt bài test, vì bạn không thể thay nửa truy hồi mà không làm xáo phần phán đoán.
Cạnh: định tuyến
Một cạnh quyết định điều gì chạy sau khi nút hiện tại kết thúc.
Bốn hình dạng bao phủ gần như mọi thứ bạn sẽ xây:
- Thẳng. Hoàn thành nút A, bắt đầu nút B.
- Có điều kiện. Một hàm định tuyến đọc state hiện tại và trả về tên nút tiếp theo. Đây là nơi phán quyết của người phản biện rẽ nhánh: duyệt và kết thúc, hoặc từ chối và trả bản thảo về cho người viết.
- Fan-out. Một nút khởi chạy nhiều nút chạy đồng thời. Đây là cách bạn truy vấn 5 nguồn song song thay vì xếp hàng.
- Fan-in. Các nhánh song song nhập lại tại một nút hợp nhất kết quả.
Cạnh cũng là nơi đặt logic dừng của bạn. Giới hạn thử lại, cổng chất lượng, và quy tắc leo thang đều là quyết định định tuyến, và giữ chúng trong các hàm cạnh nghĩa là bạn có thể kiểm toán luồng điều khiển ở một chỗ thay vì lục lọi trong thân nút.
State dùng chung: bộ nhớ của hệ
State dùng chung là đối tượng duy nhất mà mọi nút đọc và ghi khi quá trình chạy.
Không có nó, bạn có nhiều tác nhân làm việc cận kề nhưng không chuyền nhau gì, nên người viết không thấy điều người nghiên cứu tìm được, và người phản biện cũng không thấy cả hai.
Trong LangGraph, state thường là một TypedDict.
State của chúng ta tích lũy chủ đề, ghi chú của nhà nghiên cứu, bản thảo hiện tại, phán quyết và phản hồi của người phản biện, cùng bộ đếm sửa. Mỗi nút chỉ trả về các trường nó đã thay đổi, và framework trộn những phần trả về đó vào đối tượng đang chạy.
Quyền ghi là nơi đồ thị xuống cấp đầu tiên.
Quyết định trước khi code nút nào được phép ghi trường nào, vì một state mà 3 nút khác nhau có thể ghi đè là một buổi debug bạn đã tự lên lịch sẵn.
Kỹ thuật vòng lặp vs kỹ thuật đồ thị: Khi nào dùng cái nào
Kỹ thuật vòng lặp thiết kế chu kỳ một tác nhân đơn lặp lại cho đến khi xong, còn kỹ thuật đồ thị thiết kế sự phối hợp giữa vài chu kỳ như vậy.
Đây là quyết định hệ trọng nhất trong bài, nên nó đến trước phần hướng dẫn.
Câu trả lời mặc định là vòng lặp.
Một tác nhân được giới hạn phạm vi tốt với bộ thẩm định nghiêm ngặt sẽ nhanh xây hơn, rẻ chạy hơn, và dễ debug hơn bất kỳ đồ thị nào làm cùng công việc.
Và đó không chỉ là sở thích của tôi.
Một nhóm UC Berkeley (tác giả đầu Mert Cemri) bắt đầu từ quan sát rằng lợi ích đa tác nhân so với thiết lập đơn tác nhân thường tối thiểu, rồi gán nhãn hơn 1.600 vết thực thi từ 7 framework đa tác nhân để tìm lý do (arXiv:2503.13657, v3).
Phân loại của họ, xây từ việc đọc kỹ 150 vết trong số đó, nêu tên 14 kiểu hỏng riêng biệt.
14 kiểu đó xếp vào 3 nhóm: vấn đề thiết kế hệ, lệch pha giữa tác nhân, và kiểm định nhiệm vụ.
Giữ lấy nhóm thứ ba cho đến khi ta đến nút người phản biện.
Bảng quyết định: vòng lặp vs đồ thị
Hãy xem đây là các tín hiệu kích hoạt, không phải danh sách kiểm.
Một cái gật đầu rõ ràng ở cột bên phải là đủ, còn 5 cái mơ hồ thì không.
| Câu hỏi về nhiệm vụ | Vòng lặp xử lý được | Bạn muốn đồ thị |
|---|---|---|
| Bạn có thể viết công việc thành một chỉ dẫn không? | Có, và một người có thể làm từ đầu đến cuối | Nghe như một lần bàn giao giữa 2 vai trò khác nhau |
| Mọi bước có muốn cùng một mô hình không? | Một mô hình và một bộ công cụ xuyên suốt | Thu thập muốn rẻ và nhanh, đánh giá muốn sắc bén |
| Có bước nào không phụ thuộc nhau? | Mỗi bước cần đầu ra của bước trước | Nhiều tra cứu có thể chạy đồng thời |
| Ai quyết định đầu ra đã đủ tốt? | Tác nhân tự đọc lại việc mình làm | Thứ không viết nó phải ký duyệt |
| Điều gì nên xảy ra khi một bước thất bại? | Thử lại và tiếp tục | Cô lập lỗi để phần còn lại sống sót |
| Có ai phải kiểm toán con đường đã đi? | Vết chạy dành cho bạn và đồng đội | Người ngoài cần thấy bước nào đã chạy, và tại sao |
Phiên bản làm quá mà tôi hay gặp thậm chí không liên quan đến tác nhân. Ai đó cần làm sạch và geocode danh sách 800 địa chỉ khách sạn, và nó đến dưới dạng một đồ thị 5 nút: nút nạp, nút chuẩn hóa, nút geocode, nút kiểm định, và nút ghi, với state dùng chung luồn giữa chúng.
Mọi bước đó đều quyết định được, nên thứ họ thực sự xây là một script Python 40 dòng khoác áo framework, và giờ nó tốn tiền theo hàng và hỏng theo cách mà pandas không bao giờ hỏng.
Phiên bản vừa vặn là thứ ta sắp xây.
Tạo một bản tóm tắt ngắn có nghiên cứu tách ra thành việc một vòng lặp đơn vật lộn: thu thập nguyên liệu thô, biến nó thành văn, rồi đánh giá văn đó từ bên ngoài.
Bước thứ ba là lý do đồ thị tồn tại, vì một tác nhân tự phản biện bản thảo của mình thì không phải là phản biện.
Tín hiệu cho thấy đồ thị xứng đáng
Ba điều biện minh cho một nút.
Nếu bạn không thể chỉ ra một trong ba cho mỗi nút đã thêm, hãy xóa nút và gộp việc của nó vào hàng xóm.
Chuyên môn hóa thực sự là đầu tiên.
Nhà nghiên cứu của chúng ta muốn mô hình rẻ, nhanh và, trong sản xuất, công cụ tìm kiếm. Người viết không muốn những thứ đó và hưởng lợi từ mô hình mạnh hơn, nên việc tách ra đang làm thực việc chứ không chỉ tô điểm sơ đồ.
Thứ hai, song song mà bạn thực sự sẽ nhận ra.
Fan-out đáng giá khi các nhánh độc lập và tiết kiệm thời gian treo tường quan trọng với ai đó, và khiến bạn trả giá bằng độ phức tạp thêm khi cả hai điều đó không đúng.
Thứ ba, và đây là điều tôi sẽ bảo vệ mạnh nhất, kiểm định độc lập.
Một tác nhân chấm bài của chính mình chấm nương tay, nên một nút người phản biện riêng biệt chỉ có quyền đọc bản thảo thường là nút giá trị nhất trong mọi đồ thị.
Ở góc nhìn framework về cách các thư viện khác nhau biểu đạt các mẫu này, so sánh của chúng tôi về CrewAI vs LangGraph vs AutoGen trình bày các đánh đổi.
Xây đồ thị đa tác nhân với LangGraph
Chúng ta xây pipeline đa tác nhân LangGraph với nhà nghiên cứu, người viết, và người phản biện để tạo một bản tóm tắt ngắn có nghiên cứu và trả các bản thảo trượt về để sửa.
LangGraph là framework điều phối cấp thấp cho các tác nhân có state, và StateGraph của nó gần như một-một với nút, cạnh, và state ở phần trước.
Mọi thứ bên dưới đã được kiểm tra với langgraph 1.2.11 và langchain-anthropic 1.7.1 vào tháng 9/2026.
Nếu thư viện này còn mới với bạn, hướng dẫn LangGraph của chúng tôi bao quát căn bản. Phần này đi nhanh, và bài so sánh LangChain vs LangGraph vs LangSmith vs LangFlow giải rõ mỗi mảnh trong họ nhà này làm gì.

Ảnh: Tác giả. Pipeline ta sắp xây. Đường liền là 3 cạnh thẳng; đường gạch và chấm là 2 nhánh của một cạnh có điều kiện.
Thiết lập và định nghĩa state dùng chung
Cài các gói, cộng python-dotenv để khóa của bạn không nằm trong mã nguồn:
pip install langgraph langchain-anthropic python-dotenv
Tạo file .env cạnh script của bạn:
ANTHROPIC_API_KEY=sk-ant-your-key-here
Giờ là import và schema state. Viết TypedDict trước đáng 2 phút, vì nó là hợp đồng mọi nút đều làm theo:
from typing import Literal, TypedDict
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
from langgraph.graph import END, START, StateGraph
load_dotenv()
MAX_REVISIONS = 3
# A cheap model for gathering, a stronger one for writing and reviewing.
fast_llm = ChatAnthropic(model="claude-haiku-4-5-20251001", max_tokens=2000)
main_llm = ChatAnthropic(model="claude-sonnet-5", max_tokens=2000)
class BriefState(TypedDict):
topic: str
notes: str
draft: str
verdict: str
feedback: str
revisions: int
Hai mô hình, không phải một. Đó là tín hiệu "mỗi bước một mô hình khác" từ bảng quyết định hiển lộ trong mã thật, vì nghiên cứu là việc khối lượng cao và phán đoán thấp, không cần mô hình đắt.
MAX_REVISIONS đang làm việc lặng lẽ mà quan trọng ở đây.
Không có giới hạn, một người phản biện nghiêm và người viết bướng bỉnh sẽ chuyền qua lại bản thảo cho đến khi hóa đơn của bạn trở nên đáng chú ý.
Xây các nút nhà nghiên cứu, người viết, và người phản biện
Mỗi nút theo cùng hợp đồng. Nó nhận state hiện tại, làm việc của nó, và trả về một dictionary chỉ chứa các trường nó đã thay đổi.
Nhà nghiên cứu gom nguyên liệu thô và ghi vào notes:
def researcher(state: BriefState) -> dict:
"""Gather raw material and write it into shared state as notes."""
prompt = (
f"Topic: {state['topic']}\n\n"
"List 6 to 8 concrete facts, numbers, or named examples a writer "
"could use. Bullet points only. No introduction, no conclusion."
)
response = fast_llm.invoke(prompt)
return {"notes": response.text}
Phiên bản chạy thật của nút này sẽ gọi công cụ tìm kiếm thay vì dựa vào kiến thức sẵn của mô hình.
Tôi giữ nó là một lần gọi .invoke() để cấu trúc đồ thị nhìn rõ, nên hãy coi ghi chú nó tạo là chưa kiểm chứng.
Người viết đọc ghi chú và tạo bản thảo. Nó cũng kiểm tra phản hồi của người phản biện, giúp cạnh retry có cái để hành động:
def writer(state: BriefState) -> dict:
"""Turn notes into a draft, applying reviewer feedback on a retry."""
feedback = state.get("feedback", "")
revision_note = (
f"\n\nThe reviewer rejected your last draft. Fix this: {feedback}"
if feedback
else ""
)
prompt = (
f"Write a 200-word brief on: {state['topic']}\n\n"
f"Use only these notes:\n{state['notes']}{revision_note}"
)
response = main_llm.invoke(prompt)
return {
"draft": response.text,
"revisions": state.get("revisions", 0) + 1,
}
Người phản biện chấm điểm bản thảo.
Nó chưa từng thấy lý luận của người viết và cũng không tạo ra đoạn văn nào, nên có thể thẳng thắn về kết quả.
Đây là nhóm lỗi thứ ba trong phân loại của Berkeley, được trao riêng một nút.
Kiểm định nhiệm vụ hỏng khi không có gì độc lập kiểm tra đầu ra, nên cách khắc phục là một người thợ không thể tự chấm bài mình:
def reviewer(state: BriefState) -> dict:
"""Score the draft. This node never writes, so it can be honest."""
prompt = (
"You are a skeptical editor. Reject the draft if it makes a claim "
"the notes do not support, or if it runs past 250 words.\n\n"
f"NOTES:\n{state['notes']}\n\nDRAFT:\n{state['draft']}\n\n"
"Reply with APPROVE or REVISE on the first line. "
"If REVISE, add one line explaining the single biggest problem."
)
response = main_llm.invoke(prompt)
text = response.text.strip()
verdict = "approve" if text.upper().startswith("APPROVE") else "revise"
return {"verdict": verdict, "feedback": text}
Lưu ý .text thay vì .content ở cả ba nút.
Cả hai đều trả chuỗi cho câu trả lời đơn giản, nhưng .text cũng xử lý đúng khi phản hồi đến dạng nhiều khối nội dung, giúp bạn tránh một AttributeError: 'list' object has no attribute 'strip' gây bối rối sau này.
Parse phán quyết từ dòng đầu giúp dễ đọc, và nó mong manh.
Cho bất kỳ thứ gì chạy không giám sát, hãy thay kiểm tra chuỗi đó bằng structured output của LangChain để phán quyết trở về như một trường có kiểu thay vì tiền tố bạn hy vọng mô hình sẽ tôn trọng.
Nối cạnh và thêm retry có điều kiện
Hàm định tuyến là cạnh có điều kiện. Nó đọc state sau khi người phản biện chạy và trả về tên của điều nên xảy ra tiếp theo:
def route_after_review(state: BriefState) -> Literal["writer", "__end__"]:
"""The conditional edge: ship it, or send it back to the writer."""
if state["verdict"] == "approve":
return END
# revisions counts every draft, including the first, so ">" allows
# 1 original draft plus MAX_REVISIONS rewrites.
if state["revisions"] > MAX_REVISIONS:
return END
return "writer"
Giữ hàm đó im lặng. Một print() bên trong sẽ rơi vào stdout trong khi vòng stream vẫn đang in phần trước, nên thông báo giới hạn sẽ xuất hiện sớm một bước và vết chạy trông như sai thứ tự.
Giới hạn sửa nằm ở đây chứ không trong một nút, vì dừng là quyết định luồng điều khiển và luồng điều khiển thuộc về cạnh.
Giờ lắp ráp đồ thị. Nút, rồi cạnh, rồi biên dịch:
builder = StateGraph(BriefState)
builder.add_node("researcher", researcher)
builder.add_node("writer", writer)
builder.add_node("reviewer", reviewer)
builder.add_edge(START, "researcher")
builder.add_edge("researcher", "writer")
builder.add_edge("writer", "reviewer")
builder.add_conditional_edges(
"reviewer",
route_after_review,
{"writer": "writer", END: END},
)
graph = builder.compile()
Đối số thứ ba cho .add_conditional_edges() là bản đồ đường đi.
Nó liệt kê mọi đích đến mà hàm định tuyến có thể trả về, và LangGraph dùng nó để vẽ nhánh trước khi bất kỳ nút nào chạy.
Chạy đồ thị và xem từng bước
Gọi đồ thị đã biên dịch với state khởi tạo. Chỉ topic và revisions cần giá trị, vì các trường khác sẽ được điền khi thực thi luân chuyển:
result = graph.invoke(
{"topic": "Why Postgres beat MongoDB for most startups", "revisions": 0}
)
if result["verdict"] != "approve":
print(f"Hit the {MAX_REVISIONS}-revision cap. Shipped as is.")
print(f"Revisions: {result['revisions']}")
print(f"Verdict: {result['verdict']}")
print(result["draft"])
Điều đó cho bạn state cuối và không gì khác. Không giúp nhiều khi một lượt chạy đi chệch hướng.
Đổi .invoke() sang .stream() với stream_mode="updates" để xem mỗi nút báo những gì nó đã ghi. Mỗi lần gọi là một lượt chạy riêng với các cuộc gọi mô hình riêng, nên hãy dùng một trong hai thay vì chạy cả hai:
for step in graph.stream(
{"topic": "Why Postgres beat MongoDB for most startups", "revisions": 0},
stream_mode="updates",
):
for node, update in step.items():
print(f"[{node}] wrote: {list(update.keys())}")
Trong một lượt người phản biện từ chối bản thảo đầu, nó in như sau:
[researcher] wrote: ['notes']
[writer] wrote: ['draft', 'revisions']
[reviewer] wrote: ['verdict', 'feedback']
[writer] wrote: ['draft', 'revisions']
[reviewer] wrote: ['verdict', 'feedback']
Hai điều hiện rõ ở đó mà state cuối che giấu.
Nhà nghiên cứu chỉ chạy một lần, và ghi chú của nó tồn tại suốt hai lần viết, nên retry không tái nghiên cứu. Mỗi nút cũng chỉ chạm các trường của chính nó, biến quy tắc quyền ghi ở trên thành thứ bạn có thể kiểm chứng.
Đếm số lần gọi khi bạn đang ở đây.
Con đường bị từ chối đó tốn 5 lần gọi mô hình so với khoảng 1 cho phiên bản vòng lặp đơn của cùng nhiệm vụ, và cách duy nhất để biết 4 lần thêm có mua được gì không là log phán quyết và đọc chúng.
Trực quan hóa đồ thị đã biên dịch
Bạn không cần thêm công cụ để thấy hình dạng thứ mình xây:
print(graph.get_graph().draw_ascii()) # needs: pip install grandalf
print(graph.get_graph().draw_mermaid()) # paste into any Mermaid renderer
Đầu ra Mermaid vẽ nhánh có điều kiện bằng các đường gạch từ reviewer tới cả __end__ và vòng về writer.
Điều đó xác nhận cạnh retry của bạn tồn tại trước khi bạn tiêu gì cho các cuộc gọi mô hình. Bản ASCII chỉ vẽ đường thẳng từ start tới end, nên dùng Mermaid khi bạn muốn thấy vòng lặp.

Ảnh chụp màn hình: Tác giả. Terminal hiển thị kết quả .draw_ascii(), với __start__, researcher, writer, reviewer, và __end__ xếp dọc và nối nhau.
Để debug từng bước với kiểm tra state tại mỗi nút, LangGraph Studio kết nối tới máy chủ cục bộ. Việc đó cần gói riêng và một file cấu hình, nên pip install "langgraph-cli[inmem]", thêm langgraph.json trỏ tới đối tượng graph đã biên dịch, rồi chạy langgraph dev và mở URL Studio nó in ra.
Hướng dẫn LangGraph Studio của chúng tôi đi qua giao diện (từ 2024, nên đối chiếu bước thiết lập với lệnh ở trên), và hướng dẫn tác nhân LangGraph của chúng tôi bao quát việc thêm công cụ thật vào một nút như nhà nghiên cứu.
Một lưu ý về phạm vi.
Pipeline này là tuần tự, nên nó không trình diễn fan-out, mẫu trong đó nhà nghiên cứu sẽ truy vấn vài nguồn một lúc, và một nút nhập sẽ hợp nhất kết quả.
Đó là bước mở rộng tự nhiên kế tiếp, và cũng là nơi chi phí nhân lên nhanh nhất.
Thực hành tốt cho Graph Engineering
Các kiểu lỗi trong graph engineering của AI tác nhân lặp lại đủ thường xuyên để đặt tên. Đây là ba điều tôi kiểm tra trước khi ship bất cứ thứ gì.
1. Nắm vững vòng lặp trước đồ thị
Mỗi nút là một vòng lặp theo nghĩa của nó, với prompt, công cụ, và định nghĩa hoàn thành.
Nối 3 nút lung lay lại với nhau cho bạn một hệ lung lay với diện tích bề mặt gấp ba và câu chuyện debug tệ hơn nhiều.
Hãy khiến một nút hoạt động độc lập trước.
Một nhà nghiên cứu trả về ghi chú mơ hồ khi bạn gọi trực tiếp cũng trả về ghi chú mơ hồ trong một đồ thị, và người viết ở sau sẽ tự tin xây trên đó.
2. Giữ nút nhỏ và đơn nhiệm
Chống lại việc nhét logic vào nút khi nó thuộc về cạnh.
Điều kiện dừng, quyết định rẽ nhánh, và giới hạn thử lại là định tuyến, và định tuyến thuộc về hàm cạnh, nơi bạn có thể đọc tất cả cùng lúc.
Áp dụng bài test không-liên-từ ở trên.
Một nút vừa tìm nguồn vừa quyết định đã đủ hay chưa thực chất là 2 nút chung chữ ký hàm.
3. Theo dõi chi phí
Fan-out và vòng thử lại nhân số token theo những cách mà sơ đồ hoàn toàn che giấu.
Một fan-out 5 nhánh đổ vào nút nhập với giới hạn 3 lần thử lại không phải là 5 cuộc gọi, và tùy vị trí retry, nó có thể là 15 hoặc hơn trước khi bạn đếm nút nhập.
Đặt giới hạn rõ ràng, như ta làm với MAX_REVISIONS. Rồi log số token theo nút và đọc chúng sau một tuần, vì nút bạn tưởng là rẻ thường là nút chạy nhiều nhất.
Chọn framework
AutoGen vẫn thường được khuyên cho điều phối đồ thị, và công trình GraphFlow ở trạng thái thử nghiệm của nó là tiền lệ thật, nhưng repository đang ở chế độ bảo trì tính đến tháng 9/2026, không có tính năng mới.
Microsoft hướng người dùng mới tới Microsoft Agent Framework, vốn có các workflow dựa trên đồ thị riêng, qua một hướng dẫn di trú đã xuất bản.
Tính từ hôm nay, LangGraph, ADK của Google, hoặc Microsoft Agent Framework là lựa chọn an toàn hơn, và khóa Xây dựng AI Agents với Google ADK của chúng tôi bao quát ADK chuyên sâu.
Kết luận
Graph engineering là lớp điều phối phía trên loop engineering.
Các nút làm việc, các cạnh quyết định điều gì chạy tiếp, và một đối tượng dùng chung mang thông tin giữa chúng.
Gạt bỏ nhiễu của dòng thời gian tháng 7/2026, đó là toàn bộ mô hình.
Pipeline của chúng ta cố ý giữ nhỏ: 3 nút, 4 khai báo cạnh (1 trong số đó có điều kiện, nên vẽ 2 nhánh), và một giới hạn sửa để vòng retry không chạy mất kiểm soát.
Chừng đó cấu trúc là đủ để bản thảo được phản biện bởi thứ không viết nó, và thuộc tính duy nhất đó là thứ vòng lặp không thể mang lại.
Hãy chọn đồ thị khi công việc tách thành các pha cần chuyên gia khác nhau, và không sớm hơn một nút. Những người hoài nghi đúng rằng cơ chế đã tồn tại hàng thập kỷ và phần lớn bài viết quanh thuật ngữ này là nhiễu.
Họ cũng đúng về phần quan trọng vào một chiều thứ Ba.
Một bộ thẩm định yếu gắn vào một vấn đề hình vòng lặp sẽ không khá hơn chỉ vì bạn vẽ thêm nhiều hộp quanh nó.
Để đi xa hơn các mẫu này, khóa Hệ đa tác nhân với LangGraph của chúng tôi bao quát thiết kế supervisor và network mà hướng dẫn này dừng lại trước đó.
Ở nhánh dữ liệu của từ này, Graph RAG với LangChain và Neo4j là bước tiếp theo phù hợp. Để ở lại phía điều phối, Text-to-Query Agents với MongoDB và LangGraph xây một pipeline LangGraph trên cơ sở dữ liệu sống, và Giải thích LLM Agents lấp đầy kiến trúc nằm dưới tất cả.
Toàn bộ script nằm trong repo GitHub của tôi, kèm tiện ích render đồ thị và ghi chú ngắn về chi phí mỗi lượt chạy.
FAQs
Graph engineering là gì?
Graph engineering là thực hành viết tường minh luồng điều khiển của một hệ tác nhân: các thợ được đặt tên, các tuyến đường giữa họ được khai báo, và một đối tượng state mà tất cả cùng chia sẻ. Cụm từ này xuất hiện từ tháng 2/2024, khi Itamar Friedman mô tả sự dịch chuyển từ prompt engineering sang flow (/graph) engineering, và trở nên phổ biến trên X vào tháng 7/2026. Từ vựng thì cũ hơn cơn sốt, và năng lực thì cũ hơn cả hai.
Graph engineering có giống knowledge graph engineering hay GraphRAG không?
Không. Knowledge graph và GraphRAG mô hình hóa dữ liệu của bạn dưới dạng thực thể và quan hệ để hệ thống truy hồi có thể đi theo các kết nối. Graph engineering mô hình hóa thực thi: tác nhân nào chạy tiếp, và nó nhận được gì khi chạy.
Khi nào tôi nên dùng đồ thị thay vì một vòng lặp tác nhân đơn?
Ba tín hiệu biện minh: chuyên môn hóa thực sự (các bước muốn mô hình hoặc bộ công cụ khác nhau), song song mà bạn sẽ thật sự nhận ra, và kiểm định độc lập bởi thứ không tạo ra đầu ra. Thiếu một trong số đó, một vòng lặp giới hạn phạm vi tốt với bộ thẩm định nghiêm sẽ rẻ hơn và dễ debug hơn nhiều.
Tôi có cần LangGraph để làm graph engineering không?
Không. Google ADK cung cấp các tác nhân workflow tuần tự, song song, và vòng lặp, và Microsoft Agent Framework tiếp nối công việc điều phối mà AutoGen khởi đầu. LangGraph là điểm vào Python phổ biến nhất vì StateGraph của nó ánh xạ một-một với nút, cạnh, và state.
Đồ thị đắt hơn vòng lặp bao nhiêu?
Hãy đếm số cuộc gọi trước khi bạn xây. Pipeline 3 nút trong hướng dẫn này tốn 3 cuộc gọi mô hình khi người phản biện duyệt ngay bản thảo đầu và 5 khi trả về một bản, so với khoảng 1 cho phiên bản vòng lặp đơn của cùng nhiệm vụ. Fan-out nhân con số đó lần nữa, nên hãy đặt giới hạn retry trước lượt chạy đầu tiên.
Josep là một Nhà khoa học dữ liệu tự do chuyên về các dự án châu Âu, có chuyên môn về lưu trữ dữ liệu, xử lý, phân tích nâng cao và kể chuyện bằng dữ liệu tạo tác động.
Với vai trò giảng dạy, anh phụ trách môn Dữ liệu lớn trong chương trình Thạc sĩ tại Đại học Navarra và chia sẻ góc nhìn qua các bài viết trên các nền tảng như Medium, KDNuggets và DataCamp. Josep cũng viết về Dữ liệu và Công nghệ trong bản tin Databites (databites.tech).
Anh có bằng Cử nhân Vật lý Kỹ thuật từ Đại học Bách khoa Catalonia và bằng Thạc sĩ Hệ thống Tương tác Thông minh từ Đại học Pompeu Fabra.
