Render Anthropic reasoning traces from Microsoft 365 Copilot Studio agents inside your own UI. This README distills the companion article posted on MCS CAT blog.
- Strengthen trust in automated or assisted decisions.
- Give operators visibility into multi-step, decision-heavy workflows.
- Help end users judge the suitability of an answer before acting on it.
The reference sample (static HTML + JS) simulates an organization triaging monday.com tickets with an Anthropic-enabled Copilot Studio agent. Submitting a new ticket shows incremental reasoning as typing activities, and near-duplicate tickets are merged automatically instead of duplicated.
- Copilot Studio agent configured with an Anthropic model (Settings -> Agent model).
- Custom UI wired to the Microsoft 365 Agents SDK.
- Optional backend summarization endpoint to shorten verbose reasoning (recommended for UX). GPT-family models do not yet emit reasoning traces.
- Initialize the client
import { CopilotStudioClient } from '@microsoft/agents-copilotstudio-client'; import { acquireToken } from './acquireToken.js'; import { settings } from './settings.js'; export const createCopilotClient = async () => { const token = await acquireToken(settings); return new CopilotStudioClient(settings, token); };
- Start a conversation
const copilotClient = await createCopilotClient(); let conversationId; for await (const act of copilotClient.startConversationAsync(true)) { conversationId = act.conversation?.id ?? conversationId; if (conversationId) break; }
- Send a prompt
const prompt = `Create the following ticket:\n\nTitle: ${shortTitle}\nDescription: ${longDescription}`; const activityStream = copilotClient.askQuestionAsync(prompt, conversationId);
- Capture reasoning and answers
for await (const activity of activityStream) { if (!activity) continue; const activityType = activity.type?.toLowerCase(); if (activityType === 'typing' && activity.channelData?.streamType === 'informative') { const streamKey = resolveStreamKey(activity); const previousActivity = streamLastActivity.get(streamKey); if (previousActivity && isContinuationOfPrevious(previousActivity, activity)) { streamLastActivity.set(streamKey, activity); continue; } await flushActivity(previousActivity, false); streamLastActivity.set(streamKey, activity); continue; } if (activityType === 'message') { agentMessages.push(activity.text); continue; } }
const isReasoningTyping = (activity) =>
(activity?.type || '').toLowerCase() === 'typing' &&
activity?.channelData?.streamType === 'informative';Reasoning chunks can be lengthy. Capture completed thoughts and optionally POST them to a backend summarizer:
async function summarizeSafely(text) {
try {
const res = await fetch('/api/summarize', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
const { summary } = await res.json();
return summary.trim();
} catch {
return null;
}
}Keep API keys server-side and apply rate limiting. The sample UI exposes an input control so end users can supply their summarizer key during demos.
- Show a calm, rotating status label once users submit a ticket (for example, "Reviewing possible options...").
- Keep the spinner visible while informative typing events are active.
- Prepend the newest summarized reasoning to the top, keeping the latest five items.
- Add a subtle entrance animation and collapse the panel once the final answer arrives, with an optional "Show details" toggle.
- Switch your agent to an Anthropic model.
- Iterate the Microsoft 365 Agents SDK activity stream.
- Detect reasoning via
type === 'typing'andchannelData.streamType === 'informative'. - Group reasoning chunks by
channelData.streamId. - Flush pending reasoning when you receive the final message.
- Optionally summarize server-side to protect secrets.
- Render a compact Thinking panel with recent updates.
- Clone the reference implementation.
- Configure Copilot Studio with an Anthropic model.
- Run the sample locally, observe informative typing streams, and integrate your summarizer.
Questions or feedback on the pattern are welcome.