Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Claude Code Review

on:
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"

jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}

Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage

Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.

Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.

# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

50 changes: 50 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read

# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'

# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,4 @@ cython_debug/
# DevTunnels
DevTunnels
.azure
.claude/settings.local.json
191 changes: 191 additions & 0 deletions .roo/rules/rules-local-seo-specialist/local-seo-specialist.xml

Large diffs are not rendered by default.

75 changes: 75 additions & 0 deletions .roo/rules/rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## Core Behavior

- Be concise and practical. Prefer clear bullet points and short paragraphs.
- Default to a senior engineer tone: direct, honest, and focused on tradeoffs.
- Always assume the user is technical and comfortable with Azure, Kubernetes, CI/CD, and LLMs.

## Code & Outputs

- When writing code:
- Include inline comments explaining non-obvious logic or config.
- Prefer production-grade patterns over quick hacks.
- Make examples self-contained and runnable where possible.
- When editing or generating multiple files, summarize:
- What changed
- Why it changed
- Any follow-up actions (migrations, secrets, infra changes).
- Prefer:
- Backend: Node.js (20+), TypeScript, or Python 3.12+
- Infra: Terraform, Helm, Kubernetes manifests, Azure DevOps pipelines
- Frontend: React 18+ when UI is needed.

## Safety & Destructive Actions

- Never propose destructive commands (e.g., `rm -rf`, dropping DBs, mass deletes) without:
- Explicitly calling them out as destructive
- Providing a safer alternative or dry-run version
- When suggesting shell, kubectl, or Terraform commands:
- Prefer idempotent or clearly labeled “read-only / diagnostic” commands first.
- Call out environment assumptions (dev, qa, uat, prod).

## Azure & Cloud Defaults

- Default cloud: Azure.
- Prefer:
- Azure Kubernetes Service (AKS) for containers
- Azure AI Foundry / Azure OpenAI for LLMs
- Azure DevOps or GitHub Actions for CI/CD
- Azure Monitor / Application Insights / Log Analytics + Datadog for observability when relevant.
- When proposing an architecture:
- Mention identity (Managed Identity / Entra ID)
- Mention secrets (Key Vault)
- Mention BCDR/high-availability at a high level.

## LLM / Agent / Prompt Work

- When designing agents or prompts:
- Use clear structure (role, objective, context, tools, tasks, outputs, constraints).
- Call out safety constraints (no medical/legal advice, no harmful content, protect PII).
- Prefer JSON or well-structured outputs when used by other systems.
- Keep prompts token-efficient while remaining clear.

## Review & Debug Style

- For debugging issues (errors/logs/stack traces):
- First summarize what the problem looks like.
- Then list likely root causes ranked by probability.
- Then propose a minimal, step-by-step diagnostic plan.
- For PR/code reviews:
- Focus on correctness, readability, security, and performance.
- Group feedback into: MUST FIX, SHOULD FIX, NICE TO HAVE.

## Ops & Process

- Assume Git-based workflows (feature branches, PRs, code review).
- When suggesting process or automation:
- Tie it to metrics: reliability, cost, latency, or developer productivity.
- When in doubt, favor:
- Simpler, observable solutions over clever but opaque ones.
- Explicit configuration over hidden magic.

## Communication

- If something is ambiguous, briefly state your assumption and proceed.
- If a task seems risky or incomplete (e.g., missing secrets, env vars, or config), call that out explicitly.
- Avoid boilerplate “I am an AI…” language; speak like a teammate.
144 changes: 144 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

This is a **Call Center Voice Agent Accelerator** built with Azure Voice Live API and Azure Communication Services (ACS). It provides real-time speech-to-speech voice agents for call center scenarios with two client modes: web browser (for testing) and ACS phone calls (for production).

## Technology Stack

- **Backend**: Python 3.9+ with Quart (async Flask-like framework)
- **Package Manager**: UV (fast Python dependency management via `pyproject.toml`)
- **Infrastructure**: Azure Bicep templates for IaC
- **Deployment**: Azure Developer CLI (`azd`)
- **Key Azure Services**:
- Azure Voice Live API (Speech-to-speech with integrated ASR, LLM, TTS)
- Azure Communication Services (telephony/call automation)
- Azure Container Apps (hosting)
- Azure Container Registry
- Azure Key Vault (stores ACS connection string)

## Development Commands

### Local Development (server/ directory)

```bash
# Run the server locally
uv run server.py

# Access web client at http://127.0.0.1:8000
```

### Docker Development

```bash
# Build image
docker build -t voiceagent .

# Run with environment variables
docker run --env-file .env -p 8000:8000 -it voiceagent
```

### Deployment

```bash
# Login to Azure
azd auth login

# Deploy all resources (initial + updates)
azd up

# Deploy code changes only
azd deploy

# Clean up all resources
azd down
```

### Testing with ACS Phone Client (Local)

Use Azure DevTunnels to expose local server for webhook testing:

```bash
devtunnel login
devtunnel create --allow-anonymous
devtunnel port create -p 8000
devtunnel host
```

## Architecture

### Core Application Structure

```
server/
├── server.py # Main Quart application with routes
├── app/
│ └── handler/
│ ├── acs_event_handler.py # Processes ACS incoming calls and callbacks
│ └── acs_media_handler.py # Manages audio streaming to Voice Live API
└── static/ # Web client HTML/JS
```

### Request Flow

1. **Web Client Mode**: Browser → `/web/ws` WebSocket → `ACSMediaHandler` → Voice Live API
2. **ACS Phone Mode**: Phone Call → ACS IncomingCall event → `/acs/incomingcall` → Answer call with media streaming → `/acs/ws` WebSocket → `ACSMediaHandler` → Voice Live API

### Key Handlers

- **AcsEventHandler** (`acs_event_handler.py`): Handles EventGrid subscription validation and incoming call events. Answers calls with `MediaStreamingOptions` configured for bidirectional audio.
- **ACSMediaHandler** (`acs_media_handler.py`): Establishes WebSocket connection to Voice Live API, manages audio queues, and handles bidirectional audio streaming. Uses managed identity or API key authentication.

### Infrastructure (infra/)

Bicep modules provision:
- User-assigned managed identity (for Key Vault and AI services access)
- AI Services (Voice Live API endpoint)
- Communication Services (telephony)
- Container Apps + Container Registry
- Key Vault (stores ACS connection string as secret)
- Monitoring (Log Analytics, Application Insights)

The main deployment is subscription-scoped (`infra/main.bicep`). Note: Limited to `eastus2` and `swedencentral` regions due to Voice Live API availability.

## Environment Configuration

Create `.env` file in `server/` directory based on `.env-sample.txt`:

```
AZURE_VOICE_LIVE_API_KEY=<AI Foundry resource key>
AZURE_VOICE_LIVE_ENDPOINT=<AI Foundry resource endpoint>
VOICE_LIVE_MODEL=gpt-4o-mini
ACS_CONNECTION_STRING=<Communication Services connection string>
ACS_DEV_TUNNEL=<Optional: DevTunnel URL for local ACS testing>
```

When deployed to Azure, the container app uses:
- Managed Identity for Voice Live API authentication
- Key Vault secret reference for ACS connection string

## Voice Live API Configuration

Session configuration is defined in `acs_media_handler.py:session_config()`:
- **Turn Detection**: Azure Semantic VAD with end-of-utterance detection
- **Audio Processing**: Deep noise suppression and server echo cancellation
- **Voice**: Configurable Azure Neural TTS voice (default: en-US-Aria)
- **Instructions**: Customizable system prompt for LLM behavior

## Post-Deployment Setup

After `azd up`:
1. Navigate to the Container App URL to test the web client
2. For phone testing:
- Create Event Grid subscription for IncomingCall events pointing to `https://<container-app-url>/acs/incomingcall`
- Provision a phone number for the ACS resource
- Call the number to test the voice agent

## Important Notes

- **Security**: ACS connection string is stored in Key Vault. Container app retrieves it via secret reference.
- **Authentication**: Production deployments use managed identity for Voice Live API. Local development uses API key.
- **Region Constraints**: Voice Live API is only available in specific regions (swedencentral strongly recommended).
- **WebSocket Endpoints**: `/web/ws` for browser clients (raw audio), `/acs/ws` for ACS calls (PCM 24kHz mono).
Binary file added docs/azure-speech-docs.pdf
Binary file not shown.
Loading