CAMPUX learn / ai / 01
Project 01 of 09
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.

Warranty Desk solution architecture: a customer signs in to a Streamlit app on Azure Container Apps, which calls a hosted agent in a Microsoft Foundry project; the agent uses a model deployment, per-user managed memory, file search and an OpenAPI tool that invokes Azure Functions reading Azure Cosmos DB; tracing flows to Application Insights; Microsoft Entra ID is the identity plane for every hop. the agent is the only thing that ever touches the data CLIENT MICROSOFT FOUNDRY PROJECT DATA AND OBSERVABILITY Customerweb browser Container AppsStreamlit UIEntra sign-in Hosted agent · Foundry Agent ServiceAgent Framework · your container · man in the middle Model deploymentgpt-5.4-mini · Standard Managed memoryper-user scope Toolsfile search · vector store of policy PDFsOpenAPI tool · calls Azure Functions Tracing and evaluationOpenTelemetry export · Agent Monitoring Dashboard Application Insightstraces · metrics · cost Azure FunctionsGET /orders · GET /warrantymanaged identity, no key Azure Cosmos DBorders, keyed by customerData Reader role, via identity Microsoft Entra IDuser sign-in · managed identities · Foundry RBAC roles (Foundry User, Project Manager) · no API keys anywhere 1 2 3 4 5 6 7 8
livepress play to watch one warranty question move through the system
Figure 2 The solution architecture. Green-outlined tiles are objects you create inside Foundry; the grey tiles are the Azure services around it. Every numbered hop is an identity, never a key. Redraw this from memory before the interview.
  1. Sign in. The customer opens the Streamlit app on Azure Container Apps and signs in with Microsoft Entra ID.
  2. Call the agent. The app calls the hosted agent in the Foundry project with the customer's own identity, not a shared key.
  3. Reason. The agent runs the gpt-5.4-mini deployment to decide whether to answer or call a tool.
  4. Use a tool. It searches the policy vector store, or invokes the OpenAPI tool for order data.
  5. Hit the API. The OpenAPI tool calls Azure Functions, which run as a system-assigned managed identity.
  6. Read the data. The Function reads the order and computes the warranty end date from Azure Cosmos DB.
  7. Remember. The agent reads and writes per-user managed memory so the next turn has context.
  8. Trace it. Every hop is exported to Application Insights for the Monday accuracy report.
Service map, for readers coming from AWS
JobBedrock versionThis buildSame idea?
ModelBedrock modelFoundry model deploymentYes
Agent runtimeAgentCore RuntimeFoundry Agent Service, hosted agent1Yes, but you bring the container
MemoryAgentCore MemoryFoundry managed memory, Cosmos DB backedYes
ActionsLambda via action groupsAzure Functions via OpenAPI toolYes
KnowledgeKnowledge baseFile search over policy PDFsYes. Project 02 replaces it with Foundry IQ
IdentityIAM + CognitoEntra ID + managed identity + Foundry rolesDifferent
ObservabilityCloudWatchAgent Monitoring Dashboard + Application InsightsDifferent. Foundry ships evals, not just logs
Front endStreamlitStreamlit on Container AppsSame

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.

  1. 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.
  2. Orders data

    Cosmos DB, serverless. Database retail, container orders, partition /customerId. Load the twenty sample orders from the project repo.

    A query for customerId = "c-0007" returns three orders.
  3. Two tools as Azure Functions

    Python Function App, two routes: GET /orders?customerId= and GET /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.

    curl both routes with an Entra token. Confirm the date for order o-1042 by hand.
  4. 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.
  5. 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.
  6. Memory

    Create a memory store, then attach the memory_search_preview tool 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's scope and send the customer's id as x-memory-user-id on every call.4

    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.
  7. 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.
  8. 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.
  9. 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.
  10. Tear it down
    azd down

    Then check the resource group. azd down only removes what azd created; the Cosmos account and Function App are yours to delete.

    The resource group is empty. Today's cost is under $5.

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

  1. 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 init has changed shape, the Learn page wins; tell us and we will fix it.
  2. 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.
  3. 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=V1Preview header; 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 with scope set to {{$userId}} the x-memory-user-id header 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.
  4. "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.