Skip to content
XUtilHub

AI-103 courseLesson 6 of 18 · 14 min

Build Generative AI Apps With the Foundry SDK in Python (AI-103)

XUtilHub Team ·

Exam skills covered

  • Deploy and consume LLMs, small models, code models, and multimodal models
  • Integrate generative workflows into applications by using Foundry SDKs and connectors
  • Configure an application to connect to a Foundry project

This lesson starts the biggest domain on AI-103, generative AI and agentic solutions (30–35%). You'll connect a Python app to a Foundry project and call different kinds of models with the Responses API: plain chat, streaming, structured JSON and images.

Connect an app to a Foundry project

Install the SDKs:

pip install azure-ai-projects azure-identity openai

Read configuration from the environment, not from code:

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

project = AIProjectClient(
    endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],  # https://<resource>.services.ai.azure.com/api/projects/<project>
    credential=DefaultAzureCredential(),
)
openai = project.get_openai_client()
MODEL = os.environ.get("CHAT_DEPLOYMENT", "chat-main")

What's happening:

  • AIProjectClient connects to the project endpoint.
  • DefaultAzureCredential is keyless: your Azure CLI login locally, a managed identity in Azure. The identity needs the Azure AI User role on the project.
  • get_openai_client() returns an OpenAI-compatible client already pointed at the project.
  • MODEL is your deployment name, not necessarily the model's name.

The project client also gives you connections (project.connections.list()), deployments, datasets, indexes, evaluations and agents, so one client covers most of the Foundry SDK.

Call a model

response = openai.responses.create(
    model=MODEL,
    instructions="You are a concise assistant for Contoso's HR team.",
    input="Summarise our parental leave policy in three bullet points.",
    max_output_tokens=400,
)
print(response.output_text)
  • instructions is the system message.
  • input is a string, or a list of messages and content parts.
  • output_text joins the text output. response.usage reports input and output tokens for cost tracking.

Multi-turn: pass previous_response_id=response.id on the next call, or create a server-side conversation with openai.conversations.create() and pass conversation=conv.id.

Small, code and reasoning models

The same call works for any chat-capable deployment. Only model changes:

cheap = openai.responses.create(model="phi-mini", input="Classify: 'My card was charged twice' → billing/tech/sales")
code = openai.responses.create(model="codex-mini", input="Write a Python function that validates an IBAN.")
hard = openai.responses.create(
    model="reasoning-main",
    input="Plan a 3-phase migration of 40 VMs with these constraints: ...",
    reasoning={"effort": "high"},
)

Some models in the catalog aren't OpenAI models. Many of them are served through the same Foundry endpoint, so you still call them by deployment name. Reasoning models accept reasoning effort instead of (or as well as) temperature. Check each model's supported parameters.

Stream responses

Streaming sends tokens as they're generated, which cuts time to first token, the latency users actually notice:

stream = openai.responses.create(model=MODEL, input="Explain RAG to a new developer.", stream=True)
for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)

Structured outputs

When code consumes the answer, ask for JSON that matches a schema:

schema = {
    "type": "object",
    "properties": {
        "category": {"type": "string", "enum": ["billing", "technical", "sales"]},
        "urgency": {"type": "integer", "minimum": 1, "maximum": 5},
        "summary": {"type": "string"},
    },
    "required": ["category", "urgency", "summary"],
    "additionalProperties": False,
}

r = openai.responses.create(
    model=MODEL,
    input="Ticket: 'Production API is down since 9am, we're losing orders!'",
    text={"format": {"type": "json_schema", "name": "ticket", "schema": schema, "strict": True}},
)
ticket = json.loads(r.output_text)

strict: True constrains generation to the schema, which is far more reliable than "please reply in JSON".

Multimodal input

Send an image next to text using content parts:

r = openai.responses.create(
    model=MODEL,
    input=[{
        "role": "user",
        "content": [
            {"type": "input_text", "text": "What error is shown in this screenshot?"},
            {"type": "input_image", "image_url": "data:image/png;base64," + b64_png},
        ],
    }],
)

Need a quick base64 string to test with? Use our image to Base64 converter.

Integrating into applications

  • Keep the AI call behind your own API layer, so the browser never talks to the model directly
  • Add timeouts, retries and fallbacks (for example a second deployment) for 429s and outages
  • Log usage per feature and user for cost analytics
  • Connectors such as Logic Apps, Power Automate and Microsoft 365 connectors let workflows call your models and agents without custom code

Key takeaways

  • AIProjectClient(endpoint, DefaultAzureCredential()) → get_openai_client() → responses.create(model=<deployment>, ...).
  • Swap models by changing the deployment name; reasoning models use reasoning effort.
  • Stream for responsiveness; use structured outputs with a JSON schema for machine-readable answers.
  • Images go in as input_image content parts.

Next lesson: implement RAG with Azure AI Search.

Check your understanding

Exam-style questions on this lesson. Get them all right to mark the lesson complete.

Question 1

1.Which object connects Python code to a Foundry project?

Question 2

2.In responses.create(model=..., input=...), what is the value of model?

Question 3

3.You need the model to return JSON that always matches a schema. What should you use?

Question 4

4.Users complain the chat UI feels slow even though total time is fine. What helps most?

Question 5

5.How do you send an image to a multimodal model with the Responses API?

Finished reading?

← AI-103 course outline