nodejs/langchain: add Word @mention (WpxComment) support#312
Conversation
Wires the LangChain sample so that a Word `@mention` on a document comment
flows through `mcp_WordServer` and is answered with a single reply on the
same thread, with an optional proactive Teams DM to the mentioner.
- ToolingManifest.json: register `mcp_WordServer`.
- src/agent.ts:
- enable `proactive: {}` on `AgentApplication`.
- track Teams conversations by user key on every message turn and on
InstallationUpdate(add), so a later WpxComment can be routed back to
the same 1:1 chat.
- handle `NotificationType.WpxComment`: extract document URL from
`activity.attachments`, prompt the LLM to call `GetDocumentContent`
and the reply tool (not `AddComment`), and proactively notify the
mentioner in Teams with the reply text.
- stop printing the truncated Observability token prefix.
- src/client.ts: add a LangGraph `MemorySaver` checkpointer keyed by
`conversation.id` so multi-turn comment threads keep their tool-call
history.
<noreply@anthropic.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
- mcp_MailTools: switch to the v2 endpoint, Tools.ListInvoke.All scope, new audience, and add publisher. - mcp_OneDriveRemoteServer: register so the @mention flow can resolve Word documents stored on OneDrive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The Word notification flow still logs potentially sensitive document data:
That is a privacy footgun for a sample that handles Word documents and user comments, especially since this same change removes the Observability token prefix from logs. It would be safer to log only stable metadata such as |
There was a problem hiding this comment.
Pull request overview
Adds Word comment @mention (NotificationType.WpxComment) handling to the Node.js LangChain sample so the agent can read the referenced Word document via MCP, post a reply on the existing comment thread, and (optionally) send a proactive Teams 1:1 message back to the mentioner. Also introduces conversation-scoped LangGraph checkpointing to preserve tool-call history across multi-turn threads.
Changes:
- Register
mcp_WordServerin the sample’sToolingManifest.json. - Add
WpxCommentnotification handling insrc/agent.ts, including proactive Teams DM routing based on stored conversation references. - Add a process-wide LangGraph
MemorySavercheckpointer insrc/client.ts, keyed byconversation.idviathread_id.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| nodejs/langchain/sample-agent/ToolingManifest.json | Registers the Word MCP server for tool discovery/auth. |
| nodejs/langchain/sample-agent/src/client.ts | Adds LangGraph MemorySaver checkpointer support keyed by conversation thread. |
| nodejs/langchain/sample-agent/src/agent.ts | Implements NotificationType.WpxComment flow + proactive Teams DM routing and removes token-prefix logging. |
| "scope": "Tools.ListInvoke.All", | ||
| "audience": "c2d0c2b6-8013-4346-9f8b-b81d3b754a29", |
| function userKeysFor(from: any): string[] { | ||
| if (!from) return []; | ||
| const keys = new Set<string>(); | ||
| if (from.aadObjectId) keys.add(`aad:${String(from.aadObjectId).toLowerCase()}`); | ||
| if (from.id) keys.add(`id:${String(from.id).toLowerCase()}`); | ||
| if (from.name) keys.add(`name:${String(from.name).toLowerCase()}`); | ||
| return [...keys]; |
| const keys = new Set<string>(); | ||
| if (from.aadObjectId) keys.add(`aad:${String(from.aadObjectId).toLowerCase()}`); | ||
| if (from.id) keys.add(`id:${String(from.id).toLowerCase()}`); | ||
| if (from.name) keys.add(`name:${String(from.name).toLowerCase()}`); |
| // Maps a user "key" (aadObjectId / id / name) → proactive conversation ID, so | ||
| // the WpxComment handler can post a Teams DM back to whichever user @mentioned | ||
| // the agent. In-process only — survives the process lifetime; for prod, persist. | ||
| const userKeyToConversationId = new Map<string, string>(); | ||
|
|
| const documentUrl: string | undefined = fileAttachment?.contentUrl; | ||
| const documentName: string = fileAttachment?.name ?? 'the document'; | ||
| const commentText: string = (context.activity as any)?.text ?? ''; | ||
| const senderName = context.activity.from?.name ?? 'a user'; | ||
|
|
||
| console.log(`WpxComment received — sender='${senderName}', documentName='${documentName}', documentUrl='${documentUrl ?? '(none)'}', commentText='${commentText.substring(0, 200)}', documentId='${wpx.documentId}', initiatingCommentId='${wpx.initiatingCommentId}'`); |
| console.log(`WpxComment received — sender='${senderName}', documentName='${documentName}', documentUrl='${documentUrl ?? '(none)'}', commentText='${commentText.substring(0, 200)}', documentId='${wpx.documentId}', initiatingCommentId='${wpx.initiatingCommentId}'`); | ||
|
|
||
| try { | ||
| const client: Client = await getClient(this.authorization, A365Agent.authHandlerName, context); |
Summary
mcp_WordServerMCP server inToolingManifest.jsonso the LangChain sample has Word read/reply tools available.NotificationType.WpxCommentinagent.ts: extracts the document URL fromactivity.attachments, asks the LLM to callmcp_WordServer.GetDocumentContentand the Word reply tool (notAddComment), and proactively notifies the @mentioner in their Teams 1:1 chat with the reply text.MemorySavercheckpointer inclient.tskeyed byconversation.idso multi-turn comment threads keep their tool-call history.Notes
InstallationUpdate(add).preloadObservabilityTokenlog line — tokens (even partial) should not be logged.Test plan
npm run buildinnodejs/langchain/sample-agent