使用套件 langchain-azure-ai 將 LangGraph 和 LangChain 應用程式連接到 Foundry Agent Service。 本文將介紹實務情境,從使用現有智能代理、組成多智能代理圖,到工具驅動的工作流程、人為介入批准與追蹤。
先決條件
- 一個 Azure 訂閱。 免費創建一個。
- Foundry 專案。
- 在你的專案中部署了一個聊天模型(例如,
gpt-4.1)。 - Python 3.10 或更新版本。
- Azure CLI已登入(
az login),所以DefaultAzureCredential可以進行認證。
有些例子需要額外資源:
- 程式碼直譯器的範例需要 支援的區域與模型。
- 影像生成範例需要
gpt-image-1.5部署。 將模型部署 到你的專案中。 如有需要, 申請模型存取權。 - 檔案搜尋範例需要一個向量儲存庫,至少包含一個索引檔案。 關於設定說明,請參見 「使用檔案搜尋工具」。
配置你的環境
安裝套件 langchain-azure-ai,以便在 LangGraph 和 LangChain 中使用 Microsoft Foundry 的功能。
pip install langchain-azure-ai[tools,opentelemetry] azure-identity
請驗證您的 Python 版本、套件安裝及 Azure 登入狀態:
python --version
python -c "import langchain_azure_ai; print('langchain-azure-ai is installed')"
az account show --output table
提示
安裝附加功能[tools],以使用像文件智慧或 Azure Logic Apps 連接器等工具。 安裝 [opentelemetry] 以納入生成式 AI 解決方案的 OpenTelemetry 支援及其語意慣例。
設定我們在這教學中使用的環境變數:
export AZURE_AI_PROJECT_ENDPOINT="https://<resource>.services.ai.azure.com/api/projects/<project>"
export MODEL_DEPLOYMENT_NAME="gpt-4.1"
使用 Foundry Agent Service Agent
這個類別 AgentServiceFactory 是你在 LangGraph 中組合代理,並與 Foundry 代理服務互動的起點。
工廠會建立與 LangGraph 相容的節點,這些節點會透過 Agent Service 執行,並可用來組合更複雜的 LangGraph 解。
透過將類別連接到 AgentServiceFactory Foundry 專案來建立代理工廠。 你透過這個工廠建立或參考的所有代理都在專案中管理,並且會在 Foundry 入口網站(新)中可見。
註
從 Foundry 經典版本遷移: 通過 langchain_azure_ai.agents.v1.AgentServiceFactory 創建的 Agent 僅在 Foundry 平台(經典版)中可見。
import os
from langchain_core.messages import HumanMessage
from azure.identity import DefaultAzureCredential
from langchain_azure_ai.agents import AgentServiceFactory
from langchain_azure_ai.utils.agents import pretty_print
factory = AgentServiceFactory(
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
credential=DefaultAzureCredential(),
)
使用現有的經紀人
我們建議在 Foundry 入口網站或 Foundry SDK 中建立並設定代理,然後使用名稱 get_agent_node 來參考它們,以便組成圖表。 此方法被推薦,因為它能將代理設定集中在 Foundry 中,並讓你的程式碼專注於編排。 當您需要完全以程式碼定義 Agent 時,也可以使用 create_prompt_agent 以程式設計方式建立 Agent。
echo_node = factory.get_agent_node(
name="my-echo-agent",
version="latest",
)
這段程式碼的作用:擷取現有 Foundry Agent 的參考,作為與 LangGraph 相容的節點。 代理人必須已經存在於你的 Foundry 專案中。 使用 version="latest" 一律以最新版本為目標,或釘選特定版本號碼以維持穩定性。
測試你的代理程式能運行:
response = echo_node.invoke(
{"messages": [HumanMessage(content="Hello, world!")]}
)
pretty_print(response)
================================ Human Message =================================
Hello, world!
================================== Ai Message ==================================
Name: my-echo-agent
Goodbye, world!
對話與狀態
連接至代理服務的節點會自動追蹤對話中的回應。
azure_ai_agents_conversation_id屬性被添加到狀態中,以便你能參考或繼續對話:
print(
"azure_ai_agents_conversation_id:",
response["azure_ai_agents_conversation_id"],
)
azure_ai_agents_conversation_id: <conversation-id>
與現有代理構建圖表
你可以像使用 LangGraph 中的其他節點一樣使用代理服務節點來建立複雜的圖。 下列範例會建置條件式路由圖,其中本機 router_node 會檢查使用者訊息,並決定是否委派給 Foundry Agent。
from typing import Literal
from langchain_core.messages import AIMessage
from langgraph.graph import StateGraph, MessagesState, START, END
class RouterState(MessagesState):
jump_to: str | None
def router_node(state: RouterState):
last_message = state["messages"][-1].content.lower()
# Simple logic simulating a model decision
if "negate" in last_message:
return RouterState(
messages=state["messages"], jump_to="delegate"
)
else:
return RouterState(
messages=[AIMessage(content="I can handle this!")],
jump_to=None,
)
def route_decision(state: RouterState) -> Literal["expert_node", END]:
if state.get("jump_to", None) == "delegate":
return "expert_node"
return END
workflow = StateGraph(RouterState)
workflow.add_node("router_node", router_node)
workflow.add_node("expert_node", echo_node)
workflow.add_edge(START, "router_node")
workflow.add_conditional_edges("router_node", route_decision)
workflow.add_edge("expert_node", END)
app = workflow.compile()
這段程式碼 建立一個有兩個節點的 LangGraph StateGraph 。
router_node 會檢查最後一則訊息;如果其中包含「negate」,就會將工作委派給 expert_node (也就是使用 get_agent_node 擷取的 Foundry Agent)。 否則,路由器會在本地處理請求並結束圖表。 此模式展示了如何將局部邏輯與 Foundry 代理結合。
圖表如下所示:
調用圖表:
print("--- Test 1 (Direct) ---")
pretty_print(
app.invoke({"messages": [HumanMessage(content="Hello, world!")]})
)
print("\n--- Test 2 (Delegated) ---")
pretty_print(
app.invoke(
{"messages": [HumanMessage(content="Negate that I'm a genius!")]}
)
)
------------------------------- Test 1 (Direct) --------------------------------
================================ Human Message =================================
Hello, world!
================================== Ai Message ==================================
I can handle this!
------------------------------ Test 2 (Delegated) ------------------------------
================================ Human Message =================================
Negate that I'm a genius!
================================== Ai Message ==================================
Name: my-echo-agent
You're not a genius!
在測試一中,路由器會本地處理請求。 在測試 2 中,路由器會委派給 Foundry 代理,代理程式則回應與使用者陳述相反的訊息。
建立一個基本的提示代理程式
當你需要完全以程式碼定義代理時——例如在原型設計時,或代理設定應與應用程式同時存在——請使用 create_prompt_agent。 先用一個簡易的 ReAct 風格提示代理來驗證你的整合。
agent = factory.create_prompt_agent(
name="my-echo-agent",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
instructions=(
"You are a helpful AI assistant that always replies with the "
"opposite of what the user says."
),
)
agent_ids = factory.get_agents_id_from_graph(agent)
print(f"Agent created: {next(iter(agent_ids))}")
Agent created: my-echo-agent:1
啟動代理人:
messages = [HumanMessage(content="I'm a genius and I love programming!")]
response = agent.invoke({"messages": messages})
pretty_print(response)
================================ Human Message =================================
I'm a genius and I love programming!
================================== Ai Message ==================================
Name: my-echo-agent
You are not a genius and you hate programming!
這段程式碼片段的作用是: 在 Foundry 代理服務中建立一個基於提示的代理,並回傳一個使用該代理的 LangGraph CompiledStateGraph。 在 Foundry 入口網站的代理人頁面中可以立即看到代理。
此 factory.get_agents_id_from_graph 方法會從編譯後的圖中取得 Foundry 指派的代理名稱與版本。
你可以透過列印代理的圖表表示來視覺化代理是如何被創建和在 LangGraph 圖中使用的。 該節點 foundryAgent 運行於 Foundry 代理服務中。 請注意,圖表中顯示了代理名稱和版本。
from IPython import display
display.Image(agent.get_graph().draw_mermaid_png())
factory.delete_agent(agent)
為你的經紀人新增工具
你可以在代理中新增執行動作的工具。 這個方法 create_prompt_agent 會幫你實作代理迴圈。
你應該區分兩種工具:
- 本地工具:這些工具會在代理程式碼所在的位置執行。 它們可以是可呼叫的函式,或是任何 LangChain/LangGraph 生態系統可用的函式。
- 內建工具:這些工具只能在 Foundry Agent Service 中執行;伺服器端。 伺服器端工具只能套用於 Foundry 代理程式。
在你的代理中加入 本地工具 ,會在圖表中加入一個工具 節點 ,讓這些工具執行。 內建工具 不會新增 工具節點 ,而是在你提出請求時在服務中執行。
以下章節將說明如何使用這兩種:
新增本地工具
你可以定義本地 Python 函式,並將它們附加為工具。 此模式對於確定性商業邏輯與公用運算非常有用。
def add(a: int, b: int) -> int:
"""Add two integers."""
return a + b
def multiply(a: int, b: int) -> int:
"""Multiply two integers."""
return a * b
def divide(a: int, b: int) -> float:
"""Divide one integer by another."""
return a / b
將工具傳遞給函數 create_prompt_agent,並透過多步驟算術問題來呼叫代理:
math_agent = factory.create_prompt_agent(
name="math-agent",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
instructions=(
"You are a helpful assistant tasked with performing arithmetic "
"on a set of inputs."
),
tools=[add, multiply, divide],
)
messages = [
HumanMessage(
content="Add 3 and 4. Multiply the output by 2. Divide the output by 5."
)
]
response = math_agent.invoke({"messages": messages})
pretty_print(response)
================================ Human Message =================================
Add 3 and 4. Multiply the output by 2. Divide the output by 5
================================== Ai Message ==================================
Tool Calls:
add (call_JSmltOCbsTRkbNEBMAVSgVe1)
Call ID: call_JSmltOCbsTRkbNEBMAVSgVe1
Args:
a: 3
b: 4
================================= Tool Message =================================
Name: add
7
================================== Ai Message ==================================
Tool Calls:
multiply (call_ae6M6XyhOIBOkPy3ETd8nDI9)
...
================================== Ai Message ==================================
Name: math-agent
Here's the step-by-step calculation:
1. Add 3 and 4 to get 7.
2. Multiply the result (7) by 2 to get 14.
3. Divide the result (14) by 5 to get 2.8.
The final result is 2.8.
這段程式碼的作用是使用三種算術工具來建立代理程式。 當代理判定需要工具呼叫時,Foundry 代理服務會在本地協調工具調用,並將結果回饋給代理繼續推理。
在相同代理流程中,使用 LangGraph/LangChain 生態系統中的其他工具,例如 Foundry Tools 中的 Azure 文件智慧。 雖然這些工具連接到 Foundry 資源,但 並非專屬於代理服務,因此更像是本地工具。
from langchain_azure_ai.tools import AzureAIDocumentIntelligenceTool
document_parser_agent = factory.create_prompt_agent(
name="document-agent",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
instructions="You are a helpful assistant tasked with analyzing documents.",
tools=[AzureAIDocumentIntelligenceTool()],
)
提示
AzureAIDocumentIntelligenceTool 可以使用 Foundry 專案連接服務,並且支援Microsoft Entra進行認證。 預設情況下,工具使用 AZURE_AI_PROJECT_ENDPOINT , DefaultAzureCredential因此不需要進一步設定。 如果需要,你可以改成使用特定的端點和金鑰。
請客服從網址分析發票:
messages = [
HumanMessage(
content=(
"What's the total amount in the invoice at "
"https://raw.githubusercontent.com/Azure/azure-sdk-for-python/main/"
"sdk/formrecognizer/azure-ai-formrecognizer/tests/sample_forms/"
"forms/Form_1.jpg"
)
)
]
response = document_parser_agent.invoke({"messages": messages})
pretty_print(response)
================================ Human Message =================================
What's the total amount in ...
================================== Ai Message ==================================
Tool Calls:
azure_ai_document_intelligence (call_32V6bqeCcJhhsOXDrYFXggnc)
Call ID: call_32V6bqeCcJhhsOXDrYFXggnc
Args:
source_type: url
source: https://raw.githubusercontent.com/Azure/ ...
================================= Tool Message =================================
Name: azure_ai_document_intelligence
Content: Purchase Order Hero ...
================================== Ai Message ==================================
Name: document-agent
The total amount in the invoice is **$144.00**.
此段程式碼:請程式代理從一張發票影像中擷取數據。 代理呼叫 AzureAIDocumentIntelligenceTool 以解析文件並回傳結果。 預期產出:「 發票上的總金額為 144.00美元。」
新增內建工具
Foundry Agent Service 內建工具是在伺服器端執行,而非像本地工具那樣在 工具節點 中運行。 命名空間 langchain_azure_ai.agents.prebuilt.tools.* 中的工具都是內建工具,且僅能與 create_prompt_agent一起使用。
範例:使用 Code 解譯工具
建立一個用於資料分析的程式碼解譯代理,並用虛構 data.csv 的資料檔案呼叫它。
在執行這個範例之前,請在你目前的工作目錄中建立一個本地 data.csv 檔案。
region,sales
North,120
South,80
East,100
West,60
import base64
from langchain_azure_ai.agents.prebuilt.tools import CodeInterpreterTool
code_interpreter_agent = factory.create_prompt_agent(
name="code-interpreter-agent",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
instructions=(
"You are a data analyst agent. Analyze CSV data and create "
"visualizations when helpful."
),
tools=[CodeInterpreterTool()],
)
with open("data.csv", "rb") as file_handle:
csv_data = base64.b64encode(file_handle.read()).decode()
response = code_interpreter_agent.invoke(
{
"messages": [
HumanMessage(
content=[
{
"type": "file",
"mime_type": "text/csv",
"base64": csv_data,
},
{
"type": "text",
"text": (
"Create a pie chart showing sales by region and "
"return it as a PNG image."
),
},
]
)
]
}
)
pretty_print(response)
================================ Human Message =================================
[
{'type': 'file', 'mime_type': 'text/csv', 'base64': '77u/bW9udG...xTb3V0aAo='},
{'type': 'text', 'text': 'create a pie chart with the data showing sales by region and show it to me as a png image.'}
]
================================== Ai Message ==================================
Name: code-interpreter-agent
[
{'type': 'text', 'text': 'Here is the pie chart showing sales by region as a PNG image:\n\n[Download the Pie Chart](sandbox:/mnt/data/sales_by_region_pie.png)'},
{'type': 'image', 'mime_type': 'image/png', 'base64': 'iVBORw0...ErkJggg=='}
]
範例:使用影像生成工具
在執行此範例前,請確認你的專案有一個名為 gpt-image-1.5的部署。 以下範例展示了如何使用 ImageGenTool 進行影像生成:
from langchain_azure_ai.agents.prebuilt.tools import ImageGenTool
image_agent = factory.create_prompt_agent(
name="image-generator-agent",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
instructions=(
"You are an image generation assistant. You receive a text prompt and "
"must generate an image by using the configured tool."
),
tools=[ImageGenTool(model_deployment="gpt-image-1.5", quality="medium")],
)
response = image_agent.invoke(
{"messages": [HumanMessage("Generate an image of a sunset over mountains.")]}
)
pretty_print(response)
================================ Human Message =================================
Generate an image of a sunset over the mountains.
================================== Ai Message ==================================
Name: image-generator-agent
使用其他內建工具
任何 Foundry Agent Service 工具都可以搭配 create_prompt_agent 使用。 使用 AgentServiceBaseTool 將 Azure AI Projects SDK 中的工具包裝並附加到你的提示代理上。
在執行這個範例之前,請確認你的專案中有向量儲存 ID。 將 ID 設為環境變數:
export VECTOR_STORE_ID="<vector-store-id>"
以下範例顯示了如何使用FileSearchTool
from azure.ai.projects.models import FileSearchTool
from langchain_azure_ai.agents.prebuilt.tools import AgentServiceBaseTool
file_search_agent = factory.create_prompt_agent(
name="file-search-agent",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
instructions=(
"You are a helpful agent with access to a file search tool over a "
"vector store."
),
tools=[
AgentServiceBaseTool(
tool=FileSearchTool(
vector_store_ids=[os.environ["VECTOR_STORE_ID"]]
),
)
],
)
print(factory.get_agents_id_from_graph(file_search_agent))
{'file-search-agent:1'}
人機互動
Foundry 中的某些工具內建了審核流程,例如 MCPTool。 你可以要求在伺服器上執行特定工具呼叫前取得批准。
此方法 create_prompt_agent 實作了 LangGraph 建議的模式,在圖中引入一個批准節點:
以下範例示範如何正確使用 MCPTool :
from langchain_azure_ai.agents.prebuilt.tools import MCPTool
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import Command
mcp_agent = factory.create_prompt_agent(
name="mcp-github-specs-agent",
model=os.environ["MODEL_DEPLOYMENT_NAME"],
instructions=(
"Use the available MCP tool to answer every request. "
"Don't answer from your existing knowledge."
),
tools=[
MCPTool(
server_label="api-specs",
server_url="https://gitmcp.io/Azure/azure-rest-api-specs",
require_approval="always",
)
],
checkpointer=MemorySaver(),
)
config = {"configurable": {"thread_id": "mcp-session-1"}}
response = mcp_agent.invoke(
input={
"messages": [
HumanMessage(
"Use the MCP tool to find the APIs available for Azure Cosmos DB."
)
]
},
config=config,
)
pretty_print(response)
================================ Human Message =================================
Use the MCP tool to find the APIs available for Azure Cosmos DB.
================================== Ai Message ==================================
Tool Calls:
mcp_approval_request (mcpr_74e314080483acce0069a11d2d9f008190a971212ac61d76d8)
Call ID: mcpr_74e314080483acce0069a11d2d9f008190a971212ac61d76d8
Args:
server_label: api-specs
name: search_azure_rest_api_docs
arguments: {"query":"Cosmos DB APIs"}
================================== Interrupt ==================================
Interrupt ID: c3cb23363f91d097298fb3c6f8fbf70a
Interrupt Value:
Tool Call ID: mcpr_74e314080483acce0069a11d2d9f008190a971212ac61d76d8
Server Label: api-specs
Tool Name: search_azure_rest_api_docs
Arguments: {"query":"Cosmos DB APIs"}
在 LangGraph 中使用 Command 發送核准:
response = mcp_agent.invoke(Command(resume={"approve": True}), config)
pretty_print(response)
================================ Human Message =================================
Use the MCP tool to find the APIs available for Azure Cosmos DB.
================================== Ai Message ==================================
Tool Calls:
mcp_approval_request (mcpr_74e314080483acce0069a11d2d9f008190a971212ac61d76d8)
Call ID: mcpr_74e314080483acce0069a11d2d9f008190a971212ac61d76d8
Args:
server_label: api-specs
name: search_azure_rest_api_docs
arguments: {"query":"Cosmos DB APIs"}
================================= Tool Message =================================
{"approve": true}
================================== Ai Message ==================================
Name: mcp-github-specs-agent
Azure Cosmos DB supports multiple APIs, ...
可觀察性
當你使用 Foundry Agent Service 和 LangGraph 組合解決方案時,有些部分會在 Agent Service 執行,而其他部分則在程式碼執行處執行。
此類別 AzureAIOpenTelemetryTracer 允許你追蹤以 LangGraph 建構的端到端解決方案,這些解決方案使用 OpenTelemetry 標準,由代理服務支援。
要追蹤你的程式碼,請使用:
from langchain_azure_ai.callbacks.tracers import AzureAIOpenTelemetryTracer
tracer = AzureAIOpenTelemetryTracer(
agent_id="mcp-github-specs-agent-langgraph"
)
mcp_agent = mcp_agent.with_config({"callbacks": [tracer]})
此片段的功能: 建立一個 AzureAIOpenTelemetryTracer 實例,使用 OpenTelemetry 標準將追蹤傳送至 Azure 應用程式 Insights。 它會設定 agent_id 參數,透過在 gen_ai.agent.id 類型的 span 中設定 屬性來識別追蹤。
AzureAIOpenTelemetryTracer 需要一個連接字串來連線至 Azure 應用程式 Insights。 在這種情況下,沒有顯示是因為你設定了環境變數 AZURE_AI_PROJECT_ENDPOINT,該類別可以使用此變數來偵測與專案相關聯的 Azure 應用程式 Insights 的連接字串。 你可以傳遞任何需要的連線字串。
要查看痕跡,重要的是要了解這裡有 兩個代理人 :
- Foundry 代理程式,是圖形中某個節點的後端程式。
- 整個 LangGraph 圖,由多個節點組成。
你可以使用 Foundry 入口查看 Foundry 代理的追蹤,但在開發時要查看 LangGraph 代理的追蹤,必須在 Azure 入口中使用 Azure 監視器。
提示
LangChain 和 LangGraph 應用程式可在 Foundry Control Plane 註冊以進行治理。 接著,你可以用 Foundry 平台 查看追蹤記錄。 請參閱在 Foundry 控制平面中檢視追蹤。
若要查看追蹤,請使用 Azure 監視器:
前往Azure入口。
導航到你設定的 Azure 應用程式 Insights。
在左側導覽欄中,選擇 「調查>代理人(預覽)」。
你會看到一個儀表板,顯示代理、模型和工具的執行情況。 使用此視圖來了解您的代理人的整體狀況。
選取使用 Agent 執行作業檢視追蹤。。 側面板顯示所有由代理執行產生的痕跡。
選擇一條走線。 你應該看看細節。
注意對話中涉及到兩位代理人:代理人
foundryAgent以及名為mcp-github-specs-agent-langgraph的代理人。
清理代理程式
刪除你在樣本中建立的代理,以避免留下未使用的資源。
只刪除您在工作階段中建立的 Agent。
for variable_name in (
"math_agent",
"document_parser_agent",
"image_agent",
"code_interpreter_agent",
"mcp_agent",
"file_search_agent",
):
created_agent = locals().get(variable_name)
if created_agent is not None:
factory.delete_agent(created_agent)
重要
刪除後,LangGraph 物件將無法再使用。
故障排除
使用此清單來診斷使用代理服務時 langchain-azure-ai 常見的問題。
啟用診斷日誌
先開啟除錯日誌,這樣你才能檢查認證、請求流程和工具執行細節。
import logging
logging.getLogger("langchain_azure_ai").setLevel(logging.DEBUG)
如果你需要更多細節,請增加記錄,納入其他函式庫:
import logging
logging.basicConfig(level=logging.DEBUG)
及早驗證設定
- 確認
AZURE_AI_PROJECT_ENDPOINT指向正確的專案端點,你正在使用一個帶有新體驗的 Foundry 專案。 - 確認
MODEL_DEPLOYMENT_NAME與現有部署模型相符。 - 使用
az account show驗證身份驗證上下文。 - 先用一個簡潔
create_prompt_agent的例子。
驗證資源與權限存取
- 確保你的帳號能存取 Foundry 專案和模型部署。
- 確保下游相依關係(例如向量儲存或工具資源)存在且可被存取。
- 如果工具需要特定資源類型,請確認該資源是否配置在正確的訂閱和區域。
解決工具執行錯誤
- 如果 Code Interpreter 回傳回應
400,請重新嘗試該請求。 如果錯誤持續,請確認專案區域和聊天模式是否支援 Code Interpreter。 - 若影像生成功能傳回
DeploymentNotFound,請在專案中部署gpt-image-1.5,或將model_deployment更新為現有映像模型部署的名稱。 - 如果 MCP 請求沒有暫停以等待核准,請在提示詞中明確要求使用 MCP 工具。 只有模特兒選擇工具時才會進行核准。
使用 Foundry 記憶體搭配 LangChain 和 LangGraph