Sổ tay kỹ thuật

Dựng ReAct agent với LangGraph cho tool mạng

how-to#langgraph#python#agents· cập nhật 2026-11-06

Dùng khi cần dựng nhanh một agent hỏi-đáp vận hành mạng (ping, show) bằng LangGraph và Claude, có lưu hội thoại theo thread.

Sửa trang này
Mục lục

Tóm tắt: Viết tool bằng @tool (langchain-core), model ChatAnthropic, ghép bằng create_react_agent (nhanh) hoặc tự dựng StateGraph + ToolNode + tools_condition (kiểm soát hơn). Gắn checkpointer và thread_id để agent nhớ ngữ cảnh. Khái niệm nền xem LangGraph – khái niệm cốt lõi.

Luồng hoạt động

flowchart LR U[Câu hỏi NOC] --> A["agent: Claude"] A -->|tool_calls| T[ToolNode] T -->|ping| R1[("198.51.100.11")] T -->|show_bgp_summary| R2[("pe1-hni")] T --> A A -->|"không còn tool_calls"| O[Câu trả lời]

Cấu hình

Cài đặt

uv add langgraph langchain-anthropic
export ANTHROPIC_API_KEY='***'

Tool

net_tools.py
import ipaddress
import subprocess
 
from langchain_core.tools import tool
 
INVENTORY = {
    "pe1-hni": {"mgmt": "198.51.100.11", "os": "iosxr"},
    "pe2-hcm": {"mgmt": "198.51.100.12", "os": "junos"},
}
SHOW_BGP = {"iosxr": "show bgp summary", "junos": "show bgp summary"}
 
 
@tool
def ping(target: str, count: int = 3) -> str:
    """Ping một địa chỉ IP (không nhận hostname). Dùng để kiểm tra reachability."""
    ip = ipaddress.ip_address(target)
    out = subprocess.run(["ping", "-c", str(min(count, 10)), "-W", "1", str(ip)],
                         capture_output=True, text=True, timeout=30)
    return out.stdout[-1500:] or out.stderr
 
 
@tool
def show_bgp_summary(device: str) -> str:
    """Chạy 'show bgp summary' (chỉ đọc) trên thiết bị theo tên inventory, vd pe1-hni."""
    d = INVENTORY.get(device)
    if d is None:
        return f"Không có thiết bị {device}. Thiết bị hợp lệ: {', '.join(INVENTORY)}"
    return run_show(d["mgmt"], d["os"], SHOW_BGP[d["os"]])
 
 
def run_show(host: str, os_name: str, command: str) -> str:
    # Gọi netmiko/scrapli/PyEZ ở đây; chỉ cho phép lệnh show
    if not command.startswith("show "):
        raise ValueError("chỉ cho phép lệnh show")
    raise NotImplementedError

Cách 1: prebuilt create_react_agent

agent_prebuilt.py
from langchain_anthropic import ChatAnthropic
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.prebuilt import create_react_agent
 
from net_tools import ping, show_bgp_summary
 
model = ChatAnthropic(model="claude-sonnet-5-5", temperature=0)
agent = create_react_agent(
    model,
    tools=[ping, show_bgp_summary],
    prompt="Bạn là trợ lý NOC. Chỉ dùng tool đọc, trả lời ngắn, nêu rõ lệnh đã chạy.",
    checkpointer=InMemorySaver(),
)
 
config = {"configurable": {"thread_id": "noc-1"}, "recursion_limit": 20}
result = agent.invoke({"messages": [("user", "pe1-hni có ping được không?")]}, config)
print(result["messages"][-1].content)

Ở LangGraph 1.x, create_react_agent được đánh dấu deprecated, hướng thay thế là create_agent trong package langchain. Kiểm tra phiên bản bạn cài; Cách 2 bên dưới không phụ thuộc vào thay đổi này.

Cách 2: tự dựng StateGraph

agent_graph.py
from langchain_anthropic import ChatAnthropic
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode, tools_condition
 
from net_tools import ping, show_bgp_summary
 
tools = [ping, show_bgp_summary]
model = ChatAnthropic(model="claude-sonnet-5-5", temperature=0).bind_tools(tools)
 
 
def agent(state: MessagesState) -> dict:
    return {"messages": [model.invoke(state["messages"])]}
 
 
builder = StateGraph(MessagesState)
builder.add_node("agent", agent)
builder.add_node("tools", ToolNode(tools))
builder.add_edge(START, "agent")
builder.add_conditional_edges("agent", tools_condition)  # có tool_calls -> "tools", không -> END
builder.add_edge("tools", "agent")
graph = builder.compile(checkpointer=InMemorySaver())
 
config = {"configurable": {"thread_id": "noc-1"}, "recursion_limit": 20}
for chunk in graph.stream({"messages": [("user", "BGP trên pe1-hni có peer nào down?")]},
                          config, stream_mode="values"):
    chunk["messages"][-1].pretty_print()

Chạy và hỏi tiếp cùng thread

uv run agent_graph.py

Gọi lại graph.invoke(..., config) với cùng thread_id thì agent nhớ thiết bị đang bàn. Muốn duyệt trước khi chạy tool: builder.compile(checkpointer=..., interrupt_before=["tools"]).

Lỗi thường gặp

Triệu chứng Nguyên nhân Cách xử lý
GraphRecursionError Agent lặp agent↔tools quá recursion_limit Xem tool trả gì (thường lỗi lặp lại), sửa description; đặt recursion_limit hợp lý
Agent không nhớ câu trước Không có checkpointer hoặc đổi thread_id compile(checkpointer=...), giữ nguyên thread_id
Model không gọi tool Quên .bind_tools(tools) ở Cách 2 Bind tool cho model trong node agent
ImportError: create_react_agent hoặc cảnh báo deprecated Đổi API giữa các phiên bản Ghim phiên bản trong pyproject.toml, hoặc dùng Cách 2
Tool lỗi làm crash cả graph Exception không được bắt ToolNode mặc định trả lỗi về model; với tool tự viết hãy trả chuỗi lỗi rõ ràng
Output show quá dài, tốn token Trả nguyên output CLI Lọc/tóm tắt trong tool (chỉ peer down, chỉ dòng liên quan)

Tham khảo