Microsoft AI-901: Prompt Design and Python Chat Client Labs
A beginner can make a model answer a question in a portal without understanding how to reproduce the result in an application. This guide creates one small prompt contract, compares a revision against evidence, and translates the request to a version-pinned Python client for the correct Microsoft Foundry endpoint. It also tests refusals, throttling and structured output. The goal is a recoverable exercise grounded in the AI-901 objectives, not a library snippet that claims to work with every SDK generation.
On this page
- Start with a narrow, testable prompt contract
- Keep trusted instructions separate from source data
- Test one meaningful prompt revision
- Select a supported Python client contract
- Authenticate without embedding secrets
- Validate the final response and its evidence
- Handle streaming, timeouts and throttling conservatively
- Turn the lab into a reproducible learning artifact
Start with a narrow, testable prompt contract
Write a short public troubleshooting note and define a task such as extracting the affected service, observed error and permitted next diagnostic step. The source note should contain one warning the answer must not omit. Record what an acceptable answer looks like before asking the model. An instruction like “give a great answer” cannot be audited; a contract naming source-grounded facts and allowable missing values can. The prompt should not authorize changes to external systems or ask the model to invent a missing status.
Add a negative note that contains no supported answer to a question. The correct response is a transparent lack-of-evidence statement, not a plausible guessed repair. Test whether a long user message or another document paragraph changes the outcome. A model that follows instructions closely may still hallucinate details when the source is insufficient; therefore the evidence and parsing checks belong outside the model’s words. Keep the initial draft response for comparison rather than replacing it without a record.
Write a fixture file containing three fields: source ID, source text and expected warning. Parse it as data instead of embedding the expected answer into the prompt. In one case, the warning is absent; a correct model should avoid inventing it. If the test harness accepts any nonempty response, it has no meaningful ability to judge correctness. Require an exact source identifier and compare the returned warning with the fixture. This simple discipline scales better than manually applauding whichever response reads most naturally.
Keep trusted instructions separate from source data
A prompt has distinct layers: stable application rules, the user’s actual task and lower-trust contextual material. A retrieved page or uploaded document can contain text such as “ignore previous instructions”; this is information to process, not authority over the application. Clearly delimit sourced passages and validate which documents the user can access before including them. Do not grant a tool permission simply because a retrieved sentence requests it.
Build two examples with the same legitimate task: one contains a neutral troubleshooting note, while the other embeds a malicious instruction in an attached paragraph. Inspect not just the final prose but whether the assistant attempted to call a tool or reveal a prohibited value. Tool-layer authorization remains mandatory even when a model refuses the instruction during a test. At AI-901 level, the learner should recognize the trust boundary and explain why an instruction-only defense is insufficient.
Test one meaningful prompt revision
Try a prompt that merely asks for a summary and one that explicitly requires facts supported by the note, a concise warning and an uncertainty field. Hold the model deployment and source constant. Evaluate the results for required facts, fabricated claims, incorrect advice, and output-format compliance. Shorter text is not automatically better if it removes a safety qualification. If both versions fail, investigate the source and task definition instead of layering repetitive instructions into the prompt.
Use a small comparison table with question ID, expected source evidence, version A result, version B result and reviewer rationale. The evaluator should be able to see which statement the note actually supports. If the model returns a convincing explanation without the crucial warning, label it as an omission; if it cites the wrong document, label source selection separately. This is a more useful learning result than choosing the prompt whose prose sounds more confident.
Select a supported Python client contract
Follow the SDK version and endpoint type documented by Microsoft for your specific Foundry project or compatible inference resource. Some examples use a project client while others use an OpenAI-compatible inference client; methods and response shapes can differ. Pin package versions in a dependency file and record the resource endpoint, deployment name and API version where applicable. Avoid copying constructor parameters across different generations of examples. The deployment identifier routes your call; it is not always interchangeable with the model family label.
For a basic request, use a previously verified model deployment and a non-sensitive test message. The Python function should create or reuse a client following documented lifecycle rules, obtain an authorized credential, send a bounded request, and return a typed success or error state. Treat returned content as untrusted structured data until validated. If a response object contains a refusal or no usable message, display that state rather than indexing a nonexistent text field.
A frequent migration mistake is copying a project-client example into an application that actually uses an OpenAI-compatible inference endpoint. The import may succeed while method names, authentication or returned fields remain incompatible. Save the installed package versions and print only safe, non-secret configuration identifiers at startup. Build one fake-client test that returns a refusal object and another that returns no text. The application should turn both into truthful typed states rather than raising an unexpected index error or claiming an empty answer is a successful completion.
Authenticate without embedding secrets
Use an approved Microsoft Entra identity where supported, with a credential chain appropriate to local development and a managed identity for supported hosted workloads. Give the caller only the roles required to invoke its deployment and any separately authorized data source. Keep the authenticated principal, token audience and resource scope in your setup notes. A credential that works in a portal session is not proof that a deployed workload has equivalent permissions.
Run a smoke test with an authorized principal and an intentionally denied principal. The application should distinguish invalid credentials, missing roles and network reachability. Never solve the exercise by exposing the API key in logs, embedding it in a notebook or assigning broad subscription owner permissions. Save sanitized error identifiers and correlation IDs, but not raw tokens or private prompts. This is a basic security practice with direct exam relevance and enduring value beyond it.
Validate the final response and its evidence
Test whether the returned content contains the expected fields, acceptable values and source references. For structured outputs, use supported response-format controls when the deployment provides them and validate again in Python. An apparently valid JSON object might still invent an incident ID or omit a warning. Convert the response into a stable application schema with explicit success, partial, refused and failed states rather than assuming every request produces exactly one text string.
If a user asks for a numeric result, verify that the output uses consistent units and comes from the supplied evidence. Do not allow the model to approve a payment, ticket closure or external message through its generated prose. For an information-only lab, write the validated result to a small local test file and include the model and prompt revision. Repeat the same fixture after any SDK or deployment change so a seemingly harmless package upgrade cannot silently alter response interpretation.
For a structured case, require issue_type to be one of three approved strings, observed_system to come from the source paragraph, and next_action to be either a documented safe step or unknown. Test an extra field named administrator_override; the parser must not treat it as a privilege even if the model invents it. Also include a malformed date. The application can reject the record, ask for clarification or display a review warning, but it should not silently coerce unsupported values into an apparently complete business record.
Handle streaming, timeouts and throttling conservatively
Streaming can deliver provisional fragments that improve perceived responsiveness, but a partial message is not a confirmed action or complete structured record. Buffer and validate terminal output before handing it to a downstream system. Document what happens if the connection drops midstream, if the user cancels or if the server returns a recoverable rate-limit response. An inference call and a state-changing tool may have completely different retry safety.
Choose a finite deadline and bounded backoff for transient errors; do not retry a permission denial or schema error indefinitely. Correlate attempts with a stable request identifier where supported and record cost and latency for completed, rejected and failed cases separately. Testing a 429 response with a mock is useful when a free training environment cannot reliably reproduce a quota event. State clearly when a result came from a mock rather than an actual Foundry endpoint.
Simulate a stream interrupted immediately after the model begins a JSON object. A UI may show partial words for convenience, but the application must not write the malformed object as a finished result. Next simulate a transient timeout after a read-only query and a timeout after a hypothetical outbound action. The latter cannot safely be replayed without checking authoritative state. Mark which test uses a mock service and which reached the actual model deployment. This is a better lesson than claiming every retry automatically improves reliability.
Turn the lab into a reproducible learning artifact
Your deliverable is a small manifest, minimal version-pinned script, two public test inputs, expected output contracts and sanitized execution results. The run instructions should name the endpoint class, deployment configuration, principal permissions and how to install the pinned dependencies. A colleague using another authorized tenant should be able to identify which configuration needs changing rather than editing prompt text to fix authentication.
Finally compare the client result to the original portal output. Explain variations in formatting or behavior without pretending that two stochastic requests must be byte-identical. Revisit Microsoft’s AI-901 implementation objectives and mark exactly which steps the lab demonstrates. Passing this exercise means you can choose, invoke and evaluate a simple deployed model and diagnose safe failures—not that you built a production retrieval or agent platform.