Azure Hosted Copilot SDK
Build production-grade copilots on Azure with enterprise controls, tool safety, and predictable operations.
Use This Skill When
- The user wants to build a customer-facing or internal assistant
- The user needs architecture for prompts, tools, retrieval, and safety
- The user needs deployment guidance and cost controls for copilot workloads
- The user asks about model routing, fallback, or multi-turn conversations
Context: Copilot Maturity
Immature: Hardcoded prompt, single model, no tool safety
Developing: Template-based system prompt, basic tool whitelist
Managed: Versioned prompts, tool isolation, token budgets, structured logging → Target
Optimized: Dynamic prompt selection, multi-model routing, real-time safety evaluation, feedback loops
Required Inputs
- Use case: Customer support? Data analyst? Content generator? Internal ops?
- User scale: <100 users? 1M+ concurrent users?
- Model provider: Azure OpenAI? Third-party API? Mixed?
- Tool access: What actions should the copilot take? (Email, DB query, file access?)
- Data scope: Should it access company data? User files? Public internet?
- Budget: Cost per user? Token budget per session?
- Latency: Real-time (<1s)? Batch acceptable?
- Compliance: PII handling? Data residency? Audit requirements?
Decision Tree
What's the primary use case?
├─ Customer support (knowledge base, FAQ) → Retrieval augmented generation (RAG)
├─ Data analysis (SQL queries, spreadsheets) → Tool calling + sandbox
├─ Content generation (marketing, docs) → Fine-tuned or prompt-engineered
├─ Internal assistant (ops, IT help) → Multi-tool + controlled access
└─ Specialized domain (medical, legal) → Compliance checks + audit trail
How many users will this serve?
├─ < 100 (pilot) → Single model, shared prompt, simple logging
├─ 100-10K (growing) → Multi-instance, load balancing, token budgets
└─ 10K+ (scale) → Multi-region, model fallback, cost controls
What data should the copilot access?
├─ None (generic) → Just prompt engineering
├─ Public data → Semantic search, embeddings
├─ Private company data → Secure retrieval, managed identity, auditable
└─ User-specific data → Tenant isolation, row-level access control
What actions can the copilot take?
├─ Read-only (analyze, explain) → No tool safety needed
├─ Read-write (email, create docs) → Tool sandboxing, approval workflows
└─ Restricted (delete, financial) → Explicit approval, audit trail, rate limits
Workflow
Phase 1: Define Copilot Scope & Safety Boundaries
System prompt design (versioned):
You are ProductBot, a customer support assistant.
✓ You can: Answer FAQs, suggest solutions, escalate to human
✗ You cannot: Accept payment, access customer passwords, make promises on behalf of support team
Always:
- Be friendly and professional
- If unsure, ask the customer for clarification
- Offer to escalate to human agent if customer frustrated
Tool whitelist (what the copilot can do):
Tool: lookup_knowledge_base
├─ Purpose: Search company FAQs and docs
├─ Inputs: query (string)
├─ Returns: matching articles
├─ Rate limit: 100/min
└─ Safety: Read-only, no side effects
Tool: create_support_ticket
├─ Purpose: Open a ticket for human agent
├─ Inputs: customer_email, issue_summary, priority
├─ Returns: ticket_id
├─ Rate limit: 10/min per customer
└─ Safety: Requires verification, audit logged
Tool: send_email_to_customer
├─ Purpose: Send follow-up email
├─ Inputs: recipient, body
├─ Returns: status
├─ Rate limit: 1/min per unique recipient
└─ Safety: ⚠️ Restricted - only on approval workflow
Safety guardrails:
✓ Input validation
└─ Reject prompts > 10K tokens (prevent token stuffing)
└─ Reject special characters in tool args (SQL injection prevention)
✓ Output filtering
└─ Redact email addresses and phone numbers (before sending to user)
└─ Block generation of malware, illegal content
✓ Rate limiting
└─ Per-user: 100 requests/hour
└─ Per-IP: 1000 requests/hour
✓ Approval workflows
└─ send_email_to_customer: Require human review
└─ delete_customer_record: Disabled (no tool access)
Phase 2: Choose Orchestration Stack
Option 1: Azure Cognitive Services + Custom Orchestration
User → [App Service]
├─ Chat handler
├─ Context manager (chat history)
├─ Tool dispatcher
└─ Safety checks
↓ (Azure OpenAI API)
[Azure OpenAI] → Generate response + tool calls
↓ (tool call response)
[App Service] → Execute tool + loop back to model
Option 2: Semantic Kernel (Microsoft)
// .NET
var builder = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(
deploymentName: "gpt-4",
endpoint: "https://myai.openai.azure.com/",
apiKey: kvClient.GetSecret("openai-key").Value.Value)
.Plugins.AddFromType<ToolPlugin>();
var kernel = builder.Build();
var response = await kernel.InvokePromptAsync(
"""
You are a helpful assistant. Use tools to help the user.
Question: {{$input}}
"""
);
Option 3: LangChain / LangGraph (Python)
# Python
from langchain.chat_models import AzureChatOpenAI
from langchain.tools import Tool
from langgraph.graph import StateGraph
llm = AzureChatOpenAI(
deployment_name="gpt-4",
azure_endpoint="https://myai.openai.azure.com/",
api_key=kv.get_secret("openai-key")
)
tools = [search_kb_tool, create_ticket_tool]
agent = create_tool_calling_agent(llm, tools, system_prompt)
Phase 3: Implement Retrieval (if knowledge-grounded)
Setup Azure AI Search (semantic search):
# Create search service
az search service create \
--resource-group $RG \
--name "search-${app}-${env}" \
--sku "standard" \
--partition-count 1 \
--replica-count 1
Ingest documents (embeddings):
# Upload PDFs, docs → Search index with embeddings
# Each document: text + metadata (source, date, author)
Query from copilot:
// C#
var results = await searchClient.SearchAsync<SearchDocument>(
"How do I reset my password?",
new SearchOptions {
QueryType = SearchQueryType.Semantic,
SemanticConfiguration = "default",
Top = 3
}
);
// Inject top results into system prompt
var context = string.Join("\n", results.Value.GetResults()
.Select(r => r.Document["content"]));
var prompt = $"Context: {context}\nQuestion: How do I reset my password?";
Phase 4: Deploy & Configure
Deploy to Azure:
# Option 1: App Service
az webapp up --runtime "DOTNET:6.0" \
--resource-group $RG \
--name "copilot-${app}-${env}"
# Option 2: Container Apps (modern)
az containerapp create \
--resource-group $RG \
--name "copilot-${app}" \
--image "myacr.azurecr.io/copilot:latest" \
--environment $ENV \
--target-port 5000
Configure secrets (no hardcoding):
# Store in Key Vault
az keyvault secret set \
--vault-name $KV \
--name "openai-api-key" \
--value "$OPENAI_KEY"
# App reads via managed identity
Set environment variables:
az webapp config appsettings set \
--resource-group $RG \
--name "copilot-${app}" \
--settings \
"AZURE_OPENAI_ENDPOINT=https://myai.openai.azure.com/" \
"AZURE_OPENAI_MODEL=gpt-4" \
"AZURE_SEARCH_ENDPOINT=https://search-${app}.search.windows.net/" \
"TOOL_TIMEOUT_MS=30000" \
"MAX_TOKENS_PER_REQUEST=4000"
Phase 5: Implement Token & Cost Controls
Token budgeting:
# Track usage per user/session
class TokenBudget:
def __init__(self, tokens_per_hour=100_000):
self.limit = tokens_per_hour
self.used_this_hour = 0
def check_budget(self, estimated_tokens):
if self.used_this_hour + estimated_tokens > self.limit:
raise BudgetExceededError()
self.used_this_hour += estimated_tokens
def reset_hourly(self):
self.used_this_hour = 0
Cost monitoring:
# Log token usage to Application Insights
logger.LogInformation($"Request: {tokens_in}, Response: {tokens_out}, Cost: ${cost}");
# Query: Daily cost by user
customMetrics
| where name == "copilot_tokens"
| summarize sum(value) by user_id, bin(timestamp, 1d)
Phase 6: Observability & Safety Monitoring
Instrument traces:
// Log every interaction
var activity = new Activity("copilot_interaction").Start();
activity.AddTag("user_id", userId);
activity.AddTag("session_id", sessionId);
activity.AddTag("model", "gpt-4");
activity.AddTag("tokens_in", tokensIn);
activity.AddTag("tokens_out", tokensOut);
activity.AddTag("tool_calls", toolCalls.Count);
activity.AddTag("latency_ms", stopwatch.ElapsedMilliseconds);
activity.Dispose();
Alert on anomalies:
- High latency: >5 seconds
- Token overrun: >4K tokens per request
- Tool failures: >5% error rate
- Abusive patterns: Same user >100 requests/hour
Capture user feedback:
[Helpful 👍] [Not helpful 👎] [Report abuse 🚩]
→ Store feedback in database
→ Retrain or prompt-tune based on patterns
Phase 7: Rollout & Failover
Canary deployment (5% users → 100%):
# Deploy new copilot version to 5% of traffic
# Monitor error rate, latency, cost
# If healthy, gradually shift traffic
Model fallback:
# If GPT-4 fails, fallback to GPT-3.5-turbo
try:
response = await gpt4_client.call(prompt)
except APIError:
response = await gpt35_client.call(prompt)
Rollback plan:
If latency > 2x or error rate > 5%:
├─ Switch traffic to previous version
├─ Investigate root cause
├─ Fix and re-deploy
Output Contract
Copilot Architecture Blueprint
- System prompt and safety guardrails
- Tool whitelist with rate limits
- Orchestration stack (Semantic Kernel, LangChain, custom)
Deployment Configuration
- Infrastructure (App Service, Container Apps, AKS)
- Secrets management (Key Vault)
- Model endpoint and fallback strategy
Observability Plan
- Token usage tracking and budgeting
- Latency and error rate SLOs
- User feedback loops
Safety & Compliance
- Input/output filtering rules
- Approval workflows for restricted actions
- Audit trail for sensitive operations
Operational Runbook
- Deployment and rollback procedures
- Incident response (model outage, safety violation)
- Cost optimization (model selection, token budgeting)
Guardrails
- Enforce least privilege: Tools should only access data they need.
- Version system prompts: Track changes, enable rollback.
- Sandbox tool execution: Run in isolated environment, short timeout (<30s).
- Redact sensitive data: Never return API keys, passwords, or PII.
- Rate limit aggressively: Prevent token stuffing and abuse.
- Monitor model outputs: Flag and block unsafe content generation.
- Require approval for destructive actions: Email, delete, payments need human review.
1---2name: azure-hosted-copilot-sdk3description: Design and deploy copilot-style assistants on Azure with secure model access, tool integration, and observability. Use this skill when users ask to build assistants, agents, or copilot workflows in Azure. Covers orchestration, retrieval, safety guardrails, and production deployment.4---56# Azure Hosted Copilot SDK78Build production-grade copilots on Azure with enterprise controls, tool safety, and predictable operations.910## Use This Skill When1112- The user wants to build a customer-facing or internal assistant13- The user needs architecture for prompts, tools, retrieval, and safety14- The user needs deployment guidance and cost controls for copilot workloads15- The user asks about model routing, fallback, or multi-turn conversations1617## Context: Copilot Maturity1819**Immature**: Hardcoded prompt, single model, no tool safety 20**Developing**: Template-based system prompt, basic tool whitelist 21**Managed**: Versioned prompts, tool isolation, token budgets, structured logging → **Target** 22**Optimized**: Dynamic prompt selection, multi-model routing, real-time safety evaluation, feedback loops2324## Required Inputs2526- **Use case**: Customer support? Data analyst? Content generator? Internal ops?27- **User scale**: <100 users? 1M+ concurrent users?28- **Model provider**: Azure OpenAI? Third-party API? Mixed?29- **Tool access**: What actions should the copilot take? (Email, DB query, file access?)30- **Data scope**: Should it access company data? User files? Public internet?31- **Budget**: Cost per user? Token budget per session?32- **Latency**: Real-time (<1s)? Batch acceptable?33- **Compliance**: PII handling? Data residency? Audit requirements?3435## Decision Tree3637```38What's the primary use case?39├─ Customer support (knowledge base, FAQ) → Retrieval augmented generation (RAG)40├─ Data analysis (SQL queries, spreadsheets) → Tool calling + sandbox41├─ Content generation (marketing, docs) → Fine-tuned or prompt-engineered42├─ Internal assistant (ops, IT help) → Multi-tool + controlled access43└─ Specialized domain (medical, legal) → Compliance checks + audit trail4445How many users will this serve?46├─ < 100 (pilot) → Single model, shared prompt, simple logging47├─ 100-10K (growing) → Multi-instance, load balancing, token budgets48└─ 10K+ (scale) → Multi-region, model fallback, cost controls4950What data should the copilot access?51├─ None (generic) → Just prompt engineering52├─ Public data → Semantic search, embeddings53├─ Private company data → Secure retrieval, managed identity, auditable54└─ User-specific data → Tenant isolation, row-level access control5556What actions can the copilot take?57├─ Read-only (analyze, explain) → No tool safety needed58├─ Read-write (email, create docs) → Tool sandboxing, approval workflows59└─ Restricted (delete, financial) → Explicit approval, audit trail, rate limits60```6162## Workflow6364### Phase 1: Define Copilot Scope & Safety Boundaries65661. **System prompt design** (versioned):67 ```68 You are ProductBot, a customer support assistant.69 70 ✓ You can: Answer FAQs, suggest solutions, escalate to human71 ✗ You cannot: Accept payment, access customer passwords, make promises on behalf of support team72 73 Always:74 - Be friendly and professional75 - If unsure, ask the customer for clarification76 - Offer to escalate to human agent if customer frustrated77 ```78792. **Tool whitelist** (what the copilot can do):80 ```81 Tool: lookup_knowledge_base82 ├─ Purpose: Search company FAQs and docs83 ├─ Inputs: query (string)84 ├─ Returns: matching articles85 ├─ Rate limit: 100/min86 └─ Safety: Read-only, no side effects87 88 Tool: create_support_ticket89 ├─ Purpose: Open a ticket for human agent90 ├─ Inputs: customer_email, issue_summary, priority91 ├─ Returns: ticket_id92 ├─ Rate limit: 10/min per customer93 └─ Safety: Requires verification, audit logged94 95 Tool: send_email_to_customer96 ├─ Purpose: Send follow-up email97 ├─ Inputs: recipient, body98 ├─ Returns: status99 ├─ Rate limit: 1/min per unique recipient100 └─ Safety: ⚠️ Restricted - only on approval workflow101 ```1021033. **Safety guardrails**:104 ```105 ✓ Input validation106 └─ Reject prompts > 10K tokens (prevent token stuffing)107 └─ Reject special characters in tool args (SQL injection prevention)108 109 ✓ Output filtering110 └─ Redact email addresses and phone numbers (before sending to user)111 └─ Block generation of malware, illegal content112 113 ✓ Rate limiting114 └─ Per-user: 100 requests/hour115 └─ Per-IP: 1000 requests/hour116 117 ✓ Approval workflows118 └─ send_email_to_customer: Require human review119 └─ delete_customer_record: Disabled (no tool access)120 ```121122### Phase 2: Choose Orchestration Stack123124**Option 1: Azure Cognitive Services + Custom Orchestration**125```126User → [App Service] 127 ├─ Chat handler128 ├─ Context manager (chat history)129 ├─ Tool dispatcher130 └─ Safety checks131 132 ↓ (Azure OpenAI API)133 134 [Azure OpenAI] → Generate response + tool calls135 136 ↓ (tool call response)137 138 [App Service] → Execute tool + loop back to model139```140141**Option 2: Semantic Kernel (Microsoft)**142```csharp143// .NET144var builder = Kernel.CreateBuilder()145 .AddAzureOpenAIChatCompletion(146 deploymentName: "gpt-4",147 endpoint: "https://myai.openai.azure.com/",148 apiKey: kvClient.GetSecret("openai-key").Value.Value)149 .Plugins.AddFromType<ToolPlugin>();150151var kernel = builder.Build();152153var response = await kernel.InvokePromptAsync(154 """155 You are a helpful assistant. Use tools to help the user.156 Question: {{$input}}157 """158);159```160161**Option 3: LangChain / LangGraph (Python)**162```python163# Python164from langchain.chat_models import AzureChatOpenAI165from langchain.tools import Tool166from langgraph.graph import StateGraph167168llm = AzureChatOpenAI(169 deployment_name="gpt-4",170 azure_endpoint="https://myai.openai.azure.com/",171 api_key=kv.get_secret("openai-key")172)173174tools = [search_kb_tool, create_ticket_tool]175agent = create_tool_calling_agent(llm, tools, system_prompt)176```177178### Phase 3: Implement Retrieval (if knowledge-grounded)1791801. **Setup Azure AI Search** (semantic search):181 ```bash182 # Create search service183 az search service create \184 --resource-group $RG \185 --name "search-${app}-${env}" \186 --sku "standard" \187 --partition-count 1 \188 --replica-count 1189 ```1901912. **Ingest documents** (embeddings):192 ```bash193 # Upload PDFs, docs → Search index with embeddings194 # Each document: text + metadata (source, date, author)195 ```1961973. **Query from copilot**:198 ```csharp199 // C#200 var results = await searchClient.SearchAsync<SearchDocument>(201 "How do I reset my password?",202 new SearchOptions { 203 QueryType = SearchQueryType.Semantic,204 SemanticConfiguration = "default",205 Top = 3 206 }207 );208 209 // Inject top results into system prompt210 var context = string.Join("\n", results.Value.GetResults()211 .Select(r => r.Document["content"]));212 213 var prompt = $"Context: {context}\nQuestion: How do I reset my password?";214 ```215216### Phase 4: Deploy & Configure2172181. **Deploy to Azure**:219 ```bash220 # Option 1: App Service221 az webapp up --runtime "DOTNET:6.0" \222 --resource-group $RG \223 --name "copilot-${app}-${env}"224 225 # Option 2: Container Apps (modern)226 az containerapp create \227 --resource-group $RG \228 --name "copilot-${app}" \229 --image "myacr.azurecr.io/copilot:latest" \230 --environment $ENV \231 --target-port 5000232 ```2332342. **Configure secrets** (no hardcoding):235 ```bash236 # Store in Key Vault237 az keyvault secret set \238 --vault-name $KV \239 --name "openai-api-key" \240 --value "$OPENAI_KEY"241 242 # App reads via managed identity243 ```2442453. **Set environment variables**:246 ```bash247 az webapp config appsettings set \248 --resource-group $RG \249 --name "copilot-${app}" \250 --settings \251 "AZURE_OPENAI_ENDPOINT=https://myai.openai.azure.com/" \252 "AZURE_OPENAI_MODEL=gpt-4" \253 "AZURE_SEARCH_ENDPOINT=https://search-${app}.search.windows.net/" \254 "TOOL_TIMEOUT_MS=30000" \255 "MAX_TOKENS_PER_REQUEST=4000"256 ```257258### Phase 5: Implement Token & Cost Controls2592601. **Token budgeting**:261 ```python262 # Track usage per user/session263 class TokenBudget:264 def __init__(self, tokens_per_hour=100_000):265 self.limit = tokens_per_hour266 self.used_this_hour = 0267 268 def check_budget(self, estimated_tokens):269 if self.used_this_hour + estimated_tokens > self.limit:270 raise BudgetExceededError()271 self.used_this_hour += estimated_tokens272 273 def reset_hourly(self):274 self.used_this_hour = 0275 ```2762772. **Cost monitoring**:278 ```bash279 # Log token usage to Application Insights280 logger.LogInformation($"Request: {tokens_in}, Response: {tokens_out}, Cost: ${cost}");281 282 # Query: Daily cost by user283 customMetrics284 | where name == "copilot_tokens"285 | summarize sum(value) by user_id, bin(timestamp, 1d)286 ```287288### Phase 6: Observability & Safety Monitoring2892901. **Instrument traces**:291 ```csharp292 // Log every interaction293 var activity = new Activity("copilot_interaction").Start();294 activity.AddTag("user_id", userId);295 activity.AddTag("session_id", sessionId);296 activity.AddTag("model", "gpt-4");297 activity.AddTag("tokens_in", tokensIn);298 activity.AddTag("tokens_out", tokensOut);299 activity.AddTag("tool_calls", toolCalls.Count);300 activity.AddTag("latency_ms", stopwatch.ElapsedMilliseconds);301 activity.Dispose();302 ```3033042. **Alert on anomalies**:305 - High latency: >5 seconds306 - Token overrun: >4K tokens per request307 - Tool failures: >5% error rate308 - Abusive patterns: Same user >100 requests/hour3093103. **Capture user feedback**:311 ```312 [Helpful 👍] [Not helpful 👎] [Report abuse 🚩]313 314 → Store feedback in database315 → Retrain or prompt-tune based on patterns316 ```317318### Phase 7: Rollout & Failover3193201. **Canary deployment** (5% users → 100%):321 ```bash322 # Deploy new copilot version to 5% of traffic323 # Monitor error rate, latency, cost324 # If healthy, gradually shift traffic325 ```3263272. **Model fallback**:328 ```python329 # If GPT-4 fails, fallback to GPT-3.5-turbo330 try:331 response = await gpt4_client.call(prompt)332 except APIError:333 response = await gpt35_client.call(prompt)334 ```3353363. **Rollback plan**:337 ```338 If latency > 2x or error rate > 5%:339 ├─ Switch traffic to previous version340 ├─ Investigate root cause341 ├─ Fix and re-deploy342 ```343344## Output Contract3453461. **Copilot Architecture Blueprint**347 - System prompt and safety guardrails348 - Tool whitelist with rate limits349 - Orchestration stack (Semantic Kernel, LangChain, custom)3503512. **Deployment Configuration**352 - Infrastructure (App Service, Container Apps, AKS)353 - Secrets management (Key Vault)354 - Model endpoint and fallback strategy3553563. **Observability Plan**357 - Token usage tracking and budgeting358 - Latency and error rate SLOs359 - User feedback loops3603614. **Safety & Compliance**362 - Input/output filtering rules363 - Approval workflows for restricted actions364 - Audit trail for sensitive operations3653665. **Operational Runbook**367 - Deployment and rollback procedures368 - Incident response (model outage, safety violation)369 - Cost optimization (model selection, token budgeting)370371## Guardrails372373- **Enforce least privilege**: Tools should only access data they need.374- **Version system prompts**: Track changes, enable rollback.375- **Sandbox tool execution**: Run in isolated environment, short timeout (<30s).376- **Redact sensitive data**: Never return API keys, passwords, or PII.377- **Rate limit aggressively**: Prevent token stuffing and abuse.378- **Monitor model outputs**: Flag and block unsafe content generation.379- **Require approval for destructive actions**: Email, delete, payments need human review.