ERW CommandPMO

AI-103 CERTIFICATION BOOTCAMP

Developing AI Apps and Agents on Azure — Build it, run it, name it exactly.

← Course home
40 sessions · 45 minutes each · 8 weeks at your own pace · One track: your own Azure subscription
WEEK 3 OF 8 · AGENTS · SESSIONS 11–15
This week’s assessments: Pop Quiz 3 — Agents after Session 15
Every session: the exact names Microsoft uses · one assignment marked against a published rubric · pass mark 70 · Certificate: capstone at 70+ and the marked Final at 700+
A · Plan and manage an Azure AI solution · 25–30%SESSION 11
Choosing memory, tool and knowledge services for agents
Session 11 of 40 · 45-minute session
Skills measured — Microsoft’s wording
  • Choose appropriate memory, tool, and knowledge integration services for agent solutions

Why This Matters

An agent is only as useful as what it can reach. Give it the wrong tool and it guesses. Give it the wrong knowledge source and it cites the wrong policy. Forget memory and it asks a returning customer the same question twice. AI-103 tests this as a design choice: which built-in tool, which custom tool, which knowledge service, which kind of memory. This is the agents week, and it starts on paper on purpose. Today you learn the current tool catalogue in Foundry Agent Service, what each tool is for and whether it is generally available, and you design the tools, knowledge and memory for an agent you would actually build.

IN YOUR SUBSCRIPTION
Creates
Nothing. This is a design session: you read the tool, knowledge and memory options and write a design. No agent, vector store, memory store or connection is created.
Cost
Nothing new is billed today. Your design must still account for cost, because tools carry their own meters: the Foundry Agent Service pricing page (azure.microsoft.com/en-us/pricing/details/foundry-agent-service) lists File Search Storage, Code Interpreter and Web Search under tools and knowledge, and notes extra charges for Grounding with Bing Search and Foundry IQ. I quote no prices; use that page and the pricing calculator.
Clean-up
Nothing to delete. If a model deployment is still running from Week 2 and you are not starting Session 12 today, delete it: Foundry portal → Build → Models, or az cognitiveservices account deployment delete. Keep rg-ai103 and the project.
The 45-Minute Session
8:00 – 19:00
The tool catalogue: built-in and custom
  • Built-in tools are preconfigured: you switch them on and the service runs them, with no hosting or code of your own. Custom tools extend the agent with your own APIs, services or other agents, for when the built-in ones do not cover the scenario.
  • Tool (Learn’s name)What it doesNew Foundry status, at the time of writing
    Web searchReal-time public web results with inline citationsGA
    File SearchSearches files you upload into a vector storeGA
    Code InterpreterWrites and runs Python in a sandbox for analysis, charts and filesGA
    Azure AI SearchGrounds answers in an existing Azure AI Search indexGA
    Function callingThe model asks for your function; your app runs it and returns the resultGA
    OpenAPI toolCalls an external HTTP API described by an OpenAPI 3.0 or 3.1 specificationGA
    Model Context Protocol (MCP)Calls tools hosted on a remote MCP server endpointGA
    Agent-to-Agent (A2A), SharePoint, Microsoft Fabric, Browser Automation, Computer Use, Image GenerationSpecialist tools for other agents, Microsoft 365 and Fabric data, browsers, desktops and imagesPreview
  • The status column comes from Learn’s migration table, which compares classic and new Foundry. Two traps live there. MCP is GA in the new service although it was preview in classic. And Connected Agents, a classic tool, is not in the new service at all. Session 15 covers what replaced it.
  • Web grounding has two routes. Web search is Learn’s recommended start: Microsoft manages the Grounding with Bing resource for you, and no extra Azure resource is needed. Grounding with Bing Search needs a Grounding with Bing Search resource of your own and a project connection. Both are GA; Learn’s comparison lists Azure OpenAI models for Web search, and Foundry Models sold by Azure as well for Grounding with Bing Search.
  • THE EXAM LINE

    Web search and Grounding with Bing Search both send data outside the Azure compliance boundary, and the Microsoft Data Protection Addendum does not apply to data sent to Grounding with Bing. Exclude them when data must stay inside.

  • Candidates blur the three custom routes. Function calling: the code runs in your app, which sends the result back. OpenAPI tool: the service calls an HTTP API from its specification. MCP: the service calls a remote MCP server; the runtime only accepts remote endpoints, so a local server must be hosted first, for example on Azure Container Apps.
  • Learn now recommends offering tools through a Toolbox: tools defined once behind a single MCP-compatible endpoint, with credentials and policy managed centrally. Promote a new toolbox version and every agent pointing at it picks it up with no code changes.
For each tool, say out loud who runs it: the service, your app, or someone else’s server. That one question settles most tool questions.
28:00 – 37:00
Memory: this conversation, and the next one
  • Learn separates two kinds. Short-term memory tracks the current session; in Foundry Agent Service that is the conversation object, or a chain of responses linked by previous_response_id. Long-term memory retains distilled knowledge across sessions, so a returning user does not start from nothing.
  • Long-term memory lives in a managed memory store, in preview at the time of writing. Learn names three memory types:
  • Memory typeWhat it keepsExample (illustrative)
    User profile memoryDurable preferences and personal context, such as language or accessibility needsA patient prefers letters in large print
    Chat summary memoryDistilled summaries of earlier conversation topicsLast week the visitor asked about parking at the east entrance
    Procedural memoryReusable routines inferred from earlier interactionsThis clerk always exports the ward list before filtering it
  • There are two ways in. Attach the memory search tool to a prompt agent and it reads from and writes to the store during conversations; Learn calls this ideal for most scenarios. Or call the Memory Store API directly when you need control over individual records and retention. A scope partitions the memories, typically one scope per end user.
  • THE EXAM LINE

    Conversation history is short-term memory for one session. A memory store (preview) is long-term memory across sessions, with user profile, chat summary and procedural memory, partitioned by scope and usually attached through the memory search tool.

  • Memory is data about people, so decide what it must never keep; Learn’s example excludes age, financials, precise location and credentials. It is billed through the chat and embedding models it uses.
If you cannot say which facts the agent should forget, you are not ready to give it long-term memory.

The exact names

As Microsoft prints them — the exam and the marker both expect these, letter for letter.
Web searchtoolBuilt-in tool that grounds answers in real-time public web results with inline citations.Learn →
File SearchtoolBuilt-in tool that searches files you upload into a vector store.Learn →
Code InterpretertoolBuilt-in tool that writes and runs Python code in a sandboxed environment.Learn →
Function callingtoolCustom functions the agent can ask for; your app runs them and returns the result.Learn →
OpenAPI tooltoolConnects an agent to an external HTTP API described by an OpenAPI 3.0 or 3.1 specification.Learn →
Model Context Protocol (MCP)toolConnects an agent to tools hosted on a remote MCP server endpoint.Learn →
ToolboxfeatureA curated, versioned set of tools exposed through one MCP-compatible endpoint for many agents.Learn →
Grounding with Bing SearchtoolWeb grounding tool that needs your own Grounding with Bing Search resource and a project connection.Learn →
memory storeconceptThe managed store (preview) that holds an agent’s long-term memories across sessions.Learn →
User profile memoryconceptMemory type for durable preferences and personal context, such as language or accessibility needs.Learn →
Chat summary memoryconceptMemory type holding distilled summaries of earlier conversation topics.Learn →
Procedural memoryconceptMemory type holding reusable routines inferred from earlier interactions.Learn →
knowledge sourcesconceptThe connections to indexed or remote content that make up a Foundry IQ knowledge base.Learn →
Every name in the course is on one printable page: download the AI-103 cheat sheet (PDF).
Key Terms

Custom tool

A tool you supply: your own function, an OpenAPI-described API, an MCP server or another agent.

Memory scope

The key that partitions a memory store, usually one per end user, so one person’s memories never reach another.

Self-Check — Before You Submit
1. A bank’s data team already maintains an Azure AI Search index of product terms. The new agent must answer from that index. Which tool fits?
  • A. File Search with a new vector store
  • B. The Azure AI Search tool, through a project connection
  • C. Web search
  • D. Code Interpreter
B. The Azure AI Search tool, through a project connection — The Azure AI Search tool grounds an agent in an existing index you own, through a project connection. File Search would mean copying the content into a new vector store, which duplicates work the index already does.
2. A public agency’s agent must never send any data outside the Azure compliance boundary. Which tool should the design leave out?
  • A. Function calling
  • B. File Search
  • C. Grounding with Bing Search
  • D. Code Interpreter
C. Grounding with Bing Search — Learn states that data sent to Grounding with Bing Search flows outside the Azure compliance boundary and the Data Protection Addendum does not apply. Function calling runs in the agency’s own app, so it is not the problem.
3. A retailer wants its agent to remember a customer’s preferred delivery slot in a chat next month, not just in today’s chat. What provides that?
  • A. A memory store attached with the memory search tool, scoped per user
  • B. The same conversation object reused for a month
  • C. A larger context window
  • D. Setting store to false
A. A memory store attached with the memory search tool, scoped per user — Long-term memory across sessions is what a memory store provides, with user profile memory for preferences and a per-user scope. A conversation is short-term memory for one chat, and store=False keeps nothing at all.

Today’s Assignment

Design the tools, knowledge and memory for an agent you would build at work, using Learn’s exact tool names, with the status and data-boundary decisions justified.
  • Describe the agent in 60–100 words: who uses it, what it must do, and what data it touches. Use a real organisation or a clearly illustrative one.
  • Build a tools table with at least four tools, mixing built-in and custom. For each give the exact name, who runs it (the service, your app, or an external server), how it authenticates, and its status (GA or preview) with the date you checked.
  • Choose the knowledge option for each body of content (File Search, Azure AI Search tool, Foundry IQ knowledge base, Web search) and say why the obvious alternative loses.
  • Choose the memory design: short-term only, or long-term as well. If long-term, name the memory types you enable, the scope, and at least three kinds of data the store must never keep.
  • Add one paragraph on data leaving the compliance boundary and on anything in preview, and say whether you would use a Toolbox.
  • Keep the explanation between 300 and 700 words. Never include keys, secrets, credentials or connection strings.
Evidence to include
  • Your tools, knowledge and memory tables, complete with the “who runs it” and status columns.
  • A screenshot of the Learn page or pricing page you used to confirm each tool’s status or meter, with the page date visible.
  • A simple diagram (hand-drawn is fine) showing the agent, its tools and where each knowledge source lives.
Names your answer must use exactly
Web search File Search Function calling Model Context Protocol (MCP) memory store Toolbox
Never include a key, a connection string or a token. Crop them out of every screenshot. If one is exposed, the letter will tell you to rotate it.
How this is marked — the rubric
Each tool, knowledge and memory choice fits the agent and rules out a plausible alternative35
Status, data-boundary and authentication decisions are stated and justified20
Uses the exact tool and memory names from this session’s names box20
Evidence: the tables, the status screenshots and the diagram are included, with no keys or secrets anywhere25
Total · pass mark 70100
Submitting session 11
Write your answer in Word or Google Docs, with your screenshots pasted in. The top of the document must carry the line Session: 11 (the template has it ready, under the Course line), or the submission is refused. Upload the Word file (.docx), or switch to the Google Doc tab and paste your document’s share link.
Marked against the rubric above and returned as a written letter by email; the mark appears on your progress page. Do the self-check above before you submit.
Skills Covered
Built-in and custom agent toolsWeb grounding choicesKnowledge options for agentsShort- and long-term memoryTool status and data boundaries
Tick it once you have submitted.Next: Session 12 →
B · Implement generative AI and agentic solutions · 30–35%SESSION 12
Defining an agent: role, goals, conversation tracking, tool schemas
Session 12 of 40 · 45-minute session
Skills measured — Microsoft’s wording
  • Define agent roles, goals, conversation-tracking approach, and tool schemas

Why This Matters

The objective reads “Define agent roles, goals, conversation-tracking approach, and tool schemas”, and each of those four nouns is a place where real agents go wrong. Vague instructions give you an agent that wanders. A loose tool schema gives you arguments your code cannot use. The wrong conversation-tracking choice gives you an agent that forgets what it asked a minute ago, or one that keeps data you were told not to keep. Today you write an agent’s role and goals properly, define a function tool with a strict JSON schema, choose how the conversation is tracked, and run it in Python with a trace of every item.

IN YOUR SUBSCRIPTION
Creates
One prompt agent (parcel-agent) with one or more immutable versions, and one or more conversations, inside your Foundry project. It calls a model deployment in rg-ai103: if you deleted yours at the end of Week 2, redeploy one on Global Standard as in Session 4. The function itself runs on your laptop, not in Azure.
Cost
Billed per token on the model deployment, for every response, including the extra response that carries the function result back. The Foundry Agent Service pricing page lists meters for models, hosted agents and tools; this session uses model tokens only. Check that page and the Microsoft Foundry pricing page for your model.
Clean-up
Run cleanup.py in the wrap-up to delete every agent version and the conversation. Keep the model deployment for Session 13; if you are pausing for more than a day, delete it (Foundry portal → Build → Models, or az cognitiveservices account deployment delete).
The 45-Minute Session
9:00 – 19:00
Tool schemas: the contract between model and code
  • A function tool is a contract. Its name and description tell the model when to call it; its parameters, a JSON schema, tell it exactly what to send. In Session 8 you passed a function to a model call; here the agent definition holds it, so every conversation gets the same contract.
  • In the Foundry SDK the class is FunctionTool. The parameters object has type, properties (a type and description for each), required, and additionalProperties set to False so the model cannot invent fields. Learn’s function-calling sample also sets strict=True, which enforces stricter validation of the schema.
  • Set up your shell as in Week 1 (FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL_NAME, the deployment name), then create the agent. The code follows Learn’s Use function calling with Microsoft Foundry agents how-to.
  • pythondefine_agent.pytype it yourself
    import os
    from azure.identity import DefaultAzureCredential
    from azure.ai.projects import AIProjectClient
    from azure.ai.projects.models import PromptAgentDefinition, FunctionTool
    
    INSTRUCTIONS = """Role: You are the parcel-tracking assistant for a Lagos logistics firm.
    Goals: 1) Tell customers where their parcel is. 2) Set honest expectations.
    3) Hand over to a human colleague when you are unsure.
    Tools: Call get_parcel_status whenever the customer gives a tracking ID.
    If the ID is missing, ask for it. Never guess a status.
    Limits: Never promise refunds or delivery dates that the tool did not return.
    Style: Plain English, three sentences or fewer."""
    
    status_tool = FunctionTool(
        name="get_parcel_status",
        description="Look up the latest status of a parcel by its tracking ID.",
        parameters={
            "type": "object",
            "properties": {
                "tracking_id": {"type": "string", "description": "Tracking ID, for example LOS-48213"},
                "detail": {"type": "string", "enum": ["summary", "full"], "description": "How much history to return"},
            },
            "required": ["tracking_id", "detail"],
            "additionalProperties": False,
        },
        strict=True,
    )
    
    project = AIProjectClient(endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], credential=DefaultAzureCredential())
    agent = project.agents.create_version(
        agent_name="parcel-agent",
        definition=PromptAgentDefinition(
            model=os.environ["FOUNDRY_MODEL_NAME"],  # your deployment name
            instructions=INSTRUCTIONS,
            tools=[status_tool],
        ),
    )
    print(f"Agent created (name: {agent.name}, version: {agent.version})")
    WHAT YOU SHOULD SEE
    Agent created (name: parcel-agent, version: 1)
  • Two schema habits pay off. Use enum where only a few values make sense, as with detail; Learn’s model function-calling page uses the same keyword for temperature units. And write every description for a new colleague: an example value such as LOS-48213 teaches the format better than a paragraph.
  • THE EXAM LINE

    FunctionTool takes a name, a description and a parameters JSON schema (type, properties, required, additionalProperties); strict=True enforces stricter validation. The model only proposes the call. Your application runs the function.

A schema that allows anything will eventually receive anything.
27:00 – 38:00
Hands-on: run the agent and trace every item
  • Here is the flow Learn’s how-to shows. The response contains a function_call item with a call_id and JSON arguments. Your app runs the function and sends a function_call_output with the same call_id, in the same conversation. The agent then writes the final answer.
  • The script refers to the agent through agent_reference in extra_body, as Learn’s samples do. Session 4 used the other documented pattern, project.get_openai_client(agent_name=...), which returns a client already bound to one agent. Both reach the same agent; here the client stays unbound and each request names the agent. The script also prints the type of every output item. That printout is the trace your assignment needs.
  • pythontrack_conversation.pytype it yourself
    import json
    import os
    from azure.identity import DefaultAzureCredential
    from azure.ai.projects import AIProjectClient
    from openai.types.responses.response_input_param import FunctionCallOutput
    
    def get_parcel_status(tracking_id: str, detail: str) -> str:
        # Illustrative stand-in for the firm's tracking system
        return json.dumps({"tracking_id": tracking_id, "status": "At Abuja hub", "updated": "09:40"})
    
    project = AIProjectClient(endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], credential=DefaultAzureCredential())
    openai = project.get_openai_client()
    agent = {"agent_reference": {"name": "parcel-agent", "type": "agent_reference"}}
    
    conversation = openai.conversations.create()  # durable, server-side history
    print("Conversation:", conversation.id)
    
    for text in ["Where is my parcel?", "Sorry, the tracking ID is LOS-48213."]:
        print("User:", text)
        response = openai.responses.create(conversation=conversation.id, input=text, extra_body=agent)
        outputs = []
        for item in response.output:
            print(f"  [{item.type}]")
            if item.type == "function_call" and item.name == "get_parcel_status":
                print(f"  -> {item.name}({item.arguments})")
                outputs.append(FunctionCallOutput(
                    type="function_call_output",
                    call_id=item.call_id,
                    output=get_parcel_status(**json.loads(item.arguments)),
                ))
        if outputs:  # your app ran the function: hand the result back in the same conversation
            response = openai.responses.create(conversation=conversation.id, input=outputs, extra_body=agent)
        print("Agent:", response.output_text)
    WHAT YOU SHOULD SEE
    Conversation: <conversation-id>
    User: Where is my parcel?
      [message]
    Agent: <asks you for the tracking ID>
    User: Sorry, the tracking ID is LOS-48213.
      [function_call]
      -> get_parcel_status({"tracking_id":"LOS-48213","detail":"summary"})
    Agent: <says the parcel is at the Abuja hub, updated 09:40>
  • Notice the first turn: with no ID, a well-instructed agent asks for one instead of calling the tool. If yours calls the function with an invented ID, the instructions are too weak. Tighten them, save a new version and run the script again.
  • Learn notes that runs expire 10 minutes after creation, at the time of writing, so return tool outputs promptly. In production the function would call your tracking system: treat what it returns as untrusted input and validate it before it reaches a customer.
  • Now change one word in INSTRUCTIONS, run define_agent.py again and note the new version number. The endpoint serves the latest version by default, so the next conversation uses it.
The trace is your evidence. A transcript without the item types only shows me the ending.

The exact names

As Microsoft prints them — the exam and the marker both expect these, letter for letter.
FunctionToolclassThe Foundry SDK class that defines a function tool: name, description, parameters schema, strict.Learn →
strictparameterFunctionTool setting that enforces stricter validation of the parameters schema.Learn →
additionalPropertiesparameterJSON schema key; set to false so the model cannot send fields you did not define.Learn →
function_call_outputparameterThe input item type your app sends back with a function’s result.Learn →
call_idparameterLinks a function_call_output to the function_call item it answers.Learn →
conversations.deletemethodDeletes a stored conversation and the items it holds.Learn →
tool_choiceparameterControls tool calling on a response: auto, required or none.Learn →
agent_referenceparameterThe extra_body entry that tells a responses call which agent to run.Learn →
conversations.items.createmethodAdds items, such as a user message, to an existing conversation.Learn →
Message itemsconceptConversation items holding user or assistant messages.Learn →
Tool call itemsconceptConversation items recording the tool invocations the agent attempted.Learn →
ConversationsconceptThe current replacement for classic threads; they hold streams of items, not only messages.Learn →
Every name in the course is on one printable page: download the AI-103 cheat sheet (PDF).
Key Terms

JSON schema

A JSON description of allowed data: its fields, their types, which are required and which values are permitted.

Function call

An output item in which the model asks your app to run a named function with given arguments.

Self-Check — Before You Submit
1. A Lagos bank’s policy says no customer prompt or answer may be stored in the service once the reply is sent. Which conversation-tracking approach fits?
  • A. A conversation object reused across turns
  • B. previous_response_id with default storage
  • C. store=False, with the app passing earlier turns back as input
  • D. A new agent version for every turn
C. store=False, with the app passing earlier turns back as input — With store set to false the service does not persist the response, so the app must carry context itself. Response chaining is tempting, but by default it relies on response history stored server-side.
2. An agent must always check the stock system before it answers a stock question. What gives the most deterministic control?
  • A. Setting tool_choice to required on those turns
  • B. Adding “please” to the instructions
  • C. Setting strict to true on the function
  • D. Setting additionalProperties to false
A. Setting tool_choice to required on those turns — Learn names tool_choice as the most deterministic control, and required forces at least one tool call. strict and additionalProperties shape the arguments of a call; they do not make the call happen.
3. Your app has just run the function the agent asked for. What does it send back?
  • A. A new user message that pastes the result
  • B. A function_call_output item with the same call_id, in the same conversation
  • C. A new agent version containing the result
  • D. A conversations.delete call
B. A function_call_output item with the same call_id, in the same conversation — The result goes back as a function_call_output whose call_id matches the function_call item. Pasting it as a user message loses that link, and the agent may treat it as the user’s own words.

Today’s Assignment

Define a prompt agent for a task from your own work, with structured instructions and one strict function tool, and run a traced multi-turn conversation with it.
  • Write the instructions in five labelled parts: role, goals, tools, limits and style. Explain in two or three sentences why each limit is there.
  • Define one function tool with FunctionTool: a clear name, a description with an example value, a parameters schema with at least two properties (one of them an enum), required, additionalProperties set to false, and strict=True. Implement the function locally with illustrative data.
  • Create the agent, then run a conversation of at least three turns in which the agent must ask for missing information before it calls the function. Print every item type, as track_conversation.py does.
  • Justify your conversation-tracking approach (conversation object, previous_response_id or store=False) against a data policy you state, and say where tool_choice would help.
  • Change the instructions once, create a second version, and describe the difference in behaviour you saw.
  • Include your full code and 300–700 words of explanation. Endpoints, keys, secrets and credentials stay in environment variables only; crop them out of screenshots. Delete the agent versions and the conversation afterwards, and say so.
Evidence to include
  • Terminal output of your conversation script, showing every item type, the function call with its arguments, and the agent’s answers.
  • Terminal output or a portal screenshot showing the agent name and both version numbers.
  • The output of your clean-up script, or a screenshot showing the agent versions gone.
Names your answer must use exactly
FunctionTool strict additionalProperties function_call_output call_id tool_choice agent_reference
Never include a key, a connection string or a token. Crop them out of every screenshot. If one is exposed, the letter will tell you to rotate it.
How this is marked — the rubric
The agent and function tool work: the schema is strict and complete, and the conversation shows a correct function_call and function_call_output hand-back35
The instructions, limits and conversation-tracking choice are well reasoned against a stated policy20
Uses the exact class, parameter and method names from this session’s names box20
Evidence: the traced output, both versions and the clean-up are shown, with no keys, endpoints or secrets visible25
Total · pass mark 70100
Submitting session 12
Write your answer in Word or Google Docs, with your screenshots pasted in. The top of the document must carry the line Session: 12 (the template has it ready, under the Course line), or the submission is refused. Upload the Word file (.docx), or switch to the Google Doc tab and paste your document’s share link.
Marked against the rubric above and returned as a written letter by email; the mark appears on your progress page. Do the self-check above before you submit.
Skills Covered
Writing agent instructionstool_choiceFunction tool JSON schemasConversation-tracking approachesTracing conversation items
Tick it once you have submitted.Next: Session 13 →
B · Implement generative AI and agentic solutions · 30–35%SESSION 13
Agents with retrieval, function calling and conversation memory
Session 13 of 40 · 45-minute session
Skills measured — Microsoft’s wording
  • Build agents that integrate retrieval, function-calling, and conversation memory

Why This Matters

Session 12 gave an agent one action. A useful agent needs three things at once: knowledge it can cite, actions it can take, and a memory of what the user has already said. That combination is what the objective “Build agents that integrate retrieval, function-calling, and conversation memory” tests, and it is the shape of most agents you will build at work. Today you build one end to end in Python: your own document behind File Search, a function tool, and a multi-turn conversation that carries context between turns. You will also see how long-term memory differs, so you can explain exactly which memory you used and why.

IN YOUR SUBSCRIPTION
Creates
One vector store holding one uploaded file, one prompt agent (hr-leave-agent) with File Search and a function tool, and one conversation, all in your project. In Basic agent setup the file and vector store use Microsoft-managed storage and search; in Standard setup they use your connected Blob Storage and Azure AI Search. The optional memory step adds a memory store and a second agent, and needs a chat model and an embedding model deployment.
Cost
Billed. Model tokens for every response. Learn says File Search has charges beyond token fees, and the Foundry Agent Service pricing page lists File Search Storage, so delete the vector store today. The optional memory store is billed through the chat and embedding models it calls, and Learn warns memory pricing can change during preview. The Azure AI Search tool, if you use an existing index, bills the search service while it exists. Check the pricing pages and Cost analysis.
Clean-up
Run cleanup.py and delete_file.sh in the wrap-up: they delete the agent version, the conversation, the vector store and the uploaded file. If you did the memory step, uncomment its lines to delete that agent and the memory store, then delete the embedding deployment. Keep the chat model deployment for Session 14.
The 45-Minute Session
7:00 – 17:00
Build the knowledge and the agent
  • Create a short file, leave_policy.md, with five or six invented rules, such as a carry-over limit, a deadline for using carried-over days and a notice period. Mark it illustrative. Never upload real personnel data for an exercise.
  • The project’s OpenAI client handles files and vector stores. Following Learn’s File search tool for Microsoft Foundry agents how-to, vector_stores.create makes the store and the upload_and_poll helper adds the file and returns only when ingestion has finished. Learn is clear that files must be fully processed before you rely on them.
  • pythonbuild_agent.pytype it yourself
    import os
    from azure.identity import DefaultAzureCredential
    from azure.ai.projects import AIProjectClient
    from azure.ai.projects.models import PromptAgentDefinition, FileSearchTool, FunctionTool
    
    project = AIProjectClient(endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], credential=DefaultAzureCredential())
    openai = project.get_openai_client()
    
    # Knowledge: a vector store holding your own (illustrative) policy file
    vector_store = openai.vector_stores.create(name="leave-policy-store")
    with open("leave_policy.md", "rb") as file_handle:
        vs_file = openai.vector_stores.files.upload_and_poll(vector_store_id=vector_store.id, file=file_handle)
    
    # Action: a function your app runs
    balance_tool = FunctionTool(
        name="get_leave_balance",
        description="Return the remaining annual leave days for a staff ID such as E1042.",
        parameters={
            "type": "object",
            "properties": {"staff_id": {"type": "string", "description": "Staff ID, for example E1042"}},
            "required": ["staff_id"],
            "additionalProperties": False,
        },
        strict=True,
    )
    
    agent = project.agents.create_version(
        agent_name="hr-leave-agent",
        definition=PromptAgentDefinition(
            model=os.environ["FOUNDRY_MODEL_NAME"],
            instructions="You answer staff questions about annual leave. Use File Search for any policy "
                         "rule and say which rule you used. Use get_leave_balance only when the user gives "
                         "a staff ID. If the policy does not cover the question, say you don't know.",
            tools=[FileSearchTool(vector_store_ids=[vector_store.id]), balance_tool],
        ),
    )
    print(f"Agent {agent.name} v{agent.version} | vector store {vector_store.id} | file {vs_file.id}")
    WHAT YOU SHOULD SEE
    Agent hr-leave-agent v1 | vector store <vector-store-id> | file <file-id>
  • Adding the file parses, chunks, embeds and stores it for keyword and semantic search; you wrote no chunking code, unlike the index in Session 7. Check Learn’s supported file types before uploading anything unusual. At the time of writing, a vector store holds up to 10,000 files.
  • THE EXAM LINE

    vector_stores.create creates the store; upload_and_poll adds a file and waits for processing; FileSearchTool(vector_store_ids=[...]) attaches it to the agent. At most one vector store per agent and one per conversation.

Write down every ID the script prints. Clean-up depends on them.
28:00 – 38:00
The Azure AI Search tool, and long-term memory
  • If the knowledge already lives in an Azure AI Search index, as in Session 7, use the Azure AI Search tool instead of File Search. In Learn’s sample, AzureAISearchTool wraps an AzureAISearchToolResource, whose AISearchIndexResource takes the project connection ID, the index name and a query type from AzureAISearchQueryType. The supported values are simple, vector, semantic, vector_simple_hybrid and vector_semantic_hybrid, which is the default.
  • You create the connection in the portal: Manage → Project details → Connected resources → Add connection → Azure AI Search. Code finds it with project.connections.get(...). For keyless access, Learn’s prerequisites name the system-assigned managed identity of the Foundry resource that contains your project; it needs Search Index Data Contributor and Search Service Contributor on the search service, and Learn says key-based authentication is not supported with private virtual networking.
  • Long-term memory is the next step up. A conversation remembers one chat; a memory store (preview) remembers a user across chats. The optional script below follows Learn’s Create and use memory how-to. It needs a chat model and an embedding model deployment (the two variable names are Learn’s), and Learn asks you to enable the project’s system-assigned managed identity and give it Foundry User on the Foundry resource.
  • pythonmemory_agent.pytype it yourself
    import os
    from azure.identity import DefaultAzureCredential
    from azure.ai.projects import AIProjectClient
    from azure.ai.projects.models import (
        MemorySearchPreviewTool,
        MemoryStoreDefaultDefinition,
        MemoryStoreDefaultOptions,
        PromptAgentDefinition,
    )
    
    project = AIProjectClient(endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], credential=DefaultAzureCredential())
    chat_model = os.environ["MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME"]
    
    store = project.beta.memory_stores.create(
        name="hr_memory_store",
        definition=MemoryStoreDefaultDefinition(
            chat_model=chat_model,
            embedding_model=os.environ["MEMORY_STORE_EMBEDDING_MODEL_DEPLOYMENT_NAME"],
            options=MemoryStoreDefaultOptions(
                chat_summary_enabled=True,
                user_profile_enabled=True,
                user_profile_details="Avoid sensitive data, such as age, financials, precise location, and credentials",
            ),
        ),
        description="Long-term memory for the HR leave agent",
    )
    
    agent = project.agents.create_version(
        agent_name="hr-memory-agent",
        definition=PromptAgentDefinition(
            model=chat_model,
            instructions="You help staff with leave questions and remember the preferences they state.",
            # "{{$userId}}" isolates memories per end user; update_delay=1 is for the demo only (default 300)
            tools=[MemorySearchPreviewTool(memory_store_name=store.name, scope="{{$userId}}", update_delay=1)],
        ),
    )
    print(f"Memory store {store.name} | agent {agent.name} v{agent.version}")
    WHAT YOU SHOULD SEE
    Memory store hr_memory_store | agent hr-memory-agent v1
  • Test it as Learn does: state a preference in one conversation, wait about a minute, then ask in a new conversation. Writes are debounced by update_delay; the demo uses 1 second, and Learn’s default is 300 seconds, which is what production should use.
  • THE EXAM LINE

    Conversation: short-term memory within one chat. Memory store (preview) with MemorySearchPreviewTool: long-term memory across chats. scope "{{$userId}}" isolates each user; update_delay debounces writes, default 300 seconds.

If you cannot explain why an agent needs to remember something next month, it does not need long-term memory.

The exact names

As Microsoft prints them — the exam and the marker both expect these, letter for letter.
FileSearchToolclassAttaches File Search to an agent, pointing it at a vector store.Learn →
vector_store_idsparameterThe FileSearchTool parameter listing the vector store the agent searches.Learn →
vector_stores.createmethodCreates a vector store through the project’s OpenAI client.Learn →
upload_and_pollmethodUploads a file into a vector store and returns once processing has finished.Learn →
vector_stores.deletemethodDeletes a vector store when you no longer need it.Learn →
AzureAISearchToolclassAttaches an existing Azure AI Search index to an agent through a project connection.Learn →
AzureAISearchQueryTypeclassChooses the query type: simple, vector, semantic or one of the two hybrids.Learn →
Search Index Data ContributorroleRole the project’s managed identity needs on the search service for keyless use of the tool.Learn →
MemorySearchPreviewToolclassAttaches a memory store to a prompt agent so it reads and writes long-term memory.Learn →
MemoryStoreDefaultDefinitionclassDefines a memory store: its chat model, embedding model and options.Learn →
update_delayparameterSeconds of inactivity before memories are written; the default is 300.Learn →
Short-term memoryconceptContext for the current session, such as a conversation’s items.Learn →
Long-term memoryconceptDistilled knowledge an agent keeps across sessions in a memory store.Learn →
Every name in the course is on one printable page: download the AI-103 cheat sheet (PDF).
Key Terms

Project connection

A named, stored link from a Foundry project to another resource, such as a search service, used instead of keys in code.

Debounce

Waiting for a quiet period before acting, so several quick changes lead to one write.

Self-Check — Before You Submit
1. A manufacturer already maintains an Azure AI Search index of 40,000 maintenance manuals and wants its agent to use semantic ranking over it. What should the agent use?
  • A. FileSearchTool with a new vector store of the manuals
  • B. AzureAISearchTool with a project connection and the vector_semantic_hybrid query type
  • C. Code Interpreter with the manuals uploaded
  • D. Web search restricted to the manuals site
B. AzureAISearchTool with a project connection and the vector_semantic_hybrid query type — The Azure AI Search tool uses the existing index through a project connection, and vector_semantic_hybrid is one of its query types. Copying 40,000 manuals into a vector store duplicates an index that already exists.
2. On Monday a user tells the agent they prefer replies in French. On Friday, in a new conversation, the agent should reply in French. What makes that possible?
  • A. Monday’s conversation object
  • B. previous_response_id from Monday
  • C. A memory store attached with MemorySearchPreviewTool and a per-user scope
  • D. A second vector store
C. A memory store attached with MemorySearchPreviewTool and a per-user scope — Only long-term memory carries a preference across separate conversations; user profile memory is designed for it. A new conversation starts without Monday’s items, so short-term memory cannot help.
3. An agent answers a leave-policy question, but the trace shows no file_search_call item. What is the best first fix?
  • A. Tighten the instructions to use File Search for policy, or send that turn with tool_choice set to required
  • B. Delete and recreate the vector store
  • C. Set strict to true on the function tool
  • D. Raise the default chunk size
A. Tighten the instructions to use File Search for policy, or send that turn with tool_choice set to required — No file_search_call means the model answered without retrieving, which is a tool-use problem, not an index problem. strict only affects function arguments, and the vector store may be perfectly fine.

Today’s Assignment

Build an agent that combines File Search (or the Azure AI Search tool) with a function tool, hold a traced multi-turn conversation with it, and explain how its memory was carried.
  • Create a small illustrative document of rules from your own field (at least five rules) and a function that returns personal or live data (illustrative values). Build the agent with both tools, adapting build_agent.py, or use the Azure AI Search tool on your Session 7 index if you still have it.
  • Run a conversation of at least four turns in which a later turn depends on an earlier one without repeating it. Print the item types for every response, as chat.py does.
  • Start a new conversation and ask a question that depends on the first one. Record what happens and explain why.
  • Explain (300–700 words): which retrieval tool you chose and why; how the function call was handed back; how conversation memory carried context; and whether this agent needs long-term memory, naming the memory types and scope you would use. If you ran memory_agent.py, show and explain its result.
  • Include your full code. Keys, endpoints, secrets and credentials stay in environment variables; crop them out of screenshots.
  • Delete the agent versions, conversations, vector store and uploaded file (and any memory store), and show that you did.
Evidence to include
  • Terminal output of the multi-turn conversation with the item-type trace, including at least one file_search_call (or Azure AI Search call) and one function_call.
  • Terminal output of the new-conversation test.
  • The output of your clean-up scripts, showing the deletions.
Names your answer must use exactly
FileSearchTool vector_store_ids upload_and_poll Short-term memory Long-term memory MemorySearchPreviewTool
Never include a key, a connection string or a token. Crop them out of every screenshot. If one is exposed, the letter will tell you to rotate it.
How this is marked — the rubric
The agent works: retrieval and the function tool are both used correctly across a multi-turn conversation35
The memory explanation is correct, including the new-conversation test and a justified view on long-term memory20
Uses the exact class, method, parameter and concept names from this session’s names box20
Evidence: the traces, the new-conversation output and the clean-up output are shown, with no keys or endpoints visible25
Total · pass mark 70100
Submitting session 13
Write your answer in Word or Google Docs, with your screenshots pasted in. The top of the document must carry the line Session: 13 (the template has it ready, under the Course line), or the submission is refused. Upload the Word file (.docx), or switch to the Google Doc tab and paste your document’s share link.
Marked against the rubric above and returned as a written letter by email; the mark appears on your progress page. Do the self-check above before you submit.
Skills Covered
File Search and vector storesFunction calling in a loopConversation memoryAzure AI Search toolLong-term memory stores
Tick it once you have submitted.Next: Session 14 →
B · Implement generative AI and agentic solutions · 30–35%SESSION 14
Agent tools: APIs, knowledge stores, search, Content Understanding, custom functions
Session 14 of 40 · 45-minute session
Skills measured — Microsoft’s wording
  • Integrate agent tools, including APIs, knowledge stores, search, content understanding, and custom functions

Why This Matters

An agent earns its keep when it reaches real systems: a partner’s API, your own search index, a document pipeline, a function in your codebase. AI-103 names all of these in one objective, and its questions are rarely about syntax. They ask which integration fits, how it authenticates, and who approves a call before it runs. Today you connect two different tool types to one agent: an OpenAPI tool built from a specification, and an MCP server that needs a person’s approval for every call. You also place knowledge stores, search and Content Understanding correctly in a design, so you can defend every tool you choose.

IN YOUR SUBSCRIPTION
Creates
Versions of one prompt agent (tools-agent) in your project, and the stored responses from your test calls. No project connection is needed: the OpenAPI sample uses anonymous authentication, and the Microsoft Learn MCP Server needs none. Nothing else is created in Azure. A Foundry IQ knowledge base is discussed but not built today.
Cost
Billed per token for each response, including the extra response after each approval. Learn states there is no charge to use the Microsoft Learn MCP Server. The weather API named in Learn’s sample spec is a public service outside Azure, so send it nothing private. If you add an Azure AI Search service for the optional reading, it is billed while it exists; check the Azure AI Search pricing page.
Clean-up
Run cleanup_tools.py in the wrap-up to delete every tools-agent version. If you created a project connection or a search service for anything optional, delete the search service from Resource groups → rg-ai103, and the connection with the Azure Resource Manager DELETE call Learn shows on its Foundry IQ page. Keep the model deployment for Session 15.
The 45-Minute Session
8:00 – 17:00
OpenAPI and MCP: the two custom tool types
  • An OpenAPI tool is a tool schema written in OpenAPI instead of inline JSON. In Python it is OpenApiTool wrapping an OpenApiFunctionDefinition (name, spec, description, auth). Learn’s first-success path uses OpenApiAnonymousAuthDetails with a public weather API, so you prove the mechanics before you handle credentials.
  • Open the spec before you use it and find the operationId. Learn requires one for every operation, using only letters, - and _, and descriptive names help the model choose the right one. Request bodies must be application/json or application/json-patch+json.
  • The MCP tool, MCPTool, has server_label (your name for the server), server_url, require_approval, optionally allowed_tools to limit which of the server’s tools the agent may use, and project_connection_id when the server needs authentication.
  • require_approval defaults to always. It also accepts never, or an object listing tools under never or always. With approval on, the response contains an mcp_approval_request item, and your app answers with an McpApprovalResponse carrying approve and the approval_request_id, chained with previous_response_id.
  • THE EXAM LINE

    MCPTool: server_label, server_url, require_approval (default always), allowed_tools, project_connection_id. An mcp_approval_request item is answered with an McpApprovalResponse (approve, approval_request_id) sent with previous_response_id.

  • Treat everything an MCP server returns as untrusted. Learn warns that tool descriptions, annotations and results can carry indirect prompt injection; that Microsoft does not test or verify third-party remote MCP servers; and that you are responsible for the data you send them. Its best practices: an allowed_tools allow-list, approval for high-risk operations, and a log of approvals and tool calls.
  • bashsetup.shtype it yourself
    # In your course virtual environment (Python 3.10+)
    pip install "azure-ai-projects>=2.4.0" azure-identity jsonref   # 2.4.0: the floor since Session 9
    
    # Learn's first-success flow: save the sample spec into an assets folder
    mkdir -p assets
    # Download weather_openapi.json from the link on Learn's OpenAPI how-to into ./assets/
    
    az login
    export FOUNDRY_PROJECT_ENDPOINT="https://<resource-name>.services.ai.azure.com/api/projects/<project-name>"
    export FOUNDRY_MODEL_NAME="<your-deployment-name>"
Read a third-party tool description the way you would read an email from a stranger.
30:00 – 38:00
Knowledge stores, search, Content Understanding and custom functions
  • Search. The Azure AI Search tool from Session 13 is the direct route to one index you own.
  • Knowledge stores. A Foundry IQ knowledge base reaches an agent through the MCP tool. Learn’s pattern is a project connection of category RemoteTool, authenticated with ProjectManagedIdentity, pointing at the knowledge base’s MCP endpoint on the search service; then an MCPTool with require_approval set to never and allowed_tools set to knowledge_base_retrieve. The project’s managed identity needs Search Index Data Reader on the search service. You build agentic retrieval in Session 27.
  • THE EXAM LINE

    A Foundry IQ knowledge base connects to an agent through MCPTool with allowed_tools set to knowledge_base_retrieve, using a RemoteTool project connection that authenticates with the project’s managed identity.

  • Content Understanding. At the time of writing, Learn’s tool catalogue does not list Content Understanding as an agent tool. It enters an agent solution at ingestion: the Azure Content Understanding skill in an Azure AI Search skillset analyses documents, chunks them (Learn says no Text Split skill is needed) and outputs tables and figures as Markdown, and the agent searches the resulting index. Learn notes that skill is billed at the Content Understanding price. If an agent must analyse one file during a conversation, wrap your analyzer call (Session 28) in a function tool or an OpenAPI tool.
  • Custom functions. Function calling, from Sessions 12 and 13. Learn’s tool catalogue also lists an Azure Functions tool, but its migration table marks Azure Functions as not available in the new service, and the tool’s own page shows support for Standard agent setup only. Check the current pages before you design with it.
When two Learn pages disagree, design with the option both pages support, and note the conflict.

The exact names

As Microsoft prints them — the exam and the marker both expect these, letter for letter.
OpenApiToolclassAdds an OpenAPI-described HTTP API to an agent as a tool.Learn →
OpenApiFunctionDefinitionclassHolds an OpenAPI tool’s name, specification, description and authentication.Learn →
OpenApiAnonymousAuthDetailsclassAuthentication setting for public APIs that need no credential.Learn →
operationIdparameterRequired name for each operation in the spec; letters, hyphens and underscores only.Learn →
MCPToolclassConnects an agent to a remote MCP server endpoint.Learn →
server_labelparameterYour identifying label for an MCP server in the tool definition.Learn →
require_approvalparameterWhether MCP tool calls need approval: always (default), never, or per tool.Learn →
mcp_approval_requestconceptThe output item type raised when an MCP call awaits approval.Learn →
McpApprovalResponseclassYour app’s answer to an approval request: approve and approval_request_id.Learn →
allowed_toolsparameterAn allow-list of the MCP server’s tools the agent may call.Learn →
knowledge_base_retrievetoolThe knowledge base MCP tool an agent is allowed to call to query Foundry IQ.Learn →
RemoteToolsettingThe project connection category used to reach a knowledge base’s MCP endpoint.Learn →
Azure Content Understanding skillfeatureAzure AI Search skill that uses Content Understanding analyzers to extract and chunk content at indexing time.Learn →
Every name in the course is on one printable page: download the AI-103 cheat sheet (PDF).
Key Terms

MCP server

A service that publishes tools through the Model Context Protocol so that agents can discover and call them.

Indirect prompt injection

Instructions hidden in content a tool returns, written to make the model do something its user did not ask for.

Self-Check — Before You Submit
1. A bank’s agent must call an internal REST API protected by Microsoft Entra ID. Security forbids API keys. How should the OpenAPI tool authenticate?
  • A. With managed identity, for a service that accepts Microsoft Entra ID tokens
  • B. With an API key written into the OpenAPI specification
  • C. Anonymously, because the API is internal
  • D. Through function calling with the key placed in the instructions
A. With managed identity, for a service that accepts Microsoft Entra ID tokens — Learn lists managed identity for Azure services and Microsoft Entra ID-protected APIs, with no key to store. A key in the specification breaks Learn’s own rule that credentials never go in the spec or source code.
2. You add an MCPTool and do not set require_approval. The agent decides to call one of the server’s tools. What happens?
  • A. The call runs immediately
  • B. The response contains an mcp_approval_request item that your app must answer
  • C. Agent creation fails because require_approval is mandatory
  • D. The call is blocked until allowed_tools is set
B. The response contains an mcp_approval_request item that your app must answer — require_approval defaults to always, so every call raises an approval request that your app answers with an McpApprovalResponse. allowed_tools is optional and only narrows which tools can be called.
3. A team wants several agents to answer from a shared Foundry IQ knowledge base. Which configuration matches Learn?
  • A. FileSearchTool with the knowledge base name as the vector store ID
  • B. AzureAISearchTool pointed at the knowledge base
  • C. OpenApiTool with anonymous authentication
  • D. MCPTool with allowed_tools set to knowledge_base_retrieve, through a RemoteTool project connection
D. MCPTool with allowed_tools set to knowledge_base_retrieve, through a RemoteTool project connection — Learn connects Foundry IQ knowledge bases through the MCP tool, allowing knowledge_base_retrieve over a RemoteTool connection that uses the project’s managed identity. The Azure AI Search tool targets one index, not a knowledge base.

Today’s Assignment

Build one agent that calls at least two different tool types, including one custom tool with an approval step, and document each call and its authentication.
  • Choose two or more tool types for a task from your work, for example an OpenAPI tool and an MCP tool as in the session, or either of those with File Search or a function tool. At least one must be an OpenAPI or MCP tool.
  • Build the agent, adapting tools_def.py and tools_agent.py. If you use a spec of your own, check every operationId against Learn’s rule. If you use an MCP server other than Microsoft Learn’s, set allowed_tools and keep approval on.
  • Run questions that trigger each tool. Approve one MCP call and decline another, and record what the agent did each time.
  • Explain (300–700 words): why each tool type fits; how each authenticates and what you would change for production; what data leaves your environment; and where a knowledge store or Content Understanding would fit in this solution.
  • Include your full code. Keys, endpoints, tokens and connection secrets never appear in code, documents or screenshots; crop them out.
  • Delete the agent versions afterwards and say so.
Evidence to include
  • Terminal output showing the item types for each tool call and the agent’s answers.
  • Terminal output showing one approved and one declined mcp_approval_request, with the arguments visible.
  • The clean-up output, or a portal screenshot showing the versions gone.
Names your answer must use exactly
OpenApiTool OpenApiAnonymousAuthDetails operationId MCPTool require_approval mcp_approval_request McpApprovalResponse
Never include a key, a connection string or a token. Crop them out of every screenshot. If one is exposed, the letter will tell you to rotate it.
How this is marked — the rubric
The agent works with at least two tool types, and the approval round trip is implemented correctly35
The explanation of fit, authentication, data flow and the place of knowledge stores or Content Understanding is correct20
Uses the exact class, parameter and item names from this session’s names box20
Evidence: tool-call traces, the approved and declined requests, and clean-up are shown, with no keys or secrets visible25
Total · pass mark 70100
Submitting session 14
Write your answer in Word or Google Docs, with your screenshots pasted in. The top of the document must carry the line Session: 14 (the template has it ready, under the Course line), or the submission is refused. Upload the Word file (.docx), or switch to the Google Doc tab and paste your document’s share link.
Marked against the rubric above and returned as a written letter by email; the mark appears on your progress page. Do the self-check above before you submit.
Skills Covered
OpenAPI toolsMCP tools and approvalsTool authenticationFoundry IQ knowledge basesContent Understanding at ingestion
Tick it once you have submitted.Next: Session 15 →
B · Implement generative AI and agentic solutions · 30–35%SESSION 15
Multi-agent orchestration, and orchestrating models, flows and rules engines
Session 15 of 40 · 45-minute session
Skills measured — Microsoft’s wording
  • Implement orchestrated multi-agent solutions
  • Orchestrate multiple models, flows, or hybrid LLM and rules engines

Why This Matters

Some jobs are too big, or too risky, for one agent with one prompt. A complaint needs drafting and reviewing; a payment decision needs rules that no model is allowed to bend. AI-103 asks you to orchestrate multiple agents and to combine models with flows and rules engines, and this is where the platform has moved fastest. Connected Agents is not in the new Agent Service, and portal workflows are being retired. Today you learn what Learn currently offers, build a two-agent sequential orchestration with Microsoft Agent Framework, and put deterministic rules before and after a model, with a trace you could show an auditor.

IN YOUR SUBSCRIPTION
Creates
Nothing new in Azure from the two scripts. The Agent Framework script runs both agents in your own code against your model deployment; Learn states this path does not create a server-managed agent resource. The rules script calls the same deployment directly. If you also try a portal workflow or an A2A connection, those create a workflow, agent versions or a project connection in your project.
Cost
Billed per token on your model deployment. The sequential orchestration makes at least one model call per agent per run. The rules script only calls the model when the pre-rules let a ticket through, which is a saving in itself. Check the Microsoft Foundry pricing page and Cost analysis.
Clean-up
Nothing to delete from the scripts. If you created a portal workflow, open it, select the Version dropdown and delete each version. This session closes Week 3, so delete the model deployment (Foundry portal → Build → Models, or az cognitiveservices account deployment delete) and check Build → Agents for versions left from Sessions 12 to 14. Keep rg-ai103 and the project.
The 45-Minute Session
9:00 – 17:00
Orchestration patterns
  • Agent Framework lists five built-in multi-agent patterns. Sequential: agents run one after another in a defined order. Concurrent: agents run in parallel. Handoff: agents transfer control to each other based on context. Group Chat: agents collaborate in a shared conversation. Magentic: a manager agent dynamically coordinates specialised agents.
  • Foundry’s portal workflows use three patterns with slightly different wording: Human in the loop (ask the user a question and wait, for example for an approval), Sequential, and Group chat (control passes between agents based on context or rules). Their nodes invoke agents, add if/else, go-to and for-each logic, set or parse variables, and send or ask messages.
  • THE EXAM LINE

    Sequential: one after another. Concurrent: in parallel. Handoff: agents transfer control by context. Group chat: a shared conversation. Magentic: a manager agent coordinates specialists. Human in the loop: pause for a person.

  • Choose by the shape of the work. A fixed pipeline (draft, check, approve) is sequential. Independent opinions you compare afterwards are concurrent. A front desk that passes the customer to the right specialist is handoff. A problem whose steps you cannot list in advance is where a manager pattern such as Magentic earns its extra model calls.
  • In Agent Framework, human-in-the-loop is not a separate pattern: Learn says its orchestrations support it through tool approval and request info. Session 16 builds on that.
If you can draw the process on a whiteboard in fixed boxes, you want a workflow, not a cleverer prompt.
28:00 – 38:00
Models plus rules: deterministic steps around the model
  • A rules engine is the part of a system that must give the same answer every time. Put rules before the model to block, redact or route what should never reach it, and after the model to validate what it returns. Learn’s tool guidance says the same: validate structured outputs against an expected schema, allow only known fields and operations, and require approval before consequential actions.
  • The script below is my own composition from calls you already know (responses.create, from Session 5). Illustrative: a Lagos bank’s complaint router.
  • pythonrules_router.pytype it yourself
    import json
    import os
    import re
    from azure.identity import DefaultAzureCredential
    from azure.ai.projects import AIProjectClient
    
    ALLOWED = {"BILLING", "CARD", "TRANSFER", "OTHER"}  # rule: the only routes the bank accepts
    ACCOUNT_NO = re.compile(r"\b\d{10}\b")             # rule: 10-digit account numbers never reach the model
    PROMPT = ('Classify this complaint. Reply with JSON only, for example '
              '{"route": "BILLING", "reason": "short reason"}. Routes: BILLING, CARD, TRANSFER, OTHER.')
    
    project = AIProjectClient(endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], credential=DefaultAzureCredential())
    openai = project.get_openai_client()
    
    def route(ticket: str) -> dict:
        trace = []
        if "fraud" in ticket.lower():                                     # rule before: hard stop
            trace.append("pre-rule: fraud keyword -> FRAUD_TEAM, model not called")
            return {"route": "FRAUD_TEAM", "trace": trace}
        clean, count = ACCOUNT_NO.subn("[ACCOUNT]", ticket)               # rule before: redact
        trace.append(f"pre-rule: redacted {count} account number(s)")
        r = openai.responses.create(model=os.environ["FOUNDRY_MODEL_NAME"], input=f"{PROMPT}\n\n{clean}")
        trace.append(f"model: {r.output_text}")
        try:                                                              # rule after: validate
            result = json.loads(r.output_text)
        except json.JSONDecodeError:
            result = {}
        if not isinstance(result, dict) or result.get("route") not in ALLOWED:
            trace.append("post-rule: output not allowed -> HUMAN_QUEUE")
            return {"route": "HUMAN_QUEUE", "trace": trace}
        trace.append("post-rule: accepted")
        return {"route": result["route"], "trace": trace}
    
    for ticket in ["I think this is fraud: a card payment I never made.",
                   "Transfer from 0123456789 failed but the money left my account."]:
        print(json.dumps(route(ticket), indent=2))
    WHAT YOU SHOULD SEE
    {
      "route": "FRAUD_TEAM",
      "trace": [
        "pre-rule: fraud keyword -> FRAUD_TEAM, model not called"
      ]
    }
    {
      "route": "TRANSFER",
      "trace": [
        "pre-rule: redacted 1 account number(s)",
        "model: {\"route\": \"TRANSFER\", \"reason\": \"<short reason>\"}",
        "post-rule: accepted"
      ]
    }
  • Read the trace. The fraud keyword never reaches the model. The account number is redacted before anything is sent. Anything the model returns outside the allowed routes, including JSON wrapped in extra text, goes to a person. The model classifies; the rules decide.
  • THE EXAM LINE

    Hybrid orchestration: deterministic rules before the model (block, redact, route) and after it (validate against an allow-list or schema, fall back to a person). A model’s free text should never trigger a consequential action unchecked.

  • At larger scale, Learn describes Azure Logic Apps as combining deterministic steps with the reasoning of Foundry agents in the same run.
If a rule matters legally, it belongs in code, not in a prompt.

The exact names

As Microsoft prints them — the exam and the marker both expect these, letter for letter.
Connected AgentstoolClassic agent-to-agent tool; not available in the new Foundry Agent Service, where Learn recommends the A2A tool.Learn →
A2APreviewToolclassAdds an Agent2Agent (A2A) endpoint, through a project connection, as a tool for an agent.Learn →
Foundry Agent ConsumerroleRole the calling identity needs, at least, on a target Foundry project for A2A calls.Learn →
Microsoft Agent FrameworktoolMicrosoft’s SDK for building agents and multi-agent workflows; Learn’s recommended path for new workflows.Learn →
Human in the loopfeatureWorkflow pattern that asks the user a question and waits for input, such as an approval.Learn →
Group chatconceptWorkflow pattern that passes control between agents based on context or rules.Learn →
Power FxfeatureThe Excel-like, low-code formula language used for expressions and conditions in Foundry workflows.Learn →
Azure Logic AppsserviceLow-code workflow service that can call Foundry agents as steps alongside deterministic actions.Learn →
agent-frameworkpackageThe Python package for Microsoft Agent Framework.Learn →
FoundryChatClientclassAgent Framework client that uses a model deployed in a Foundry project from your own code.Learn →
SequentialBuilderclassBuilds a pipeline in which agents process the task in turn.Learn →
ExecutorclassAgent Framework base class for a custom code step inside a workflow.Learn →
HandoffconceptOrchestration pattern in which agents transfer control to each other based on context.Learn →
MagenticconceptOrchestration pattern in which a manager agent dynamically coordinates specialised agents.Learn →
Every name in the course is on one printable page: download the AI-103 cheat sheet (PDF).
Key Terms

Rules engine

Deterministic logic that gives the same result for the same input every time, used to block, route or validate.

Fallback

The safe path taken when a step fails or its output is not allowed, such as a queue for a person.

Self-Check — Before You Submit
1. A team is moving a classic agent that used Connected Agents to the new Foundry Agent Service. It still needs to call another Foundry agent. What should it use?
  • A. The Connected Agents tool, unchanged
  • B. The A2A tool with an A2A project connection
  • C. File Search pointed at the other agent
  • D. Code Interpreter
B. The A2A tool with an A2A project connection — Learn’s migration table shows Connected Agents is not available in the new service and recommends the A2A tool. Keeping the classic tool is the tempting wrong answer, because the old tool simply does not exist there.
2. A loan pre-screening assistant must reject every applicant under 18, without exception. Where should that check go?
  • A. In the agent instructions, in capital letters
  • B. In a reviewer agent that reads the first agent’s output
  • C. In a lower temperature setting
  • D. In a deterministic rule before or after the model
D. In a deterministic rule before or after the model — A rule that must hold every time belongs in deterministic code around the model. Instructions and reviewer agents are both model behaviour, which is probabilistic and can fail on an unusual input.
3. Three specialist agents must each assess the same claim independently and at the same time before the results are compared. Which Agent Framework pattern fits?
  • A. Concurrent
  • B. Sequential
  • C. Handoff
  • D. Magentic
A. Concurrent — Concurrent runs agents in parallel on the same input. Sequential would pass each assessment to the next agent, so the assessments would no longer be independent.

Today’s Assignment

Build an orchestration, either two agents in sequence or a model wrapped in deterministic rules, and show its trace.
  • Pick a real process from your work that has at least two steps, or a rule that must never be broken.
  • Option A: adapt sequential.py into a two-agent (or larger) sequential orchestration with SequentialBuilder and FoundryChatClient. Option B: adapt rules_router.py with at least one rule before the model and one after it, and a fallback. Strong submissions do both.
  • Run it on at least three inputs, including one that should trigger a rule or make the second agent change something. Print the trace each time.
  • Explain (300–700 words): which pattern you chose and why the alternatives (concurrent, handoff, group chat, Magentic) fit less well; where the rules sit and why they are code rather than prompt; and how you would run this in Foundry today, given that Connected Agents is classic only and portal workflows retire on December 1, 2026 (A2A tool, Agent Framework as a hosted agent, or Azure Logic Apps).
  • Include your full code. Endpoints, keys, secrets and credentials stay in environment variables; crop them out of screenshots.
  • Delete the model deployment at the end of the week and say so.
Evidence to include
  • Terminal output of every run, showing the trace: author-by-author messages, or pre-rule, model and post-rule lines.
  • Output from at least one input where a rule fired or the second agent changed the first agent’s work.
  • A screenshot of your deployments list after clean-up, or the CLI output of the delete.
Names your answer must use exactly
SequentialBuilder FoundryChatClient Microsoft Agent Framework Connected Agents A2APreviewTool Handoff
Never include a key, a connection string or a token. Crop them out of every screenshot. If one is exposed, the letter will tell you to rotate it.
How this is marked — the rubric
The orchestration runs on three inputs, and the pattern or rules are implemented correctly with a fallback35
The explanation of pattern choice, rule placement and the current Foundry options is correct and current20
Uses the exact class, package, service and pattern names from this session’s names box20
Evidence: traces for every run, a rule or review in action, and the clean-up, with no keys or endpoints visible25
Total · pass mark 70100
Submitting session 15
Write your answer in Word or Google Docs, with your screenshots pasted in. The top of the document must carry the line Session: 15 (the template has it ready, under the Course line), or the submission is refused. Upload the Word file (.docx), or switch to the Google Doc tab and paste your document’s share link.
Marked against the rubric above and returned as a written letter by email; the mark appears on your progress page. Do the self-check above before you submit.
ASSESSMENT NOW OPEN

Pop Quiz 3 — Agents opens now. Sit it before the next session. It is how you find out what has stuck, and practice papers may be resat as often as you like.

8 questions · 12 minutes · covers Sessions 11–15 · pass mark 70
Sit Pop Quiz 3 →Closed book, no notes, and Coach Ritchie switches himself off while you sit it.
Skills Covered
Multi-agent orchestration patternsMicrosoft Agent FrameworkA2A and Connected AgentsFoundry workflows and their retirementHybrid LLM and rules
Tick it once you have submitted.Next: Session 16 →
← Back to course home