Build, break, explain.
Warranty Desk
A support agent for Campux Retail that looks up the order before it states a warranty date, and says so when it cannot.
- build time
- 4 to 6 hours
- cost
- Under $5 if torn down the same day3
- services
- Foundry Agent Service, Azure Functions, Cosmos DB, Entra ID, Application Insights, Container Apps
- assumes
- You can explain resource group, Entra ID, managed identity, role assignment. If not, do Project 00 first.
- exams
- Overlaps AI-103, AI-200
- vocabulary
- Hosted agent, project endpoint, OpenAPI tool, file search, managed memory, platform identity, trace
The problem
Campux Retail's warranty inbox gets the same three questions four hundred times a week: is this still covered, where is my replacement, what does the policy say.
The head of support has already had a chatbot. It apologised a lot and answered nothing. She wants one that looks things up, quotes the policy correctly, hands over to a person when it should, and reports every Monday how many it got wrong.
- definition
- Agent. A model in a loop that can call tools, keep state across turns, and decide when to stop. No tools, it is a chat completion. No state, it is a stateless API. You are building the loop, not the model.
The architecture
Seven parts. Every arrow is a managed identity and a role assignment. Nothing holds a key.
- Sign in. The customer opens the Streamlit app on Azure Container Apps and signs in with Microsoft Entra ID.
- Call the agent. The app calls the hosted agent in the Foundry project with the customer's own identity, not a shared key.
- Reason. The agent runs the gpt-5.4-mini deployment to decide whether to answer or call a tool.
- Use a tool. It searches the policy vector store, or invokes the OpenAPI tool for order data.
- Hit the API. The OpenAPI tool calls Azure Functions, which run as a system-assigned managed identity.
- Read the data. The Function reads the order and computes the warranty end date from Azure Cosmos DB.
- Remember. The agent reads and writes per-user managed memory so the next turn has context.
- Trace it. Every hop is exported to Application Insights for the Monday accuracy report.
| Job | Bedrock version | This build | Same idea? |
|---|---|---|---|
| Model | Bedrock model | Foundry model deployment | Yes |
| Agent runtime | AgentCore Runtime | Foundry Agent Service, hosted agent1 | Yes, but you bring the container |
| Memory | AgentCore Memory | Foundry managed memory, Cosmos DB backed | Yes |
| Actions | Lambda via action groups | Azure Functions via OpenAPI tool | Yes |
| Knowledge | Knowledge base | File search over policy PDFs | Yes. Project 02 replaces it with Foundry IQ |
| Identity | IAM + Cognito | Entra ID + managed identity + Foundry roles | Different |
| Observability | CloudWatch | Agent Monitoring Dashboard + Application Insights | Different. Foundry ships evals, not just logs |
| Front end | Streamlit | Streamlit on Container Apps | Same |
The build
In this order. If a check fails, stop. A mistake in step 4 shows up in step 6 as a failure you cannot explain.
-
Foundry project and model
Create a Foundry resource and project in a region with gpt-5.4-mini quota. Deploy the model, Standard SKU, capacity 10. Copy the project endpoint.
az login azd auth login azd ext install microsoft.foundry pip install "azure-ai-projects>=2.3.0" azure-identity python-dotenv
The model answers in the Foundry playground. -
Orders data
Cosmos DB, serverless. Database
A query forretail, containerorders, partition/customerId. Load the twenty sample orders from the project repo.customerId = "c-0007"returns three orders. -
Two tools as Azure Functions
Python Function App, two routes:
GET /orders?customerId=andGET /warranty?orderId=. Warranty returns{ "covered": true, "endsOn": "2027-03-14" }. System-assigned identity with Cosmos DB Built-in Data Reader. Publish an OpenAPI 3 document; the agent reads it to learn what the tools do, so the descriptions are prompts.curlboth routes with an Entra token. Confirm the date for ordero-1042by hand. -
Policy documents
Upload the three policy PDFs (returns, extended warranty, exclusions) to a file search vector store. Read the exclusions PDF yourself; it has the clause the agent will get wrong later.
The vector store shows three files indexed. -
The agent
Scaffold a hosted agent from the Agent Framework sample. Add instructions, the file search tool, and the OpenAPI tool pointing at your Function App. Run it locally first.
azd ai agent init -m "https://github.com/microsoft-foundry/foundry-samples/blob/main/samples/python/hosted-agents/agent-framework/responses/01-basic/azure.yaml" --deploy-mode code azd ai agent run # local azd deploy # to Foundry Agent Service
The instructions must say: check the order before stating any date; quote policy only from the documents; if a tool fails, say so and offer a person; never guess.
"Is order o-1042 still covered?" produces a tool call and the date you computed in step 3. -
Memory
Create a memory store, then attach the
Two things, in this order. First: memory is region-gated and is not in the tool-by-region table. It failed for us in East US with "Memory Tool is not supported in this region", after the store and the agent had both been created without complaint, and worked in West US 3. Second, and this is the one that matters: sign in as one customer, tell the agent something private, then ask for it as a different customer. A second customer must get nothing. When we ran this, they got everything. Do not go on until you have run this test yourself and seen the result with your own eyes.memory_search_previewtool to the agent. The store needs a chat model and an embedding model deployment, and creating one needs an opt-in header,Foundry-Features: MemoryStores=V1Preview. Set the tool'sscopeand send the customer's id asx-memory-user-idon every call.4 -
Identity
Streamlit signs the customer in with Entra ID and calls the agent as that customer. The agent's platform identity gets Foundry User on the project. The Function App accepts only the agent's identity. Remove every key you used while getting things working.
grep -ri key .env*returns nothing. An anonymous call to the Function App gets a 401. -
Observability
Connect Application Insights, turn on tracing, open the Agent Monitoring Dashboard. Run ten conversations; stop the Function App for three of them.
You can point at one trace and show the tool error, the model's next step, and what the customer was told. -
Front end
Streamlit on Container Apps with a system-assigned identity. Sign in, start a conversation, stream replies, show a "handed to a person" banner on the escalation phrase.
Someone who has never seen the project asks about their warranty from a phone and gets the right date. -
Tear it down
azd down
Then check the resource group.
The resource group is empty. Today's cost is under $5.azd downonly removes whatazdcreated; the Cosmos account and Function App are yours to delete.
Where it breaks
Cause each one on purpose. Tick it when you can describe the failure and the fix from memory.
The trade-offs
- Hosted agent, or your own container?
- Hosted gives you the dashboard, per-user memory and a platform identity for free, in preview. Your own loop on Container Apps gives control and no preview risk, and you build memory and tracing yourself. This build chooses hosted because observability is the point.
- OpenAPI tools, or an MCP toolbox?
- OpenAPI is the short path when the APIs already exist. A toolbox over MCP wins once several agents share tools. Project 04 makes that move.
- File search, or Azure AI Search with Foundry IQ?
- Three PDFs do not need a search service. Three thousand do, and so does anything with document permissions. Project 02 makes the switch.
- gpt-5.4-mini, or the larger model?
- Lookups and quotations. The small model does them at a fraction of the cost. Test the larger one on the exclusions clause only, and prove it in Project 03.
- Managed memory, or history in the prompt?
- Prompt history is simple, grows linearly in cost, and leaks nothing between customers because there is nothing shared to leak. Managed memory summarises, persists across sessions, and is in preview: region-gated, behind an opt-in header, and in our run its per-user scoping did not isolate. For a support desk holding order numbers and names, prompt history until your own isolation test passes is the defensible choice, and "I tested it and it failed, so I did not ship it" is a better interview answer than a feature you never checked.
In the interview
"Tell me about an agent you have built."
- decisionA warranty agent on Foundry: two Function tools, file search over policy, per-user memory, handoff when a tool fails.
- reasonEvery hop is managed identity. No keys.
- watchedApplication Insights traces for every answer it gave.
"What happens when the order API is down?"
- decisionThe tool returns an explicit error; instructions forbid a date without a tool result; the agent offers a person.
- reasonThe first version invented a date. That is why the instruction exists.
- watchedStopped the Function App and read the traces.
"Why Foundry instead of building the loop yourself?"
- decisionHosted, for the platform identity, memory scoping and monitoring dashboard.
- reasonA support desk that reports accuracy every Monday needs observability more than control.
- watchedPreview status. For a batch pipeline I might choose differently.
Evidence
- Figure 2, redrawn by you
- From memory, on paper, then compared.
- One trace screenshot
- The tool-failure conversation: the error, the model's next step, the final message.
- The repo
- Instructions file, OpenAPI document, Bicep for Functions and Cosmos, and a README that opens with the trade-offs, not the install steps.
- One sentence for the résumé
- "Built and deployed a customer support agent on Microsoft Foundry with tool calling, per-user memory, managed-identity auth and end-to-end tracing; tested failure handling for downstream API outages."
Next
Notes
- Hosted agents were in preview when this was written (September 2026) and commands were checked against Microsoft Learn on that date. If
azd ai agent inithas changed shape, the Learn page wins; tell us and we will fix it. - Foundry's RBAC roles were renamed in 2026 (Foundry User, Foundry Project Manager, and so on). Older tutorials use the old names; the permissions did not change.
- Built and run in a real Azure subscription on 3 September 2026. Memory is a preview feature and this is what we found on that day: creating a store needs the
Foundry-Features: MemoryStores=V1Previewheader; the store and an agent referencing it were both created successfully in East US, where the tool then failed at runtime as unsupported, while West US 3 worked; and withscopeset to{{$userId}}thex-memory-user-idheader did not change the scope, so two customers shared one memory. A hard-coded scope isolated correctly. Preview features move, and this may be fixed by the time you read it, which is the reason the check tells you to run the two-customer test rather than trust this footnote. - "Under $5" assumes serverless Cosmos DB, Consumption Functions, a Standard model deployment, and teardown the same day. Leave a provisioned Cosmos account running for a week and this footnote is wrong.