Your First Chat Client: One Endpoint, Two Kinds of Client
Your First Chat Client: One Endpoint, Two Kinds of Client
What this slice covers
This note follows the move from the playground into code: what a Foundry project endpoint is, how the Foundry SDK is put together, why a single SDK hands you two different client objects, what the shortest working chat call looks like, and how a stateless call becomes a multi-turn conversation. Choosing between SDKs and diagnosing a failed first call are covered in a companion note.
One endpoint to configure
A Foundry resource gives you unified access to models, agents, and tools, and the Foundry SDK is a thin client that exposes all of the project APIs through a single project endpoint. That endpoint has a predictable shape built from your resource name and project name, on the services.ai.azure.com domain, with the project path appended. If your organisation uses a custom subdomain, that replaces the resource name.
The payoff is configuration simplicity. Instead of tracking one address per capability, your application carries one value. Higher-level libraries build on this rather than replacing it — the Agent Framework's Foundry package depends on the Foundry SDK to reach models, tools, and project configuration, so you are not wiring endpoints by hand when you move up a level.
Two clients, and why
The part that confuses newcomers is that one SDK exposes two client types. The reason is historical and architectural rather than arbitrary: Foundry and OpenAI have different API shapes, so the SDK does not pretend otherwise.
The project client handles Foundry-native operations that have no OpenAI equivalent — listing the project's connections, reading project properties, enabling tracing. Think of it as the client for the platform around the model.
The OpenAI-compatible client handles everything that builds on OpenAI concepts, which is most of what you will do at runtime: the Responses API, agents, evaluations, and fine-tuning all follow OpenAI-style request and response patterns. This client targets the Responses API on your project endpoint, which is served on an openai route, and through it you reach Foundry Models sold by Azure, other catalogue models, and the platform tools — file search, code interpreter, web search, memory, SharePoint, Work IQ, Fabric IQ, and MCP servers.
Most applications use both: the project client for setup and configuration, the OpenAI-compatible client for actually running things.
The shortest working call
In Python the pattern is three steps and fits in a dozen lines. Install the current package — azure-ai-projects at version 2.0.0 or later, which corresponds to the current Foundry portal experience rather than the classic 1.x line. Construct an AIProjectClient with your project endpoint and DefaultAzureCredential. Then ask that project object for an OpenAI client and call the Responses API with a model name and an input string, printing the output text.
Three details in that sketch deserve attention. First, the credential: Microsoft's samples authenticate with Microsoft Entra ID rather than API keys, and DefaultAzureCredential picks up the identity you signed in with via the Azure CLI on your machine, or a managed identity in production. Nothing secret ends up in your source file. Second, the model name is your deployment name — the same name you saw when you deployed the model — and Microsoft's samples use gpt-5-mini throughout. Third, the shape is the same in C#, TypeScript, and Java; only the ceremony differs.
Getting to this point requires an RBAC role. For day-to-day development you need at least Foundry User on the project. Note the recent rename: Foundry User, Foundry Owner, Foundry Account Owner, and Foundry Project Manager were previously called Azure AI User, Azure AI Owner, Azure AI Account Owner, and Azure AI Project Manager. Older tutorials and some portal surfaces still show the old names; the role IDs and permissions are unchanged.
From one call to a conversation
A single Responses call is stateless. It answers what you asked and remembers nothing. To hold a thread you create a conversation object and pass its identifier on each subsequent call. Ask how large France is, then follow up asking only for its capital, and the second answer is correct — because the conversation carries the history, not because the model recalls you.
This is the moment the architecture clicks for most learners. Conversation state is an explicit object you create and reference, which means it is also something you can inspect, scope, and discard. When agents enter the picture, they layer instructions and tools on top of exactly this mechanism.
Mistakes people make
Mixing SDK generations is the big one: code written for Azure AI Projects 2.x is not compatible with 1.x, and following a tutorial from the classic portal against a new project produces attribute errors that look like your mistake. Hardcoding keys instead of using a credential is the second. Passing the vendor's model name instead of your deployment name is the third. And expecting memory from a bare Responses call — rather than creating a conversation — is the fourth, and the one that most often gets misdiagnosed as the model being forgetful.