Tin ngành
LangChain ra mắt Connections: Quản lý xác thực và định danh người dùng cho Deep Agents
(giờ Việt Nam)
Tóm tắt AI
LangChain giới thiệu tính năng Connections giúp lưu trữ thông tin xác thực an toàn và hỗ trợ OAuth theo từng người dùng, cho phép các tác nhân AI thực hiện hành động dựa trên danh tính riêng biệt của mỗi cá nhân.
Bản dịch AI

Mọi tác nhân (agent) cuối cùng đều cần thực hiện hành động thay mặt cho ai đó — tìm kiếm trên web, gửi phiếu hỗ trợ (ticket), hay mở một pull request. Ngày nay, điều đó thường đồng nghĩa với việc một API key được mã hóa cứng (hard-coded) trong mọi bản triển khai, và mọi hành động đều hiển thị dưới tên một tài khoản dịch vụ (service account). Một key trong tệp.env trả lời được câu hỏi tác nhân có thể làm gì, nhưng không có cách nào để biết ai là người đã yêu cầu.

Đó chính là vấn đề mà Connections giải quyết. Connection là một thông tin xác thực (credential) có tên trong không gian làm việc LangSmith của bạn, được các công cụ đọc tại thời điểm chạy (run time) thông qua slug bằng một lệnh gọi duy nhất.
Hai trục, không phải một
Một connection có chủ sở hữu (owner) và loại thông tin xác thực (credential type), và chúng độc lập với nhau.
Chủ sở hữu có thể là tác nhân hoặc người gọi (caller). Thông tin xác thực do tác nhân sở hữu thuộc về bản triển khai và mọi người gọi đều dùng chung nó. Thông tin xác thực do người dùng sở hữu sẽ được xác định theo từng cá nhân tại thời điểm chạy.
Thông tin xác thực có thể là một secret tĩnh hoặc một OAuth grant: một tác nhân có thể nắm giữ OAuth grant, và một người dùng có thể nắm giữ một secret.
Quyền sở hữu được cố định khi bạn tạo connection bằng lệnh `mda connections create`, và `connections.get ` chỉ chọn trong số các thông tin xác thực đã tồn tại.
Secret do tác nhân sở hữu

Secret do tác nhân sở hữu được sử dụng trong các tình huống bạn cần một thông tin xác thực dùng chung cho mọi người gọi. Đây là cách tiếp cận phù hợp cho các khả năng không thay đổi tùy theo từng người: tìm kiếm web, dịch vụ định vị địa lý (geocoder), hay nguồn cấp dữ liệu giá cả.
Trong ví dụ này, hãy cấu hình một connection tới Tavily để thêm một công cụ tìm kiếm web chung cho tác nhân:
uv run mda connections create tavily-agent --secret-from-env TAVILY_API_KEY
tavily-agent là slug. Đây là tên bạn đặt cho connection và là tên mà mã nguồn của bạn sử dụng; không có hệ thống nào kiểm tra nó với danh sách nhà cung cấp. Giá trị được lấy từ TAVILY_API_KEY và đưa vào không gian làm việc LangSmith của bạn. Nó không phải là một phần của bản build, và `mda deploy` không quét nó theo cách quét tệp.env vào các secret triển khai.
Công cụ đọc nó là một công cụ LangChain thông thường với một dòng mới tận dụng `connections.get`:
# tools/search_web.py import httpx from langchain.tools import tool from managed_deepagents import connections @tool(parse_docstring=True) async def search_web(query: str) -> str: """ Tìm kiếm trên web. Args: query: Truy vấn tìm kiếm. """ api_key = await connections.get("tavily-agent", {"type": "agent"}) async with httpx.AsyncClient(timeout=30.0) as client: response = await client.post( "https://api.tavily.com/search", json={"api_key": api_key, "query": query, "max_results": 5},) response.raise_for_status return response.text
@tool(parse_docstring=True) async def search_web(query: str) -> str: """ Tìm kiếm trên web.
Args: query: Truy vấn tìm kiếm. """ api_key = await connections.get("tavily-agent", {"type": "agent"}) async with httpx.AsyncClient(timeout=30.0) as client: response = await client.post( "https://api.tavily.com/search", json={"api_key": api_key, "query": query, "max_results": 5},) response.raise_for_status return response.text
Nếu bạn cần xoay vòng (rotate) key của mình, bạn có thể cập nhật secret được lưu tại tavily-agent, và mọi yêu cầu của tác nhân trong tương lai sẽ tự động sử dụng key mới.
OAuth do người dùng sở hữu, với ứng dụng của riêng bạn
Token dùng chung rất hữu ích, nhưng việc cho phép tác nhân hành động thay mặt người dùng đồng nghĩa với việc bạn có thể cung cấp thêm nhiều khả năng một cách an toàn cho tác nhân đó. GitHub có sẵn trong danh mục connections cùng với 22 dịch vụ khác, vì vậy bạn chỉ cần cung cấp client ID và secret — không cần URL ủy quyền, không cần URL token, không cần phương thức xác thực nào để tra cứu.
Bạn có thể nhanh chóng tham khảo các connection trong danh mục bằng `mda connections catalog`, nhưng bạn có thể kết nối với bất kỳ nhà cung cấp nào hỗ trợ OAuth nếu bạn cung cấp metadata của riêng mình.
Ví dụ, để cấu hình một connection tới một ứng dụng Github OAuth tùy chỉnh:
uv run mda connections create github-issues \ --oauth github \ --client-id "$GITHUB_CLIENT_ID" \ --secret-from-env GITHUB_CLIENT_SECRET \ --scope repo
Trong ví dụ này, github-issues là slug, thuộc về bạn và được mã nguồn của bạn sử dụng. github là dịch vụ trong danh mục, chỉ đóng vai trò quyết định các endpoint nào sẽ được điền vào.
Các công cụ đọc token thông qua một helper. Trong ví dụ này, dòng quan trọng là:
access_token = await connections.get("github-issues", {"type": "user"})
Với một lệnh gọi duy nhất tới `connections.get`, một tác nhân đã triển khai có thể tự động kích hoạt luồng OAuth cho người dùng mới hoặc lấy token OAuth đã lưu trong bộ nhớ đệm cho người dùng đã xác thực trước đó với nhà cung cấp OAuth.
Chúng ta có thể tận dụng access token này để thực hiện các lệnh gọi API tùy ý tới Github:
# tools/github.py async def _github(method: str, path: str, **kwargs) -> dict: access_token = await connections.get("github-issues", {"type": "user"}) async with httpx.AsyncClient(timeout=30.0) as client: response = await client.request( method, f"{GITHUB_API}{path}", headers={ "Authorization": f"Bearer {access_token}", "Accept": "application/vnd.github+json", "X-GitHub-Api-Version": GITHUB_VERSION, }, **kwargs,) response.raise_for_status return response.json
Lưu ý rằng chúng ta đặt {"type": "user"}. Connection do tác nhân sở hữu đã lưu trữ một giá trị tại thời điểm tạo. Connection này không lưu trữ giá trị nào cả, chỉ có đăng ký ứng dụng. Thông tin xác thực sẽ đến theo từng người gọi tại thời điểm chạy — và nếu người gọi chưa bao giờ ủy quyền cho GitHub, hoặc token của họ đã hết hạn, `connections.get ` sẽ tạm dừng quá trình chạy và yêu cầu cấp quyền thay vì báo lỗi.
Từ đó chỉ xuất hiện một lần, bên trong `_github`. Cả công cụ `search_issues` và `create_issue` đều kế thừa danh tính theo từng người gọi từ helper, và một công cụ GitHub thứ ba sẽ không tốn thêm bất kỳ mã xác thực nào.
Lợi ích thể hiện ở hai điểm. `search_issues` đã khác biệt theo từng người gọi trước khi bất cứ thứ gì được ghi lại, bởi vì các kho lưu trữ riêng tư mà một người có thể thấy còn người khác thì không sẽ làm thay đổi kết quả — cùng một truy vấn, cùng một bản triển khai, nhưng kết quả khác nhau. Và khi `create_issue` chạy, issue sẽ được tạo trên GitHub bởi chính người đã yêu cầu. `user.login` trong phản hồi chính là tên người dùng của họ, không phải của bot.
OAuth do người dùng sở hữu, không cần đăng ký ứng dụng
Một số máy chủ MCP tự đăng ký ứng dụng khách OAuth. Khi đó, toàn bộ thiết lập chỉ là một URL.
uv run mda connections create linear-mcp --mcp https://mcp.linear.app/mcp
# tools/mcp.py
from managed_deepagents import connections, define_mcp mcp = define_mcp( servers={ "linear": { "transport": "http", "url": "https://mcp.linear.app/mcp", "connection": connections.get("linear-mcp", {"type": "user"}), }, },)
mcp = define_mcp( servers={ "linear": { "transport": "http", "url": "https://mcp.linear.app/mcp", "connection": connections.get("linear-mcp", {"type": "user"}), }, },)
Bài viết được AI dịch và tổng hợp tự động từ LangChain: Blog. Liên kết bài gốc ở phía trên. AIHOT.vn luôn dẫn nguồn đầy đủ — nếu bạn thấy điểm cần chỉnh sửa, hãy gửi ý kiến tại trang phản hồi.