EXAMTOPICS / TECHNOLOGY INSIGHTS

Microsoft AI-901: Build a Lightweight Chat App with the Foundry SDK

A minimal Foundry chat client should identify the approved deployment, obtain credentials through a trusted mechanism, send an allowed prompt, inspect the returned response and handle an operational error without inventing a message. Model deployment and prompt testing come before creating a client; successful authentication alone does not prove that every model is available or that protected data can be accessed lawfully. Test a valid response, a missing deployment and an unavailable endpoint as separate cases. In third-party AI-901 practice questions about SDK integration, distinguish project authentication, direct model invocation and application authorization: a generated chat response is not evidence that a booking or other business action occurred. The version-specific Python example below is a local illustration, not a claim of actual Microsoft tenant execution.

Consider a small fictional visitor-information application. A person asks for general museum information, while the application has a short public FAQ and a model deployed in Microsoft Foundry. The app should provide a concise helpful response or say when the answer is unknown. It should never invent ticket purchases or reveal private customer data. We can use this example to decide what belongs in SDK code and what belongs in instructions or source material.

Distinguish the project endpoint from a model deployment

Microsoft Foundry uses projects and available models. A client needs an endpoint associated with the correct resource/project and an authorized identity. A model’s friendly catalog name is not necessarily the deployment name configured for the project. Verify the endpoint and model deployment in the portal rather than guessing them from another tutorial. Regional availability, quotas and supported inference APIs vary by model.

The current Microsoft Foundry SDK getting-started documentation and the Foundry project quickstarts are the authoritative references for client setup. Microsoft has changed the Azure AI Projects SDK significantly: 2.x Foundry Projects (new) examples are not interchangeable with classic 1.x code. An old code sample may import familiar class names yet use incompatible method signatures or endpoint paths. Pin and verify the version you actually install.

If the documentation describes an instant-access model, check whether that option is preview and available in your project. For an exam fundamentals exercise, using a normal supported deployment with known configuration reduces ambiguity. Record the deployment and model version used when you run tests.

Authenticate without putting credentials in the prompt

Application authentication is separate from natural-language instructions. A Python client can use Microsoft Entra credentials, for example the Azure identity library’s DefaultAzureCredential, when the project and RBAC permissions are configured accordingly. Local development might use a valid Azure CLI sign-in, while a hosted application should use a suitable managed identity where supported. Never paste an Azure token, subscription key or service principal secret into the chat messages sent to a model.

Use environment variables or a secure configuration mechanism for endpoint and nonsecret settings. Keep authority at the service boundary: the person who can call the app may not automatically have the right to see all external information the app could retrieve. When a request involves patron records or purchases, the backend must check identity and permissions before attempting the operation. A strong system prompt is not an authorization control.

A beginner can practice error reporting with a deliberately unprivileged identity. The expected behavior is a clear configuration or permission error, not trying another identity or revealing raw credentials to the user. Treat unauthorized access and a temporary service failure as different cases.

Map request and response through a small client

For a bounded Python example, initialize a Foundry Projects 2.x client, obtain the OpenAI-compatible model client, call the Responses API for a known deployment and check that response text is present. The current Microsoft quickstart uses AIProjectClient, get_openai_client() and responses.create(); classic Projects 1.x samples are not interchangeable. The example assumes an authorized project endpoint and deployment set as environment variables. It illustrates a direct model call, not an agent invocation or verified museum reservation.

Example, Foundry Projects 2.x (source-aligned; Microsoft execution not tested): Configure FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL_DEPLOYMENT for your own authorized deployment, install the documented 2.x SDK and sign in with an allowed identity. The public FAQ and question are fictional. This code checks for nonempty model text; it does not validate the truth of the answer or authorize a transaction.

import os
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient

project = AIProjectClient(
    endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
    credential=DefaultAzureCredential(),
)
client = project.get_openai_client()
response = client.responses.create(
    model=os.environ["FOUNDRY_MODEL_DEPLOYMENT"],
    input=(
        "Fictional public museum FAQ: weekdays 10:00-17:00; "
        "holiday opening hours are not provided. "
        "Question: Is the museum open on holidays? "
        "Answer only from the supplied FAQ; say when it is unknown."
    ),
)
answer = (response.output_text or "").strip()
if not answer:
    raise RuntimeError("No usable model text; do not claim an answer.")
print(answer)

A deliberately small request includes a stable instruction such as “Use only the supplied public museum facts; say when information is missing” and a user question. After invocation, inspect the output rather than simply printing whichever property looks plausible. Check for a successful terminal response, the intended output text, refusal or other finish state where exposed, and the absence of unsupported actions. If the task expects one of three labels, validate the label against a defined list.

Keep the distinction between model response and application behavior. The model might draft, “Your booking is confirmed,” but unless the application has made a successful authorized booking API call, the UI cannot claim that anything was booked. Do not promote generated sentences into state changes. A database write, email or purchase confirmation should have a verified result from the owning system.

Preserve conversation context deliberately

A multi-turn chat often needs the earlier question to answer a follow-up. For example, after asking about weekend opening hours, a user asks “And on holidays?” The app must either retain relevant previous turns or use a documented conversation mechanism. Some Foundry agent APIs provide server-side conversation objects; a direct model call may require the caller to assemble the needed context. The exact API’s behavior should determine the implementation, not an assumption that all models silently remember earlier messages.

Conversation state is application data and may contain private information. Define what is retained, how long and for whose use. Do not indefinitely append a full transcript if only a small context summary is needed. Long context can increase cost and risk of irrelevant prior statements affecting new answers. Preserve clear boundaries between older user text, authoritative public facts and current developer instructions.

When a user starts a new conversation, the app should not accidentally carry another user’s state. Test with two independent sessions and check whether a follow-up belongs to the correct thread. This can be done using fictional inputs without exposing any actual visitor information.

Build graceful error and uncertainty paths

Several failures are normal enough to design for at the beginning: the endpoint is wrong, the identity lacks permission, the deployment is unavailable, a request exceeds limits, a content policy blocks output or the network connection ends unexpectedly. Classify the error, log a minimal correlation identifier and show the user a truthful message. A temporary issue may justify bounded retry; a malformed request or permission denial needs a correction rather than repeated calls.

A generative model can also return a syntactically valid answer without enough evidence. For the museum FAQ, a weekday schedule might be supplied while the holiday schedule is absent. The correct response is that holiday hours are unknown from the supplied data and should be checked with the venue. Do not reward the model for inventing a plausible time.

Input and output validation are inexpensive habits with large benefits. Reject empty or excessively long user questions according to a documented app limit. Test that a response is nonempty where expected and that a chosen category is recognized. If you later add tools, validate every tool argument and backend permission separately.

Verify the user experience, not only the model call

Run several synthetic test interactions. One ordinary question should be answered from the supplied FAQ. One ambiguous question should request clarification. One request for private data should be denied. One request about missing information should openly express uncertainty. One follow-up should be associated with its own session. Finally, force an unavailable endpoint or invalid credentials and verify that the app handles the failure without leaking secrets.

Record model deployment, client library version, request class, latency, observed result and pass/fail against a simple rubric. Avoid saving full sensitive chat logs merely to debug a connection. A user may need access to a correction or human-support path if an answer affects a meaningful decision.

A model invocation is only one component of a chat feature. Even a simple interface also needs input controls, an authorized service identity, a conversation boundary, a way to handle uncertain results and a clear indication that an answer came from AI.

Know how an agent client differs

Microsoft Foundry Agent Service can package instructions, a model and tools into a named prompt agent. When an application calls that agent, the SDK may bind a client to the agent name and conversation. That is distinct from invoking a direct model deployment with independent request instructions. The prompt-agent quickstart demonstrates the difference for the current SDK, including create-version and conversation methods.

A beginner should avoid turning a simple FAQ chat into a network of autonomous agents. Start with a bounded model request. Add an agent when packaging behavior and conversation improves the task, and introduce tools only when the app needs capabilities outside generation. Whether the model is direct or agent-backed, the owning application remains responsible for authentication, permissions, output checks and any real transaction.

Finish with a reproducible build checklist

An AI-901-ready chat exercise can be explained in seven steps: choose the task; secure an appropriate project and deployment; authenticate; submit the user input with stable instructions; inspect the result; validate it against business requirements; test failures and conversation boundaries. The actual code is only the implementation of that decision path.

Microsoft’s AI-901 study guide expects a lightweight chat client. Focus on understanding what each piece does rather than on memorizing a long SDK listing that can change across package versions. If you can describe how an authorized request becomes a checked response—and where a real application could fail—you have learned the important transferable skill.