Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This tutorial demonstrates how to add agentic capability to an existing data-driven Express.js CRUD application. It does this using two different approaches: LangGraph and Azure AI Foundry Agent Service.
If your web application already has useful features, like shopping, hotel booking, or data management, it's relatively straightforward to add agent functionality to your web application by wrapping those functionalities in a plugin (for LangGraph) or as an OpenAPI endpoint (for AI Foundry Agent Service). In this tutorial, you start with a simple to-do list app. By the end, you'll be able to create, update, and manage tasks with an agent in an App Service app.
Both LangGraph and Azure AI Foundry Agent Service enable you to build agentic web applications with AI-driven capabilities. LangGraph is similar to Microsoft Semantic Kernel and is an SDK, but Semantic Kernel doesn't support JavaScript currently. The following table shows some of the considerations and trade-offs:
Consideration | LangGraph | Azure AI Foundry Agent Service |
---|---|---|
Performance | Fast (runs locally) | Slower (managed, remote service) |
Development | Full code, maximum control | Low code, rapid integration |
Testing | Manual/unit tests in code | Built-in playground for quick testing |
Scalability | App-managed | Azure-managed, autoscaled |
In this tutorial, you learn how to:
- Convert existing app functionality into a plugin for LangGraph.
- Add the plugin to a LangGraph agent and use it in a web app.
- Convert existing app functionaltiy into an OpenAPI endpoint for Azure AI Foundry Agent Service.
- Call an Azure AI Foundry agent in a web app.
- Assign the required permissions for managed identity connectivity.
Prerequisites
- An Azure account with an active subscription - Create an account for free.
- GitHub account to use GitHub Codespaces - Learn more about GitHub Codespaces.
Open the sample with Codespaces
The easiest way to get started is by using GitHub Codespaces, which provides a complete development environment with all required tools preinstalled.
Navigate to the GitHub repository at https://github.com/Azure-Samples/app-service-agentic-langgraph-foundry-node.
Select the Code button, select the Codespaces tab, and select Create codespace on main.
Wait a few moments for your Codespace to initialize. When ready, you'll see a fully configured development environment in your browser.
Run the application locally:
npm install npm run build npm start
When you see Your application running on port 3000 is available, select Open in Browser and add a few tasks.
Review the agent code
Both approaches use the same implementation pattern, where the agent is initialized on application start, and responds to user messages by POST requests.
The LangGraphTaskAgent
is initialized in the constructor in src/agents/LangGraphTaskAgent.ts. The initialization code does the following:
- Configures the AzureChatOpenAI client using environment variables.
- Creates the prebuilt ReAct agent a set of CRUD tools for task management (see LangGraph: How to use the prebuilt ReAct agent).
- Sets up memory management (see LangGraph: How to add memory to the prebuilt ReAct agent).
constructor(taskService: TaskService) {
this.taskService = taskService;
this.memory = new MemorySaver();
try {
const endpoint = process.env.AZURE_OPENAI_ENDPOINT;
const deploymentName = process.env.AZURE_OPENAI_DEPLOYMENT_NAME;
if (!endpoint || !deploymentName) {
console.warn('Azure OpenAI configuration missing for LangGraph agent');
return;
}
// Initialize Azure OpenAI client
const credential = new DefaultAzureCredential();
const azureADTokenProvider = getBearerTokenProvider(credential, "https://cognitiveservices.azure.com/.default");
this.llm = new AzureChatOpenAI({
azureOpenAIEndpoint: endpoint,
azureOpenAIApiDeploymentName: deploymentName,
azureADTokenProvider: azureADTokenProvider,
azureOpenAIApiVersion: "2024-10-21"
});
// Define tools directly in the array
const tools = [
tool(
async ({ title, isComplete = false }) => {
const task = await this.taskService.addTask(title, isComplete);
return `Task created successfully: "${task.title}" (ID: ${task.id})`;
},
{
name: 'createTask',
description: 'Create a new task',
schema: z.object({
title: z.string(),
isComplete: z.boolean().optional()
}) as any
}
),
tool(
async () => {
const tasks = await this.taskService.getAllTasks();
if (tasks.length === 0) {
return 'No tasks found.';
}
return `Found ${tasks.length} tasks:\n` +
tasks.map(t => `- ${t.id}: ${t.title} (${t.isComplete ? 'Complete' : 'Incomplete'})`).join('\n');
},
{
name: 'getTasks',
description: 'Get all tasks',
schema: z.object({}) as any
}
),
tool(
async ({ id }) => {
const task = await this.taskService.getTaskById(id);
if (!task) {
return `Task with ID ${id} not found.`;
}
return `Task ${task.id}: "${task.title}" - Status: ${task.isComplete ? 'Complete' : 'Incomplete'}`;
},
{
name: 'getTask',
description: 'Get a specific task by ID',
schema: z.object({
id: z.number()
}) as any
}
),
tool(
async ({ id, title, isComplete }) => {
const updated = await this.taskService.updateTask(id, title, isComplete);
if (!updated) {
return `Task with ID ${id} not found.`;
}
return `Task ${id} updated successfully.`;
},
{
name: 'updateTask',
description: 'Update an existing task',
schema: z.object({
id: z.number(),
title: z.string().optional(),
isComplete: z.boolean().optional()
}) as any
}
),
tool(
async ({ id }) => {
const deleted = await this.taskService.deleteTask(id);
if (!deleted) {
return `Task with ID ${id} not found.`;
}
return `Task ${id} deleted successfully.`;
},
{
name: 'deleteTask',
description: 'Delete a task',
schema: z.object({
id: z.number()
}) as any
}
)
];
// Create the ReAct agent with memory
this.agent = createReactAgent({
llm: this.llm,
tools,
checkpointSaver: this.memory,
stateModifier: `You are an AI assistant that manages tasks using CRUD operations.
You have access to tools for creating, reading, updating, and deleting tasks.
Always use the appropriate tool for any task management request.
Be helpful and provide clear responses about the actions you take.
If you need more information to complete a request, ask the user for it.`
});
} catch (error) {
console.error('Error initializing LangGraph agent:', error);
}
}
Deploy the sample application
The sample repository contains an Azure Developer CLI (AZD) template, which creates an App Service app with managed identity and deploys your sample application.
In the terminal, log into Azure using Azure Developer CLI:
azd auth login
Follow the instructions to complete the authentication process.
Deploy the Azure App Service app with the AZD template:
azd up
When prompted, give the following answers:
Question Answer Enter a new environment name: Type a unique name. Select an Azure Subscription to use: Select the subscription. Pick a resource group to use: Select Create a new resource group. Select a location to create the resource group in: Select any region. The resources will actually be created in East US 2. Enter a name for the new resource group: Type Enter. In the AZD output, find the URL of your app and navigate to it in the browser. The URL looks like this in the AZD output:
Deploying services (azd deploy) (✓) Done: Deploying service web - Endpoint: <URL>
Select the OpenAPI schema item to open the autogenerated OpenAPI schema at the default
/api/schema
path. You need this schema later.After successful deployment, you'll see a URL for your deployed application.
You now have an App Service app with a system-assigned managed identity.
Create and configure the Azure AI Foundry resource
In the Azure AI Foundry portal, deploy a model of your choice (see Quickstart: Get started with Azure AI Foundry). A project and a default agent are created for you in the process.
From the left menu, select Overview.
Select Azure AI Foundry and copy the URL in Azure AI Foundry project endpoint.
Select Azure OpenAI and copy the URL in Azure OpenAI endpoint for later.
From the left menu, select Agents, then select the default agent.
From the Setup pane, copy Agent ID, as well as the model name in Deployment.
In the Setup pane, add an action with the OpenAPI spec tool. Use the OpenAPI schema that you get from the deployed web app and anonymous authentication. For detailed steps, see How to use the OpenAPI spec tool.
Your application code is already configured to include the server's
url
andoperationId
, which are needed by the agent. For more information, see How to use Azure AI Foundry Agent Service with OpenAPI Specified Tools: Prerequisites.Select Try in playground and test your AI Foundry agent with prompts like "Show me all the tasks."
If you get a valid response, the agent is making tool calls to the OpenAPI endpoint on your deployed web app.
Assign required permissions
At the upper right corner of the foundry portal, select the name of the resource, then select Resource Group to open it in the Azure portal.
Add a role for each of the two resources for the App Service app's manage identity using the following table:
Target resource Required role Needed for Azure AI Foundry Cognitive Services OpenAI User The chat completion service in the LangGraph. Azure AI Foundry Project Azure AI User Reading and calling the AI Foundry agent. For instructions, see Assign Azure roles using the Azure portal.
Configure connection variables in your sample application
Open .env. Using the values you copied earlier from the AI Foundry portal, configure the following variables:
Variable Description AZURE_OPENAI_ENDPOINT
Azure OpenAI endpoint (copied from the Overview page). This is needed by the LangGraph agent. AZURE_OPENAI_DEPLOYMENT_NAME
Model name in the deployment (copied from the Agents setup pane). This is needed by the LangGraph agent. AZURE_AI_FOUNDRY_PROJECT_ENDPOINT
Azure AI Foundry project endpoint (copied from Overview page). This is needed for the Azure AI Foundry Agent Service. AZURE_AI_FOUNDRY_AGENT_ID
Agent ID (copied from the Agents setup pane). This is needed to invoke an existing Azure AI Foundry agent. Note
To keep the tutorial simple, you'll use these variables in .env instead of overwriting them with app settings in App Service.
Sign in to Azure with the Azure CLI:
az login
This allows the Azure Identity client library in the sample code to receive an authentication token for the logged in user. Remember that you added the required role for this user earlier.
Run the application locally:
npm run build npm start
When you see Your application running on port 3000 is available, select Open in Browser.
Select the LangGraph Agent link and the Foundry Agent link to try out the chat interface. If you get a response, your application is connecting successfully to the Azure AI Foundry resource.
Back in the GitHub codespace, deploy your app changes.
azd up
Navigate to the deployed application again and test the chat agents.
Clean up resources
When you're done with the application, you can delete the App Service resources to avoid incurring further costs:
azd down --purge
Since the AZD template doesn't include the Azure AI Foundry resources, you need to delete them manually if you want.