-
Notifications
You must be signed in to change notification settings - Fork 101
[Bug] Copilot Studio connector generation mishandles x-ms-conversation-id header and undefined causes conversation stickiness #287
Copy link
Copy link
Open
Labels
Fix rolling outWe start the rollout with the fix for this issue.We start the rollout with the fix for this issue.bugSomething isn't workingSomething isn't working
Description
Describe the bug
The generated Copilot Studio connector service (MicrosoftCopilotStudioService.ts) mishandles the conversation identifier header in two ways:
-
Wrong key (
x_ms_conversation_id) means the conversation id is never sent- The generator emits a parameter/property named
x_ms_conversation_id. - The connector expects a hyphenated header key:
x-ms-conversation-id. - As a result, even when the caller provides a conversation id, it is never actually transmitted, because the runtime/connector maps only the correct header name.
- The generator emits a parameter/property named
-
If the key is corrected but sent as
x-ms-conversation-id = undefined, Copilot Studio continues the last conversation- When the header name is corrected to
x-ms-conversation-idbut the value is passed asundefined(first call, when no conversation exists yet), Copilot Studio still responds as if it is continuing the last conversation and returns an id corresponding to the previously registered conversation.
- When the header name is corrected to
Together these issues prevent correct conversation/session isolation and make it difficult to reliably start a new conversation.
To Reproduce
Case A — Generated code uses x_ms_conversation_id (underscore)
- Add/refresh the Copilot Studio connector in a Power Apps Code App project so that service code is generated.
- Open the generated file
MicrosoftCopilotStudioService.ts. - Call the generated method and provide a conversation id value.
- Observe that the conversation id is not actually sent (because the key is wrong), so you cannot reliably control conversation continuation/new conversation behavior.
Case B — Correct header name but value is undefined
- Modify the generated code so that the key is
"x-ms-conversation-id". - Make the first call passing
"x-ms-conversation-id" = undefined(because no conversation is expected to exist yet). - Observe Copilot Studio replies but behaves as if it continued the last conversation, and returns an id matching the previously registered conversation.
Expected behavior
- The generator should map the conversation id using the correct hyphenated header key:
"x-ms-conversation-id". - On the first call, if no conversation id is available yet, the header should be omitted entirely (not sent with an
undefinedvalue), so a new conversation is started.
Actual behavior
- Generated code uses
x_ms_conversation_idinstead of"x-ms-conversation-id", so the conversation id is never transmitted. - If
"x-ms-conversation-id"is sent with valueundefined, Copilot Studio responds continuing the last conversation (sticky session), returning the previous conversation id.
Screenshots / Logs
N/A (can provide if needed). The issue is observable via generated TypeScript and runtime conversation behavior.
Generated code (problematic)
public static async ExecuteCopilotAsyncV2(
Copilot: string,
body: Record<string, unknown>,
x_ms_conversation_id?: string,
environmentId?: string
): Promise<IOperationResult<Record<string, unknown>>> {
const params: {
Copilot: string,
body: Record<string, unknown>,
x_ms_conversation_id?: string,
environmentId?: string
} = { Copilot, body, x_ms_conversation_id, environmentId };
const result = await MicrosoftCopilotStudioService.client.executeAsync<
{ Copilot: string, body: Record<string, unknown>, x_ms_conversation_id?: string, environmentId?: string },
Record<string, unknown>
>({
connectorOperation: {
tableName: MicrosoftCopilotStudioService.dataSourceName,
operationName: 'ExecuteCopilotAsyncV2',
parameters: params
},
});
return result;
}Temporary workaround (works)
My current workaround is:
- Use the correct key
"x-ms-conversation-id". - Do not send
"x-ms-conversation-id"when it isundefined(first call). - Read the conversation id from the first response.
- On the second prompt (and subsequent calls), send
"x-ms-conversation-id"with the conversation id obtained from the first response.
This reliably establishes new conversations.
public static async ExecuteCopilotAsyncV2(
Copilot: string,
body: Record<string, unknown>,
x_ms_conversation_id?: string,
environmentId?: string
): Promise<IOperationResult<void>> {
const params: {
Copilot: string,
body: Record<string, unknown>,
"x-ms-conversation-id"?: string,
environmentId?: string
} = { Copilot, body, environmentId };
// IMPORTANT: omit the header entirely when undefined to force a new conversation
if (x_ms_conversation_id !== undefined) {
params["x-ms-conversation-id"] = x_ms_conversation_id;
}
const result = await MicrosoftCopilotStudioService.client.executeAsync<
{ Copilot: string, body: Record<string, unknown>, "x-ms-conversation-id"?: string, environmentId?: string },
void
>({
connectorOperation: {
tableName: MicrosoftCopilotStudioService.dataSourceName,
operationName: 'ExecuteCopilotAsyncV2',
parameters: params
},
});
return result;
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Fix rolling outWe start the rollout with the fix for this issue.We start the rollout with the fix for this issue.bugSomething isn't workingSomething isn't working