A RAG chat sample that uses the real Foundry Agents SDK (azure-ai-agents)
with a single FileSearchTool wired up to a Foundry-hosted vector store.
The retrieval loop runs entirely server-side: the app just creates the agent,
appends user messages, and reads back assistant messages with file citations.
This sample is the knowledge-grounded sibling of embr-foundry-agent-sample.
Same auth story, same agent-create-then-list flow, same Embr deploy shape —
but instead of local Python function tools (get_weather, roll_dice), the
agent has a Foundry FileSearchTool over a vector store the developer
populates with scripts/bootstrap_vector_store.py.
app/
agent.py # AgentsClient wrapper, FileSearchTool, run loop, citation extraction
main.py # FastAPI: /api/chat, /api/threads, /api/agent, /api/config
static/
index.html # chat UI + citations side panel
scripts/
bootstrap_vector_store.py # one-shot: upload files + create vector store
sample-docs/
about.md, pricing.md, docs.md, faq.md # fictional "Embr Corp" docs
embr.yaml # Embr platform config (Python 3.12, port 8000, /health)
requirements.txt
| Var | Required | Purpose |
|---|---|---|
FOUNDRY_PROJECT_ENDPOINT |
yes | Foundry project endpoint, e.g. https://{name}.services.ai.azure.com/api/projects/{project} |
FOUNDRY_MODEL_DEPLOYMENT |
yes | Foundry model deployment name (e.g. gpt-5.4-mini-1) |
FOUNDRY_VECTOR_STORE_ID |
yes | The vector store ID printed by bootstrap_vector_store.py |
AZURE_TENANT_ID |
on Embr | SP tenant id |
AZURE_CLIENT_ID |
on Embr | SP client id |
AZURE_CLIENT_SECRET |
on Embr | SP client secret |
EMBR_AGENT_FORCE_RECREATE |
no | If 1, recreate the agent every cold start |
git clone https://github.com/embr-devs/embr-foundry-rag-sample
cd embr-foundry-rag-sample
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
az login # provides DefaultAzureCredential
export FOUNDRY_PROJECT_ENDPOINT="https://{name}.services.ai.azure.com/api/projects/{project}"
export FOUNDRY_MODEL_DEPLOYMENT="gpt-5.4-mini-1"
# 1) create the vector store from sample-docs/
python scripts/bootstrap_vector_store.py sample-docs/
# ... prints: FOUNDRY_VECTOR_STORE_ID=vs_abc123...
# 2) export the printed id
export FOUNDRY_VECTOR_STORE_ID=vs_abc123...
# 3) run
uvicorn app.main:app --reload --port 8000Open http://localhost:8000 and try:
- "how much is the Team plan?"
- "what runtimes does Cinder support?"
- "do you offer GPUs?"
Each assistant reply shows a 📄 filename chip per source, and the side panel
shows the exact retrieved quote.
embr quickstart deploy embr-devs/embr-foundry-rag-sample -i 120233234Then set the six required env vars (replace placeholders with your values):
PROJ=<projectId>; ENV=<environmentId>
embr variables set FOUNDRY_PROJECT_ENDPOINT 'https://...services.ai.azure.com/api/projects/proj-default' -p $PROJ -e $ENV
embr variables set FOUNDRY_MODEL_DEPLOYMENT 'gpt-5.4-mini-1' -p $PROJ -e $ENV
embr variables set FOUNDRY_VECTOR_STORE_ID 'vs_abc123...' -p $PROJ -e $ENV
embr variables set AZURE_TENANT_ID '<tenant-guid>' -p $PROJ -e $ENV
embr variables set AZURE_CLIENT_ID '<sp-client-id>' -p $PROJ -e $ENV
embr variables set AZURE_CLIENT_SECRET '<sp-secret>' -p $PROJ -e $ENV --secret
embr deployments trigger -c HEAD -p $PROJ -e $ENVThis sample exists to surface gaps in the Embr × Foundry integration:
-
No managed identity → SP secret in env vars. Foundry's Agents control plane requires AAD/RBAC; API keys are rejected. Embr does not expose a managed identity to app code, so the only way to obtain a token is to bundle a service principal's client secret (
AZURE_CLIENT_SECRET) as an env var. This is the same findingembr-foundry-agent-sampleraises. -
No
knowledge-base:dep type inembr.yaml. A RAG-shaped app has first-class infrastructure: a vector store, the file IDs inside it, and a logical name for the knowledge base. None of that is modeled inembr.yamltoday. The developer has to:a. Run an out-of-band script (
bootstrap_vector_store.py) to create the store and upload files, b. Copy the printed vector store ID by hand, c. Pipe it in as a nakedFOUNDRY_VECTOR_STORE_IDenv var.The "right" Embr shape would be a declared dependency, e.g.:
dependencies: - name: corp-docs type: knowledge-base provider: foundry sources: - ./sample-docs/
…with the platform handling provisioning, file sync on push, and injecting the vector store ID into the runtime automatically.
-
No automatic vector-store provisioning. Even if the dep type existed, today there is no platform mechanism for re-syncing files when they change in the repo. The bootstrap script is one-shot; updating a doc means re-running it manually.
- Server-side retrieval. The app never sees document text directly —
Foundry retrieves chunks, grounds the model, and returns assistant
messages with
MessageTextFileCitationAnnotations. The app just renders the resulting citations. - Citation rendering. Each assistant message gets a chip row of source filenames, and the side panel shows the exact retrieved quote per citation.
- Server-side state. Click "Show server-side thread" — the conversation lives in Foundry, not in this app.
- Agent reuse. The agent is created with name
embr-foundry-rag-sample. On restart, the app callslist_agents()and reuses the existing one.