LangGraph gives you fine-grained control over agent state and routing logic in code. Microsoft Foundry gives you managed hosting, identity, tracing, and one-click publishing to Teams and M365 Copilot. Increasingly, teams want both: LangGraph's graph-based orchestration for the hard routing logic, and Foundry's operational layer for everything downstream of "it works on my machine." This is a from-scratch walkthrough of wiring the two together — building a small multi-agent support triage system in LangGraph, then hosting it as a Foundry Hosted Agent. Architecture The system has three LangGraph nodes: a triage node that classifies the incoming request, and two specialist nodes (billing, technical) that the triage node routes to conditionally. Once this graph is compiled, it doesn't run as a standalone script — it gets wrapped and exposed through Foundry's hosting layer, which handles the runtime, session management, and identity so the graph itself stays free of infrastructure concerns. Step 1: Define the graph state and nodes from typing import TypedDict, Literal from langgraph.graph import StateGraph, END from langchain_azure_ai.chat_models import AzureAIChatCompletionsModel import os class TicketState(TypedDict): user_input: str ticket_type: Literal["billing", "technical", ""] response: str model = AzureAIChatCompletionsModel( endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], model=os.environ["FOUNDRY_MODEL_NAME"], ) def triage_node(state: TicketState) -> TicketState: result = model.invoke( f"Classify this support ticket as 'billing' or 'technical' only: {state['user_input']}" ) ticket_type = "billing" if "billing" in result.content.lower() else "technical" return {**state, "ticket_type": ticket_type} def billing_node(state: TicketState) -> TicketState: result = model.invoke(f"You are a billing specialist. Resolve: {state['user_input']}") return {**state, "response": result.content} def technical_node(state: TicketState) -> TicketState: result = model.invoke(f"You are a technical specialist. Resolve: {state['user_input']}") return {**state, "response": result.content} Enter fullscreen mode Exit fullscreen mode Step 2: Wire the conditional routing def route(state: TicketState) -> str: return state["ticket_type"] graph = StateGraph(TicketState) graph.add_node("triage", triage_node) graph.add_node("billing", billing_node) graph.add_node("technical", technical_node) graph.set_entry_point("triage") graph.add_conditional_edges("triage", route, {"billing": "billing", "technical": "technical"}) graph.add_edge("billing", END) graph.add_edge("technical", END) compiled_graph = graph.compile() Enter fullscreen mode Exit fullscreen mode Notice the model calls point at FOUNDRY_PROJECT_ENDPOINT, not directly at Azure OpenAI or any single provider's SDK. This is what lets the same graph run locally against a Foundry project and later behind the hosted runtime without changing model-calling code. Step 3: Expose the graph for Foundry hosting Foundry's langchain_azure_ai.agents.hosting package wraps a compiled LangGraph graph so it can be deployed as a Hosted Agent, speaking either the Responses or Invocations protocol. from langchain_azure_ai.agents.hosting import LangGraphResponsesHost host = LangGraphResponsesHost(graph=compiled_graph) app = host.create_app() Enter fullscreen mode Exit fullscreen mode That app is what gets deployed — Foundry manages the runtime, session handling, and scaling from there. Locally you can run it with uvicorn app:app --reload and test over HTTP before deploying with azd ai agent deploy or the Foundry Toolkit extension for VS Code. Local tools vs. built-in tools One distinction that trips people up: LangGraph tools you attach in code run locally, colocated with your graph. Foundry's own built-in tools (file search, code interpreter, etc.) run server-side inside the Agent Service and don't add a node to your graph at all — they're invoked transparently when the service handles a request. Aspect Local (LangGraph) tools Built-in Foundry tools Execution location Colocated with your graph process Server-side in Foundry Agent Service Graph representation Adds a tool node No node added Applicable to Any LangGraph/LangChain tool Foundry agents only Best for Deterministic business logic, custom APIs File search, code interpreter, managed retrieval Tracing across two systems Because the LangGraph portion runs outside Foundry's native agent runtime during local development, its traces don't automatically appear in the Foundry portal. You view LangGraph-level traces through Azure Monitor / Application Insights (Investigate → Agents), while Foundry-native agent traces show up directly in the Foundry portal. Once deployed as a Hosted Agent, LangChain and LangGraph applications can also be registered in the Foundry Control Plane for unified governance and trace visibility. What this buys you in production Once deployed, the same graph becomes available as a turnkey Application across Teams, M365 Copilot, and Bot Service channels without additional publishing code — Foundry handles the channel plumbing, while your LangGraph code stays focused purely on routing and reasoning logic. References Use LangGraph with the Agent Service — Microsoft Learn Host LangGraph agents as Foundry hosted agents — Microsoft Learn Agent-to-Agent Communication: Connecting Foundry and LangGraph Agents via A2A — Microsoft Community Hub LangGraph Agents: Deploy as Hosted Agents in Microsoft Foundry — Srikantan Sankaran From Local to Production: The Complete Developer Journey — Microsoft Foundry Blog
Building a Stateful Multi-Agent System with LangGraph and Microsoft Foundry Agent Service, From Scratch
Full Article
Original Source
Read the full article at Dev →KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.