Microsoft's new gdlchat repository shows how to put Microsoft Copilot Studio chat behind Azure API Management (APIM) so every user turn passes subscription auth, rate limits, and JSON validation before an agent runs tools. Azure API Management's gateway verifies API keys, enforces usage quotas and rate limits, and can transform requests through policy statements. The README targets teams that need governed access to a copilot — not anonymous Direct Line demos on the public internet.
Agents that act on your behalf need rules. See how explainx helps secure your agents →
TL;DR
| Setting | Behavior |
|---|---|
| Default path | Blazor UI → APIM chat-api/messages → backend → Copilot Studio |
ChatGateway:Enabled=false | Direct agent mode; policies skipped |
| UI transport | Blazor WebSockets at /chat/_blazor when useAPIM=true |
| Browser secrets | No agent tokens or subscription keys in browser |
| Auth modes | Direct Line anonymous POC or Entra interactive dev sign-in |
| Fail closed | Missing gateway config → chat errors, no silent fallback |
Problem: conversational UIs bypass your API edge
Enterprises already standardize REST traffic through APIM for OAuth, quotas, and WAF-ish rules. Copilot Studio samples often terminate Direct Line at the app server, leaving model-chosen tool actions outside the same envelope.
gdlchat's enforced path:
Blazor server → APIM POST /chat-api/messages → protected backend POST /chat/api/chat/messages → Copilot Studio → buffered JSON reply → outbound APIM policies → UI
The browser keeps only the Blazor circuit; policy-enforced HTTP rides server-side.
Agent permission boundary showing APIM filtering Copilot chat before the agent backend
Connection modes in the README
DirectLine default — anonymous conversation tokens from configured endpoints; suitable for tightly networked demos.
Sdk mode — set CopilotStudioAgent:ConnectionMode to Sdk with environment and schema names; production guidance favors DefaultAzureCredential or service principal env vars, never secrets in appsettings.json.
InteractiveBrowser — development-only Entra delegated sign-in with CopilotStudio.Copilots.Invoke scope; first request may open a browser within the 90-second UI timeout.
Zero-trust access gate for governed Copilot Studio chat routed through APIM
APIM hosting (useAPIM)
When useAPIM=true, the app uses path base /chat/, WebSocket API suffix chat/_blazor (not legacy chat/socket), and no long-polling fallback. APIM tier must support WebSockets (Consumption does not).
Operators import apim/chat-api.openapi.json as a separate API from the UI APIs, enable subscription required on chat-api, and keep UI APIs unsubscribed for anonymous POC.
Policy and secret model
README instructs:
- Generate 64-hex backend secret stored as APIM named value and Container App secret.
- Issue dedicated subscription key for the Blazor server (secret reference env vars).
- Apply
apim/apim-chat-policy.xmlat API scope.
Manual tests in apim/chat-api.http cover 401 without subscription, 403 on policy-block-test, 400 on schema violations, multi-turn conversationId continuity, and 401 on direct backend calls missing X-Chat-Backend-Key.
Important limitation AWS also stresses elsewhere: inbound blocking stops bad prompts before the agent runs; outbound blocking cannot undo tools already executed — same class of risk as Bedrock KB interceptors.
POC capacity and logging
Single-replica backend holds 256 conversations, 30-minute idle TTL, 409 on overlapping turns, 410 on unknown handles. Completed replies cap at 128 messages / 32k characters.
Conversation handles are capabilities, not user identities; rate limits apply per server subscription, not per anonymous visitor. README warns against logging credentials, Direct Line tokens, or unredacted resumes.
How this compares to Microsoft agent posts we track
- FoundryX Copilot skill — IDE-side skills.
- Copilot managed runtime template — app scaffolding.
gdlchat is edge policy for published agents — closest cousin to AWS's ChatGateway thinking, but for Copilot Studio + APIM.
Try it safely
- Deploy APIM before exposing Container Apps ingress publicly.
- Keep
ChatGateway:Enabled=truein any environment facing untrusted users. - Rotate subscription and backend secrets independently.
- Add real content classifiers via APIM
send-requestpolicies; the sample'spolicy-block-teststring is a wiring test, not safety ML. - Plan multi-replica conversation affinity before production — README says Blazor session affinity alone is insufficient.
Direct Line transport details builders overlook
The README explains WebSocket lifecycle: connect before post, reconnect with watermark, filter user echoes by activity ID. 90-second UI cancel versus 85-second backend means operators must align timeouts across APIM policies, Container Apps ingress, and Copilot Studio agent settings.
Plain text rendering — agent output is not HTML — reduces XSS in chat UI but also means no rich cards unless Copilot Studio activities add them server-side.
Entra application registration checklist (dev mode)
For InteractiveBrowser development:
- Redirect
http://localhoston mobile/desktop platform. - Delegate permission CopilotStudio.Copilots.Invoke with admin consent.
- Never commit client secrets for interactive mode.
- WSL users need Windows browser ↔ WSL localhost reachability — a recurring failure mode in hybrid dev setups.
Scaling beyond POC
README is explicit: single replica, in-memory conversation map, no durable conversation store. Before production:
- Externalize conversation state (Redis, Cosmos) with sticky routing on APIM or partition by conversation ID hash.
- Replace anonymous Direct Line with Entra-gated users matching enterprise COPILOT policies.
- Add WAF rules on APIM front door separate from JSON schema validation.
Comparison to Azure API Management patterns elsewhere
Microsoft's own ecosystem increasingly treats LLM traffic as just another API product — subscription keys, named values, policy fragments. gdlchat is the Copilot Studio flavored reference; Foundry agents cover GitHub-integrated agents instead.
Audit and compliance hooks
For regulated industries, extend policies with:
- JWT validation tying chat to corporate IdP, not only subscription keys.
- PII scan outbound via APIM
send-requestto a DLP service. - Immutable logging to SIEM with conversationId correlation — README warns APIM diagnostics are sampled, not full transcripts.
Licensing and support expectations
gdlchat shipped as reference code with two commits in the November 12 trending snapshot — not a supported Azure product SKU. Teams should fork with eyes open: you own patch cadence, APIM version drift, and Copilot Studio API changes. Microsoft’s README is unusually detailed; treat it as spec for your internal platform team.
Failure injection tests
Beyond apim/chat-api.http, teams should simulate:
- Expired subscription key during long conversation.
- Backend secret mismatch after rotation half-deployed.
- Copilot Studio outage — UI should surface policy-blocked message, not hang until 90s cancel.
Mapping README settings to operations
| Config key | Ops owner | Typical mistake |
|---|---|---|
ChatGateway__Endpoint | Platform | Points at prod APIM while UI still dev |
useAPIM | Frontend | Forgetting trailing slash on public URL |
CopilotStudioAgent:TokenEndpoint | Copilot admin | Anonymous mode left on in prod |
Logging:LogLevel for Direct Line | SRE | Verbose HTTP logs leak tokens |
Run a config drift scan each release — gdlchat has many boolean toggles with security impact.
Edge cases in policy-block-test
The sample blocks a literal substring. Real classifiers need tokenization-aware rules — attackers split strings. Plan to replace the test hook with Azure Content Safety or a bespoke model before any external pilot.
Why Microsoft published this now
Copilot Studio adoption created thousands of anonymous Direct Line endpoints. Security reviewers asked for APIM-shaped answers similar to API Management + Functions patterns from the 2010s. gdlchat modernizes that story for generative turns instead of REST JSON.
Procurement and tenant isolation
Multi-tenant SaaS vendors hosting Copilot for clients should never share one APIM subscription key across customers. The README's per-server subscription model is a stand-in for per-tenant credentials with separate rate limits and audit streams. Align Azure AD B2B guests with per-tenant Copilot environments before routing everything through one gdlchat deployment — otherwise policy logs commingle customer prompts.
Disaster recovery
Document fail-closed behavior when APIM is unavailable: users should see an explicit maintenance message, not silent fallback to ChatGateway disabled mode. Runbooks must forbid toggling gateway bypass under pressure unless executive risk acceptance is recorded.
Step-by-step hardening path
Week one: deploy README POC with ChatGateway enabled and run apim/chat-api.http tests. Week two: replace policy-block-test with tenant-specific banned phrases and PII regexes. Week three: integrate Entra conditional access so only managed devices hit /chat/. Week four: attach SIEM forwarding on APIM diagnostic settings with conversationId field preserved. Each week adds evidence for security questionnaire answers without requiring a Copilot rewrite.
Blazor-specific operations notes
Because UI uses Interactive Server, scale plans must account for circuit memory per anonymous user plus server-side Direct Line WebSockets. Load tests should include concurrent anonymous sessions, not only APIM POST latency. Microsoft documents single replica for a reason — treat horizontal scale as a design change, not a slider.
Documentation readers should also inventory which Copilot Studio environments map to which APIM products before auditors ask for a diagram. A common gap is dev Copilot still pointing at prod APIM keys copied from a wiki page. Rotate keys when people leave the team that built the POC, because subscription secrets in Container Apps outlive hackathon weekends.
Keep a printed network diagram showing browser → APIM → Container App → Copilot Studio → APIM return path for onboarding engineers who have never debugged split WebSocket and HTTP chat stacks.
Security review boards sometimes ask whether Copilot tool invocations can exfiltrate data during an APIM outage. The README’s fail-closed stance is the right answer: degraded chat is preferable to unmonitored agent execution.
Add change-control on apim-chat-policy.xml the same way you gate production firewall rules. Version that policy XML in git with mandatory pull request review.
Related on explainx.ai
- Microsoft FoundryX plugin
- Copilot managed runtime
- Bedrock KB ACL gateway
- AWS A2A pattern
- Prompt injection oblomovka essay
- Agent Registry governance
Configuration flags and policy file names follow the November 12, 2026 microsoft/gdlchat README.
