Skip to content

Appendix - Azure Environment Setup

Azure Environment Setup

This appendix takes you from a fresh clone to a running concierge backed by Azure: Foundry model endpoints for the LLM, realtime, and image features, plus Azure Database for PostgreSQL for persistence. Follow the steps in order.

Note

For local-only development with Docker pgvector and no Azure dependency, follow the Development Guide and tutorial steps 1 through 3 instead. This appendix covers the managed Azure path.

What you will configure

  • Foundry project endpoints for chat/LLM, realtime voice, and image generation
  • Azure Database for PostgreSQL connection with Microsoft Entra authentication
  • Persistence backends for the Todo, Chat, and Cloud Agent apps
  • Optional knowledge search over Azure PostgreSQL and a durable Cloud Agent queue

Prerequisites

Install dependencies, copy the environment template, and sign in.

make install-deps-dev
cp .env.template .env
az login

You also need the following in your subscription:

  • One or more Azure AI Foundry (AIServices) resources, each with the model deployments you intend to use.
  • An Azure Database for PostgreSQL Flexible Server with the pgvector extension available.
  • A Storage account, only if you plan to use the durable Cloud Agent queue.

Required access:

  • The "Azure AI Developer" role on each Foundry project you reference.
  • A Microsoft Entra principal that PostgreSQL recognizes (the server Entra admin, or a role mapped to your principal).
  • The "Storage Queue Data Contributor" role on the Storage account when you enable the queue.

Step 1: Discover your resources

Run these read-only commands and keep the output nearby. You will paste values from here into .env in Step 3.

# Current subscription and signed-in user
az account show --query "{name:name, id:id, user:user.name}" -o json

# Foundry (AIServices) accounts
az cognitiveservices account list \
  --query "[].{name:name, kind:kind, location:location, rg:resourceGroup}" -o table

# Model deployments for one account (repeat for each account)
az cognitiveservices account deployment list -g <rg> -n <account> \
  --query "[].{name:name, model:properties.model.name}" -o table

# Foundry project name (used in the endpoint path)
az rest --method get \
  --url "https://management.azure.com/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<account>/projects?api-version=2025-04-01-preview" \
  --query "value[].name" -o json

# PostgreSQL Flexible Server
az postgres flexible-server list \
  --query "[].{name:name, fqdn:fullyQualifiedDomainName, rg:resourceGroup, version:version}" -o table

# PostgreSQL Microsoft Entra admin (who can sign in with a token)
az postgres flexible-server microsoft-entra-admin list -g <rg> --server-name <server> \
  --query "[].principalName" -o json

# Storage account (optional, for the Cloud Agent queue)
az storage account list --query "[].{name:name, queue:primaryEndpoints.queue}" -o table

Tip

A Foundry project endpoint always has the shape https://<account>.services.ai.azure.com/api/projects/<project>. The projects call returns <account>/<project>; the value after the slash is your <project>. On Azure CLI older than 2.86, the admin command is ad-admin rather than microsoft-entra-admin.

Step 2: Map deployments to Foundry endpoints

Concierge can target up to three Foundry projects. Choose each one by the model deployment it hosts.

Variable Use the Foundry project that hosts
AZURE_AI_PROJECT_ENDPOINT chat/LLM and embeddings (for example gpt-5, gpt-4o, text-embedding-3-small)
AZURE_AI_PROJECT_ENDPOINT_REALTIME the realtime model (for example gpt-realtime-1.5), often in a different region
AZURE_AI_PROJECT_ENDPOINT_IMAGE the image model (gpt-image-2), available in a limited set of regions

Note

A single Foundry resource can host all three. Separate endpoints exist only because realtime and image models are offered in fewer regions than the core chat models.

Step 3: Fill in .env

Edit .env (copied from .env.template). The block below is the minimum for an Azure-backed run. Replace every <...> placeholder with a value from Step 1.

# --- Foundry endpoints (see Step 2) ---
AZURE_AI_PROJECT_ENDPOINT=https://<llm-account>.services.ai.azure.com/api/projects/<project>
AZURE_AI_PROJECT_ENDPOINT_REALTIME=https://<realtime-account>.services.ai.azure.com/api/projects/<project>
AZURE_AI_PROJECT_ENDPOINT_IMAGE=https://<image-account>.services.ai.azure.com/api/projects/<project>

# --- Azure Database for PostgreSQL (Microsoft Entra auth) ---
AZURE_DBHOST=<server-name>.postgres.database.azure.com
AZURE_DBNAME=appdb
AZURE_DBUSER=<entra-principal>
AZURE_USE_ENTRA_AUTH=true

# --- Use Azure PostgreSQL for every app's persistence ---
TODO_REPOSITORY_BACKEND=azure-postgres
CHAT_REPOSITORY_BACKEND=azure-postgres
CLOUD_AGENT_REPOSITORY_BACKEND=azure-postgres

# --- Chat replies via the streaming Foundry responder ---
CHAT_BOT_AGENT_TYPE=foundry

Add these only when you want the matching optional feature.

# Knowledge search tool over Azure PostgreSQL
AGENTS_KNOWLEDGE__TOOLS=search_docs
AGENTS_KNOWLEDGE__TARGET=azure
AGENTS_KNOWLEDGE__SEARCH_DOCS__COLLECTION=knowledge_default

# Durable Cloud Agent queue
CLOUD_AGENT_QUEUE_BACKEND=azure-storage-queue
CLOUD_AGENT_AZURE_STORAGE_ACCOUNT_URL=https://<account>.queue.core.windows.net

AZURE_DBUSER must be a recognized Entra principal

AZURE_DBUSER must be the Microsoft Entra principal that PostgreSQL recognizes. When it is the server Entra admin, it can create tables right away. For any other principal, create a matching database role and grant privileges first. The PostgreSQL tutorial covers the Entra configuration.

Responder and tool availability

CHAT_RESPONDER_BACKEND is deprecated and emits a warning; use CHAT_BOT_AGENT_TYPE only. The foundry responder streams replies but does not call agent tools, so the knowledge tool is unavailable in text chat under that responder. To use the knowledge tool in text chat, set CHAT_BOT_AGENT_TYPE=langgraph. Realtime voice includes the knowledge tool regardless of the responder.

Step 4: Initialize the database schema

The SQL backends do not auto-migrate for the CLIs, so create the tables once per app.

uv run chat-cli db init     # chat_conversations, chat_participants, chat_messages
uv run todo-cli db init     # todo_tasks

The Cloud Agent web and worker create cloud_agent_tasks automatically on startup. To create it ahead of time:

uv run python -c "from dotenv import load_dotenv; load_dotenv(); from concierge.cloud_agent.infrastructure.persistence.factory import get_task_repository; get_task_repository()"

When you enabled the knowledge tool, populate its collection. The table is created on the first ingest.

uv run knowledge-cli ingest run ./docs --collection knowledge_default --target azure

All DDL uses CREATE TABLE IF NOT EXISTS, so re-running these commands is safe.

Step 5: Verify

A successful, idempotent re-run confirms the schema exists. You can also start an app and exercise it.

uv run chat-cli db init
uv run chat-web

Troubleshooting

Symptom Cause and fix
relation "chat_conversations" does not exist (or a todo or cloud_agent table) Schema not initialized. Run the matching Step 4 command.
Realtime endpoint closes with code 4503 AZURE_AI_PROJECT_ENDPOINT_REALTIME is empty. Set it in Step 3.
PostgreSQL login or permission errors Run az login, confirm AZURE_DBUSER is the Entra principal or role, and verify it has privileges on AZURE_DBNAME.
DeprecationWarning mentioning CHAT_RESPONDER_BACKEND Remove that variable and use CHAT_BOT_AGENT_TYPE.