FAI Instructions Authoring
Create WAF-aligned coding standards with glob-based targeting.
What Instructions Do
Instructions are persistent, passive coding standards that Copilot absorbs automatically based on the files you're editing. You never invoke an instruction explicitly — instead, the applyTo glob pattern determines when it activates. When you open a Python file, every instruction with applyTo: "**/*.py" kicks in silently.
This makes instructions the most scalable primitive. Write a security instruction once, and every developer on the team gets the same guardrails applied to every file matching the pattern — without changing their workflow.
The .instructions.md Format
Every instruction file has two parts: YAML frontmatter (metadata) and Markdown body (the rules). The file must be named kebab-case.instructions.md and placed in .github/instructions/.
---
description: "Python coding standards with WAF security and reliability"
applyTo: "**/*.py"
waf:
- security
- reliability
- cost-optimization
---
## Authentication
- Use `DefaultAzureCredential` for all Azure SDK clients
- Never hardcode connection strings, API keys, or tokens
- Reference secrets via Key Vault: `SecretClient(vault_url, credential)`
## Error Handling
- Wrap all external API calls with retry and exponential backoff
- Use `tenacity`: `@retry(stop=stop_after_attempt(3), wait=wait_exponential())`
- Log exceptions with correlation_id for distributed tracing
## Cost Controls
- Set `max_tokens` on every OpenAI call (never leave unlimited)
- Use gpt-4o-mini for classification, summarization, simple extraction
- Reserve gpt-4o for multi-step reasoning and architecture decisions
## Observability
- Use `structlog` with bound context (correlation_id, user_id, play_id)
- Emit OpenTelemetry spans around LLM calls with token count attributesFrontmatter Fields
| Field | Required | Type | Validation |
|---|---|---|---|
| description | Yes | string | ≥ 10 characters |
| applyTo | Yes | string (glob) | Valid glob pattern |
| waf | Optional | string[] | Valid pillar names from the 6-pillar set |
Glob Pattern Reference
The applyTo field uses standard glob patterns. Here are the most common patterns for FAI instructions:
| Pattern | Matches | Use Case |
|---|---|---|
| **/*.py | All Python files | Python coding standards |
| **/*.{ts,tsx} | TypeScript + React | Frontend standards |
| **/*.bicep | Bicep IaC files | Infrastructure standards |
| **/*.{json,yaml,yml} | Config files | Config validation rules |
| src/api/**/*.py | API route files only | API-specific standards |
| **/test_*.py | Python test files | Testing conventions |
| **/* | Every file | Universal rules (use sparingly) |
Writing Effective Rules
Good instruction rules are specific, actionable, and include concrete code patterns. Avoid vague guidance like "write secure code." Instead, tell Copilot exactly what to do:
# ❌ Bad — vague, not actionable
- Write secure code
- Handle errors properly
- Optimize for performance
# ✅ Good — specific, concrete, actionable
- Use DefaultAzureCredential instead of connection strings
- Wrap HTTP calls in @retry(stop=stop_after_attempt(3))
- Cache embedding results in Redis with 24h TTL
- Set max_tokens=1000 for standard queries, 4000 for complex
# ✅ Better — includes code patterns
- Authentication pattern:
```python
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
client = OpenAIClient(endpoint, credential)
```Scope: Global vs File-Specific
FrootAI supports two instruction scopes:
- Global —
.github/copilot-instructions.mdapplies to every interaction regardless of file type. Use for project-wide conventions like naming, architecture patterns, and team preferences. - File-specific — Files in
.github/instructions/withapplyToglobs apply only when editing matching files. Use for language-specific or domain-specific standards.
Both scopes are additive. When editing a Python file, Copilot sees the global instructions plus all file-specific instructions matching **/*.py. All matching rules are active simultaneously — there is no conflict resolution.
WAF Pillar Alignment
The waf frontmatter field tags an instruction with architecture pillars. The FAI Engine can filter instructions by pillar, and play manifests auto-apply matching instructions based on context.waf.
---
description: "Bicep infrastructure with WAF reliability and security"
applyTo: "**/*.bicep"
waf:
- reliability
- security
- operational-excellence
---
## Reliability
- Deploy all services with zone redundancy where available
- Use availability zones for AKS node pools and App Service plans
- Configure health probes on every load-balanced endpoint
## Security
- Enable managed identity on all compute resources
- Use private endpoints for PaaS services (Storage, Cosmos DB, AI Search)
- Assign least-privilege RBAC roles — never use Owner or Contributor
## Operational Excellence
- Tag every resource: environment, team, cost-center, play
- Enable diagnostic settings sending to Log Analytics workspace
- Use Bicep modules from the verified infra-registry/Testing Instructions in VS Code
After writing an instruction, verify it works by testing in Copilot Chat:
# 1. Place your instruction file
cp my-instruction.instructions.md .github/instructions/
# 2. Open a file matching the applyTo pattern
code src/app.py # If applyTo: "**/*.py"
# 3. Ask Copilot a question that should trigger the rule
# "How should I authenticate to Azure Storage?"
# → Copilot should suggest DefaultAzureCredential (per your rule)
# 4. Validate with the primitives validator
npm run validate:primitives
# ✅ instructions/my-instruction.instructions.md — valid
# description: ✅ (>= 10 chars)
# applyTo: ✅ (valid glob)
# waf: ✅ (valid pillar names)Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
| Too many rules in one file | Exceeds context window | Split by concern (security, testing, API) |
| Vague guidance | Copilot ignores it | Use concrete code patterns |
| applyTo: "**/*" overuse | Unnecessary noise | Scope to specific file types |
| Missing description | Validation failure | Add ≥ 10 char description |
| Underscores in filename | Naming violation | Use lowercase-hyphen only |
Real-World: TypeScript Instruction
Here's a production-ready instruction for TypeScript projects with performance and security alignment:
---
description: "TypeScript standards with WAF performance and security"
applyTo: "**/*.{ts,tsx}"
waf:
- performance-efficiency
- security
---
## Type Safety
- Enable strict mode in tsconfig.json (strict: true)
- Avoid `any` type — use `unknown` with type guards instead
- Define API response types explicitly, never infer from fetch
## Security
- Sanitize all user input before rendering (DOMPurify for HTML)
- Use parameterized queries for database operations
- Never interpolate user input into SQL or shell commands
## Performance
- Use React.memo() for expensive pure components
- Lazy-load routes with React.lazy() and Suspense
- Prefer server components for data fetching (Next.js App Router)
- Debounce search inputs (300ms default)
## Imports
- Use barrel exports sparingly — they defeat tree-shaking
- Prefer direct imports: import { Button } from "@/components/ui/button"Scaffolding a New Instruction
Use the scaffold script to generate a properly structured instruction file:
# Scaffold a new instruction
node scripts/scaffold-primitive.js instruction
# Interactive prompts:
# ? Instruction name (kebab-case): go-api-standards
# ? Description: Go API coding standards with reliability WAF alignment
# ? applyTo glob: **/*.go
# ? WAF pillars: reliability, security
#
# Created:
# .github/instructions/go-api-standards.instructions.md
# Validate
npm run validate:primitives