LangChain Sample Agent - Node.js
This sample demonstrates how to build an agent using LangChain in Node.js with the Microsoft Agent 365 SDK. It covers:
- Observability: End-to-end tracing, caching, and monitoring for agent applications
- Notifications: Services and models for managing user notifications
- Tools: Model Context Protocol tools for building advanced agent solutions
- Hosting Patterns: Hosting with Microsoft 365 Agents SDK
This sample uses the Microsoft Agent 365 SDK for Node.js.
For comprehensive documentation and guidance on building agents with the Microsoft Agent 365 SDK, including how to add tooling, observability, and notifications, visit the Microsoft Agent 365 Developer Documentation.
Prerequisites
To run the template in your local dev machine, you will need:
- Node.js, supported versions: 18.x or higher
- Microsoft 365 Agents Toolkit Visual Studio Code Extension latest version
- Prepare your own Azure/openAI API credentials
- Azure CLI signed in with
az login
- Microsoft Agent 365 SDK
- LangChain 1.0.1 or higher
- A365 CLI: Required for agent deployment and management.
Configuration
Observability export
src/index.ts imports the observability bootstrap first. With
useS2SEndpoint: true and the app-only tokenResolver, OBS posts to
/observabilityService/tenants/{tenant}/otlp/agents/{agent}/traces?api-version=1.
The resolver uses AGENT365_OBS_TENANT_ID, AGENT365_OBS_AGENT_ID,
AGENT365_OBS_BLUEPRINT_CLIENT_ID, and AGENT365_OBS_BLUEPRINT_CLIENT_SECRET;
AGENT365_OBS_AGENT_ID must be the actual agent instance client ID. Business MCP,
Graph, and OBO calls remain separate from OBS authentication.
Single-instance limitation: this resolver exports for one statically configured
agent instance and tenant (AGENT365_OBS_*). It needs its own copy of the
blueprint secret and has no managed-identity option. Multi-instance or multi-tenant
deployments should reuse the hosting connection per agent/tenant instead of sharing
this static provider.
Sovereign clouds are not supported by this sample provider because the authority is
hard-coded to login.microsoftonline.com. For AI Teammates, complete the
Agent365.Observability.OtelWrite application-role step printed by
a365 setup all --aiteammate; AI Teammate S2S without it has not been validated.
Running the Agent in Microsoft 365 Agents Playground
- First, select the Microsoft 365 Agents Toolkit icon on the left in the VS Code toolbar.
- In file env/.env.playground.user, fill in your Azure OpenAI key
SECRET_AZURE_OPENAI_API_KEY=<your-key>, endpointAZURE_OPENAI_ENDPOINT=<your-endpoint>, and deployment nameAZURE_OPENAI_DEPLOYMENT_NAME=<your-deployment>if you're using Azure OpenAI. - In file env/.env.playground.user, fill in your OpenAI key
SECRET_OPENAI_API_KEY=<your-key>if you're using OpenAI. - In file env/.env.playground, fill in your custom app registration client id
CLIENT_APP_ID. - Press F5 to start debugging which launches your agent in Microsoft 365 Agents Playground using a web browser. Select
Debug in Microsoft 365 Agents Playground. - You can send any message to get a response from the agent.
Congratulations! You are running an agent that can now interact with users in Microsoft 365 Agents Playground.
Handling Agent Install and Uninstall
When a user installs (hires) or uninstalls (removes) the agent, the A365 platform sends an InstallationUpdate activity — also referred to as the agentInstanceCreated event. The sample handles this in handleInstallationUpdateActivity (agent.ts):
| Action | Description |
|---|---|
add |
Agent was installed — send a welcome message |
remove |
Agent was uninstalled — send a farewell message |
if (context.activity.action === 'add') {
await context.sendActivity('Thank you for hiring me! Looking forward to assisting you in your professional journey!');
} else if (context.activity.action === 'remove') {
await context.sendActivity('Thank you for your time, I enjoyed working with you.');
}
To test with Agents Playground, use Mock an Activity → Install application to send a simulated installationUpdate activity.
Sending Multiple Messages in Teams
Agent365 agents can send multiple discrete messages in response to a single user prompt in Teams. This is achieved by calling sendActivity multiple times within a single turn.
Important: Streaming responses are not supported for agentic identities in Teams. The SDK detects agentic identity and buffers the stream into a single message. Use
sendActivitydirectly to send immediate, discrete messages to the user.
The sample demonstrates this in handleAgentMessageActivity (agent.ts):
// Message 1: immediate ack — reaches the user right away
await turnContext.sendActivity('Got it — working on it…');
// ... LLM processing ...
// Message 2: the LLM response
await turnContext.sendActivity(response);
Each sendActivity call produces a separate Teams message. You can call it as many times as needed to send progress updates, partial results, or a final answer.
Typing Indicators
The agent sends typing indicators in a loop every ~4 seconds to keep the ... animation alive while the LLM processes the request:
let typingInterval: ReturnType<typeof setInterval> | undefined;
const startTypingLoop = () => {
typingInterval = setInterval(async () => {
await turnContext.sendActivity({ type: 'typing' } as Activity);
}, 4000);
};
const stopTypingLoop = () => { clearInterval(typingInterval); };
startTypingLoop();
try {
// ... LLM processing ...
} finally {
stopTypingLoop();
}
Note: Typing indicators are only visible in 1:1 chats and small group chats — not in channels.
Running the Agent
To set up and test this agent, refer to the Configure Agent Testing guide for complete instructions. For a detailed explanation of the agent code and implementation, see the Agent Code Walkthrough.
Support
For issues, questions, or feedback:
- Issues: Please file issues in the GitHub Issues section
- Documentation: See the Microsoft Agents 365 Developer documentation
- Security: For security issues, please see SECURITY.md
Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
Additional Resources
- Microsoft Agent 365 SDK - Node.js repository
- Microsoft 365 Agents SDK - Node.js repository
- LangChain documentation
- Node.js API documentation
Trademarks
Microsoft, Windows, Microsoft Azure and/or other Microsoft products and services referenced in the documentation may be either trademarks or registered trademarks of Microsoft in the United States and/or other countries. The licenses for this project do not grant you rights to use any Microsoft names, logos, or trademarks. Microsoft's general trademark guidelines can be found at http://go.microsoft.com/fwlink/?LinkID=254653.
License
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License - see the LICENSE file for details.