Card 08 of 38· Domain 2 · Generative AI and agents
The two chat APIs — ChatCompletions vs Responses
Models are stateless, and these are the two ways to cope. Which endpoint talks to what, the one hard rule about keys, and the bridge pattern you will write constantly.

Start from the fact that makes everything else here necessary: a language model has no memory. Each call arrives with no knowledge of the last one. Everything that feels like a conversation is a trick played on top of a stateless system, and there are two ways to play it.
Two approaches to the same problem
Chat Completions solves it by resending. Every turn, you send the entire conversation history again. The model reads the lot and answers the last message. Simple, and the payload grows steadily as the conversation goes on — which costs both tokens and latency.
The Responses API solves it by remembering server-side. You pass a previous_response_id, and the state is held for you. Your payload stays a constant size no matter how long the conversation runs.
The mechanical differences follow from that, and they get tested directly:
| Chat Completions | Responses | |
|---|---|---|
| History | Resent every turn | Held server-side |
| Payload size | Grows | Constant |
| System message | An entry in messages with role:"system" |
The instructions parameter |
| Reading the reply | completion.choices[0].message.content |
response.output_text |
Note where the system message goes. It is a message in one and a named parameter in the other, and mixing those up is an easy mark to drop.
Two endpoints, and the one hard rule
| Azure OpenAI endpoint | Foundry project endpoint | |
|---|---|---|
| Talks to | The model, directly | The platform — agents, tools, grounding |
| Package | openai |
azure-ai-projects (2.0.0+) |
| Client | AzureOpenAI |
AIProjectClient |
| Authentication | Keys or Entra ID | Entra ID only |
| OpenAI API coverage | Broadest | Shaped to the platform |
The authentication row is the one to memorise. The project endpoint never accepts an API key. If a question offers a key-based answer for the project endpoint, it is wrong regardless of how reasonable the rest of it looks.
Choose between them on what you are reaching for. Raw model access, and you want the Azure OpenAI endpoint and the broadest API surface. Agents, tools or grounding, and you want the project endpoint.
The bridge you will write constantly
There is a pattern that connects the two, and it is worth being able to write from memory:
- Create an
AIProjectClientwith the endpoint andDefaultAzureCredential(). - Call
project.get_openai_client()on it. - Call
client.responses.create(model=agent_name, ...).
You authenticate once at the platform level and get a working model client out the other side. Useful to know: openai arrives as a transitive dependency of azure-ai-projects, so you do not install it separately.
The distractors
Asked which method generates a reply with the Responses API, the plausible wrong answers are create on its own and get_response_id. The answer is responses.create.
Both distractors work by being almost right — one is the method name without its object, the other is a real-sounding function that does something else. That is the general shape of distractors on this exam: recognisable fragments assembled incorrectly. Read the whole call, not the verb.