Taswar Bhatti
The synonyms of software simplicity
Agent Security Journey

Last Saturday, 17 October 2026, I gave a talk at the DevNot Developer Summit in Istanbul called “From Prompt Injection to Permission Boundaries: Security for AI Agents.” This post is the written version, with a few extra notes I didn’t have time to say on stage.

Why agent security is different now

A chatbot that gives a bad answer is embarrassing. An agent that takes a bad action is an incident.

Agents don’t just generate text anymore. They call tools, hit APIs, write to databases, send emails and open pull requests. That changes the threat model completely. With tools attached, a prompt injection is no longer a text exploit; it can become an unauthorized state change in your systems.

The framing I want you to keep for the rest of this post is simple:

LLMs are untrusted planners. The model proposes actions; deterministic policy decides whether they run. Prompt defense alone is not enough.

Everything below follows from that one idea.

Prompt injection: the gateway attack

Prompt injection is the attack vector everyone talks about, and for good reason. It comes in four main flavours:

  • Direct jailbreaks: the user types input designed to override the system prompt.
  • Indirect injection: hidden instructions sit inside emails, web pages or documents the agent reads.
  • Retrieval (RAG) poisoning: an attacker plants content in your knowledge base so it gets retrieved later.
  • Multi-turn manipulation: gradual steering across a conversation that slowly erodes guardrails.

The key point: prompt injection is the vector, but the permissions and data access you give the agent decide the impact.

How indirect injection works

The dangerous part is that the attack doesn’t have to come through the chat box. It rides in on data the agent reads:

How prompt injection works: attacker, untrusted content, agent reads it, model follows it, tool call runs
  1. Attacker plants hidden text in content: a web page, an email, a PDF.
  2. Agent reads it. The untrusted text enters the model’s context.
  3. Model follows it. The hidden text is treated as a goal, sometimes as if it were the primary system directive.
  4. Tool call runs. For example, send_email with your data attached.

There are two places to break this chain: scan inputs for injection before they reach the model, and run a policy check before any action executes. You want both.

Tools worth evaluating for input scanning: Lakera Guard, Azure Prompt Shields, AWS Bedrock Guardrails, NVIDIA NeMo Guardrails and Guardrails AI.

Tool abuse: where the real damage happens

Agents gain their power through tools, and that is exactly why tool abuse is the bigger threat. Common failures look like this:

  • Over-broad APIs (one tool that can do far more than the task needs)
  • Chained actions that add up to something nobody intended
  • Unintended deletes or sends

A compromised LLM means compromised tools. Misleading tool outputs and sensitive context leaking into the model add risk on top.

The tool abuse lifecycle

Here is the scenario I walked through on stage:

How tool abuse happens: a hidden instruction leads to delete_records(scope="all") and the customers table drops from 4,812 rows to 0
  1. Goal. The agent reads untrusted input. A hidden instruction in a GitHub ticket or document gets interpreted as a legitimate task.
  2. Action. The model plans around that goal and generates a high-risk MCP tool call: delete_records(scope=”all”).
  3. Impact. The tool runs with the agent’s full permissions. Without boundaries, DELETE * FROM CUSTOMERS simply succeeds.
  4. Database. Rows go from 4,812 to 0. And then someone says the worst sentence in operations: “We don’t have any backups.”

The fixes map directly onto the steps: allowlist tools and validate their arguments, require human approval for high-risk actions, and make sure recovery doesn’t depend on luck. Limit what each tool can do, and check every call before it runs.

Policy engines and controls to look at: Cedar, OPA (Rego), OpenFGA, and MCP gateways with tool allowlists.

Permission boundaries: guardrails, not trust

If you take one thing from this post, take this: enforce security policy outside the model. Never rely on the prompt for safety.

  • Define what each agent may read, write and execute. Deny by default.
  • Give tools scoped permissions, not god-mode API keys.
  • Give agents role-based access.
  • Require human approval for high-risk actions.
  • Validate every tool call.

Why outside the prompt? Because policy that lives outside the prompt doesn’t move when the model or the instructions change. Swap the model, rewrite the system prompt, get injected: what the agent is allowed to do stays the same.

An access map for a coding agent

Here’s what default-deny looks like for an agent doing agentic development:

ResourceAccess
Feature branch✓ Read and write
Unit test runner✓ Run
Docs and issue tracker✓ Read
Production database✗ Denied
Customer data (PII)✗ Denied
Payment API✗ Denied

Grant only what the task needs. Everything else stays closed.

Data boundaries matter too

Permissions on tools are half the story. The other half is what data flows in and out.

Enforcement (before the model sees anything):

  • Apply user, tenant and document-level permissions before retrieval, not after.
  • Minimize how much sensitive data enters the model context. Less in context means a smaller blast radius if things go wrong.

Inspection (on the way out):

  • Treat model-generated SQL, HTML and shell commands as untrusted input, exactly like user input.
  • Inspect tool responses and outbound content, and redact where appropriate.
  • Check both the destination and the data being sent.

My favourite line from this part of the talk: permission to send email is not permission to send every document.

Agents need their own identities

Too many agents today run on a shared service account or, worse, a developer’s personal token. That makes every action untraceable.

  • Give each agent its own unique, non-shared identity.
  • Scope, rotate and audit tokens per agent and per task.
  • Every action should trace back to an accountable identity.

Dynamic keys in practice

Here’s the pattern: an identity store (a vault or identity provider) issues a short-lived key to the agent for one task.

How an agent uses an identity key: the identity store issues agent-42 a scoped 15-minute key for Ticket API and docs search, Billing API stays out of scope
  • Agent: Support Agent, agent-42
  • Key: scoped to the task, expires in 15 minutes (TTL: 15 MIN | SCOPE: TICKET_API_READ)
  • Allowed: Ticket API (read), docs search (read)
  • Not in scope: Billing API
  • Audit log: every use is recorded

No static credentials in agent code. Short-lived keys, scoped to the task. If the agent is compromised, the attacker gets 15 minutes of read access to tickets, not your billing system.

Tools to evaluate: Astrix, Oasis Security, Entro, Linx Security, Microsoft Entra Agent ID and Microsoft Agent 365.

Zero Trust for agents

Zero Trust isn’t new, but it fits agents perfectly. Never trust by network location or by prior approval alone.

  • Verify every tool call, data source and agent-to-agent request at the point of execution.
  • Minimize privilege for every task, and assume the agent’s context is already compromised.
  • Check at runtime: validate every request against identity, policy and context gates.

On the Zero Trust slide I added a line for the Istanbul audience: “Türk insanının güven sorunu değil, tecrübe fazlalığı var.” Roughly: Turkish people don’t have a trust problem, they have too much experience. That’s the right attitude for agents too.

Runtime gates: check every call

Here’s what that looks like when an agent tries to send an email to an external address:

Runtime gates: identity, context and policy pass, the arguments check fails because the destination is not on the allowlist, so the call is denied and logged to SIEM

Three gates pass, but the destination isn’t on the allowlist, so the call is denied and the failure is logged to your SIEM. Past approval does not carry forward: every request is verified again at runtime.

Agent gateways: one choke point

If every team bolts its own checks onto every agent, you end up with inconsistent, half-enforced policy. An agent gateway centralizes it: a single choke point for tool access, policy and logging.

A gateway handles authentication, rate limits, allowlists and human approval for risky actions. Its core jobs are policy enforcement, observability, audit trails, safe orchestration and boundaries. The payoff is that every agent is governed the same way.

A gateway in action

Support agent agent-42 asks the gateway to send_file to an external address. The gateway checks identity, evaluates policy, applies guardrails, writes an audit log and emits observability data. Then it routes the request one of three ways:

Agent gateway in action: external email blocked, internal file store allowed, high-risk action escalated to a human reviewer
DestinationDecisionWhy
Email API (external)BlockedDomain not on the allowlist
Internal file storeAllowedInternal recipient
Human reviewerApproval neededHigh-risk action escalated

Every call is checked, logged and tied to an agent identity before it runs.

Options to look at: MCP gateways (Gravitee, TrueFoundry, Bifrost), Amazon Bedrock AgentCore Gateway with Policy, LangGraph human-in-the-loop and OpenAI Agents SDK guardrails.

Contain, detect, recover

Assume a boundary will be challenged, and plan how you’ll contain the consequences before it happens.

  • Detect: alert on unusual destinations, odd access patterns and repeated denied calls. A string of denials is often the first sign of an injection in progress.
  • Limit: enforce caps on actions, spending, execution time and sub-agents.
  • Stop: keep an operator-controlled kill switch that revokes credentials and halts active, queued and delegated work.
  • Preserve evidence: keep tamper-resistant logs, with secrets and sensitive data redacted.
  • Own it: assign an incident owner and actually rehearse recovery. Remember the customer table with no backups.

Test the boundary, not just the answer

Most teams test whether the model says the right thing. That’s not enough. A refusal in the chat is not proof that no unauthorized action occurred.

  • Test direct prompts and malicious content hidden in documents and tool responses.
  • Assert that unauthorized tool calls and cross-user data access are actually blocked at the gateway.
  • Test the failure modes: expired credentials, gateway bypass attempts, and an unavailable policy service. Does it fail closed?
  • Repeat the tests after every model, prompt, tool or permission change.
  • Measure both sides: blocked attacks and legitimate task completion. A policy that blocks everything is secure and useless.

The tool landscape: commercial and open source

Here’s the map I shared at the end of the talk, grouped by the layer each tool protects:

LayerCommercialOpen source
Prompt protectionLakera Guard, Microsoft Prompt Shields, AWS Bedrock GuardrailsNVIDIA NeMo Guardrails, Guardrails AI
Data protectionMicrosoft Purview, Google Cloud DLPMicrosoft Presidio
IdentityAstrix, Oasis Security, Entro, Linx Security, Microsoft Entra Agent IDSPIFFE / SPIRE, OpenFGA
Agent gateway and policyMicrosoft Agent 365, AWS Bedrock AgentCore Gateway, Gravitee, TrueFoundryBifrost, Open Policy Agent (OPA), Cedar

My advice is to mix both: open source for control you can inspect, commercial for support and scale.

Key takeaways

Prompt injection is only the beginning.

  • Tool abuse is the real threat.
  • Permission boundaries are mandatory.
  • Agents must be governed as identities.
  • Zero Trust applies to every tool call.
  • Agent gateways are the future of AI security.

I closed the talk with one slide: a giant “LGTM” Don’t LGTM your agents. Put the boundaries in place, then verify every action.

Thanks to everyone who came to the session at DevNot, and to the organizers for having me.

Connect

UsingGrok4.7withCSharp

xAI just announced that Grok 4.7 so I wanted to try their model with C#. This isn’t another incremental update—it’s a model specifically architected for advanced reasoning, long-horizon problem solving, software engineering, and agentic workflows. For .NET developers building enterprise applications with AI capabilities, here’s what actually matters and how to put it to work.

What Grok 4.7 Actually Is

Grok 4.7 is xAI’s latest model release, built from the ground up for scenarios where you need an AI that can think through multi-step problems, use tools effectively, and maintain context across extended tasks. The key differentiators:

  • Deep reasoning capabilities. Trained extensively on complex problem-solving tasks requiring planning, analysis, and synthesis—not just pattern matching or next-token prediction.
  • Up to 500K tokens of context, according to the current Grok deployment guide. Input and output share that budget; actual use still depends on deployment limits and cost.
  • Software engineering focus. Benchmarked at 71.0% on DeepSWEv1.1—a rigorous evaluation across 113 original, long-horizon software engineering tasks spanning 91 active repositories and five languages. That’s not a toy benchmark; it’s real engineering work.
  • Enterprise-grade deployment. Available through Global Standard and US Data Zone Standard in Foundry, with familiar Chat Completions and Responses APIs, tool calling support, streaming, Microsoft Entra ID authentication, and API keys.

The model was also evaluated on CADGenBench (generating executable CAD geometry from design requirements), reflecting xAI’s broader engineering focus beyond just code generation. But for .NET developers, the software engineering and knowledge work capabilities are what matter most right now.

Set up a .NET console app

Deploy grok-4.7 in a supported Microsoft Foundry region. Copy the resource endpoint (https://<resource>.services.ai.azure.com) and the deployment name (which may differ from grok-4.7) from the Foundry portal. You need permission to deploy the model and a role that allows calling the deployed endpoint. The examples below use the official OpenAI .NET SDK pointed at the documented /openai/v1 Foundry endpoint, authenticating with Microsoft Entra ID so no API keys live in source.

With the .NET 10 SDK installed, create a project, add the SDK packages, and store the endpoint and deployment name in user secrets:

Authentication goes through Microsoft Entra ID via DefaultAzureCredential, so there are no keys to store or leak. For local development, sign in once with az login (Visual Studio and VS Code sign-ins also work); when the app runs in Azure, the same credential resolves managed identity automatically. Your identity needs a role that grants inference access—for example, Cognitive Services User—on the Foundry resource, and the Entra token scope for this API is https://ai.azure.com/.default. User secrets here hold only non-secret configuration (endpoint and deployment name) and remain a local-development convenience, not a production config store. See the Grok authentication guide for more detail.

Create FoundryChat.cs next to Program.cs. This shared factory builds a configured ChatClient the whole program reuses:

The OPENAI001 pragma is required because the OpenAI SDK marks its custom-authenticationPolicy constructor as an evaluation API—it is the supported way to attach an Entra bearer token to a non-OpenAI endpoint. Setting Endpoint to …/openai/v1 lets the SDK append chat/completions itself; this v1 surface needs no api-version query parameter.

The five examples below form a single Program.cs, not five standalone files. Replace the generated Program.cs with the shared setup block that follows, then append each use-case function (Use Cases 1–5) to the same file; keep FoundryChat.cs unchanged. The program picks a case from the command line—dotnet run — 2 runs Use Case 2 and dotnet run — all runs them in sequence, defaulting to Use Case 1 when you pass no argument.

Run from the Grok-4.7-Demo-Csharp directory with dotnet run — <case>. These examples send paid requests to your deployed model. If you see 401/403, check your Entra sign-in (az login) and role assignment; for 404, verify the resource endpoint and deployment name (not the model catalog ID); for 429, reduce traffic or retry with backoff. Each use-case block below is a function appended to this same file; the two helpers at the end of Use Case 5 go last.

Use Case 1: Drafting a technical specification

Use a constrained prompt and review the resulting document with your team rather than treating generated architecture as an approved design.

Output Case 1

Use Case 2: Two-stage refactoring review

The first completion analyzes code; the second uses that analysis to propose changes. The embedded code is deliberately input data, not a compilable payment implementation.

I have omitted the output of case 2 since it was pretty long, so you should try it yourself. This is a planning aid, not an automatic repository refactor. A human must inspect proposed patches and run tests.

Use Case 3: Structured tool calling (local research notes)

The SDK surfaces tool requests as completion.ToolCalls with a ToolCalls finish reason; never parse assistant prose for a string like tool_use. This small example looks up local, hard-coded notes, not live web search. Replace the allowlisted lookup with a real, trusted data source before claiming current research results. Keep the tool result tied to its tool_call_id and bound the number of rounds.

Output Case 3

Remember to treat tool arguments as untrusted input. Do not let a model execute arbitrary shell commands or read arbitrary paths; apply authorization, timeouts and size limits in a real agent.

Use Case 4: Bounded codebase impact assessment

A large context window is a ceiling, not a reason to upload every file. This example uses the local console project’s Program.cs so it runs without a separate repository; point it at your own reviewed files when using it for a real change.

Output Case 4

For an actual repository-wide assessment, explicitly select relevant files, exclude credentials and generated artifacts, and stay within your deployment’s token and rate limits. The Grok guide documents a 500,000-token context window; both input and output consume it.

Use Case 5: A bounded generate → compile → fix loop

This is the honest version of “agentic self-correction.” The model generates code, your harness compiles it and feeds any errors back, and the loop repeats until the build is clean or a round limit is hit. The compiler is the verifier—Grok 4.7 does the reasoning and the patching, but the loop, the build step, and the stopping rule are code you own, not something the model does on its own. The generated code is compiled, never executed, in a throwaway class library.

Output – Case 5

Building untrusted source is not a full sandbox—MSBuild can run build logic such as source generators and build targets—so run this in a disposable or sandboxed environment, cap the rounds (as above), and add a per-call timeout for anything beyond a demo. The loop stops on the first clean build; a human still reviews and tests the result before it goes anywhere near production.

That is the last block. Your single Program.cs now holds the setup-and-dispatch code, all five use-case functions, and the two local helpers—run any case with dotnet run — <case>, or dotnet run — all for the full sequence.

Practical considerations

Use larger reasoning models where they add value; check current pricing before sending large repositories or repeated multi-step calls. Model outputs are suggestions, not verified specifications, current documentation, or executable patches. Review security and architecture decisions and test generated code before production use. Foundry supports both Global Standard and US Data Zone Standard deployments; verify current region availability and data-residency requirements for your organization.

The bottom line

Grok 4.7 on Microsoft Foundry can assist with technical writing, architecture reviews, tool-assisted workflows and change-impact analysis. The workable .NET pattern is simple: deploy the model, point the OpenAI SDK at the Foundry resource’s /openai/v1 endpoint with your deployment name, authenticate with Microsoft Entra ID, and verify every output against your own codebase and requirements.

Resources

Building AI features in C#? I write about practical, no-hype prompt engineering and Azure AI patterns for .NET developers. Check out Prompt Engineering for .NET Developers — free, no Python required. You can also subscribe for more posts.

ClaudeHaiku5.5forCSharpDevelopers

There are a lot of AI model announcements these days, but every now and then one lands that feels immediately practical. Claude Haiku 5.5 is one of those releases.

Anthropic’s marketing says it’s their "cheapest, fastest, and most capable small model ever." New model, now with extra adjectives. But the numbers behind the press release are actually interesting: 75% cheaper than Haiku 4.5, sub-second response times for most requests, and speed benchmarks showing over 30% latency reduction in customer eval suites.

The more important part is that this isn’t just incremental improvements on an already-fast model — it’s designed to make high-volume work actually economically viable at scale. The kind of thing where you might have used a rule-based system or a legacy small model before, but now you can use a flagship-level reasoner without the bill spiraling.

Enough marketing though. Let’s actually call Haiku 5.5 from a .NET console app and see what it looks like in practice for real C# workloads.

What Actually Shipped

A few facts worth knowing before you touch any code:

  • 75% cheaper than Haiku 4.5 on average. For prompts under 100k tokens (90% of use cases), input costs are $0.10/M and output is $0.50/M — a 90% price cut that directly enables workloads where you previously couldn’t afford to run Claude at all.
  • Sub-second responses for most requests. Asana reports over 30% reduction in latency for task completions and up to 2.5x faster inference per agent turn compared to their current model — noticeable when users are waiting in real time.
  • Effort controls now, first time on Haiku. You can tune cost against intelligence with the effort parameter (low → max) instead of swapping models for different tasks. This matters for workflows where you want granular control over cost per request without model routing logic.
  • 1M token context window. Process entire technical manuals or large document batches in a single prompt — useful when your automation needs to reason across big datasets without chunking.
  • Sharper coding and tool use than Haiku 4.5. Anthropic’s benchmarks show Haiku 5.5 scoring equivalent to Claude 3 Opus (their previous flagship) across general knowledge, expert reasoning, and coding tasks — while running at the speed of a lightweight model.
  • Available on Microsoft Foundry. Ships as a serverless deployment — claude-haiku-5-5 inside your own Foundry resource, billed through Azure, with Entra ID authentication for enterprise identity management.

Why This Matters for .NET Developers Specifically

The use cases Anthropic and their customers are calling out map directly onto real .NET workloads where speed and cost matter:

  • High-volume customer support bots. Processing millions of requests per week without the bill spiraling — Box reports handling 8M calls/week on similar use cases, with Haiku 5.5 scoring higher accuracy at half the latency of previous models.
  • Real-time in-app assistants. Chat interfaces where users expect sub-second responses — the kind of thing where a slow model feels broken even if it’s more accurate.
  • Subagent orchestration in multi-agent systems. Pairing Haiku 5.5 with Opus 5.5 or Sonnet 5.5, letting the bigger model plan complex work while Haiku handles repetitive subtasks like summarization, classification, routing, and database queries — making it practical to run many agents in parallel.
  • Browser and desktop automation. Form filling, data entry, moving information between applications — tasks that benefit from speed and cost efficiency at scale rather than maximum reasoning depth.
  • Focused coding work. Direct edits, small specific changes across many files, applying consistent refactors — the kind of bounded task where you don’t need Opus-level intelligence but do need reliability.

One thing worth knowing up front: Claude doesn’t use Azure.AI.OpenAI or Microsoft.Extensions.AI‘s OpenAI connector. It has its own official SDK — Anthropic, plus a Foundry-specific Anthropic.Foundry package for Azure-native authentication. As always: no Python, no notebooks — just C# and dotnet run.

Getting Started

Claude ships its own official .NET SDK, and Foundry gets its own package on top of it — this is not the Azure.AI.OpenAI pattern you might already have wired up for GPT models in Foundry.

Deploy Claude Haiku 5.5 from the Foundry Model Catalog to your Foundry resource — same process as any other model. You only need your resource name, not an API key, since we’re authenticating with Entra ID.

No API keys here. Anthropic.Foundry supports both API key auth and Microsoft Entra ID token auth. This post uses Entra ID exclusively via DefaultAzureCredential — no key to generate, store, or rotate. Make sure your identity (user, managed identity, or service principal) has the Cognitive Services User or Foundry User role on the resource.

One Program.cs, Six Use Cases

The program runs case 1 by default. Pass 1–6 to select a case, or all to run them sequentially. For example, dotnet run — 2 runs the effort comparison, and dotnet run — all runs the full demo. Live calls incur charges — use caching if you’re just experimenting.

Here’s the shared client setup and entry point:

Use your actual deployment name if it differs from claude-haiku-5-5; set AZURE_AI_FOUNDRY_DEPLOYMENT through user secrets or an environment variable. DefaultAzureCredential also needs a supported signed-in developer credential locally, or a correctly configured managed identity when hosted. Compiling does not verify deployment availability, permissions, or model features.

Now append each use-case block below to that same file. Function-local parameters and message variables can safely reuse their names.


Use Case 1: A Basic Call — The Same Messages API Shape

Whether you’re classifying support tickets, summarizing logs, or answering quick questions about your codebase, the Messages API shape stays the same. Haiku 5.5 just handles high-volume work more efficiently than its predecessor:

Output – Case 1

Dev takeaway: switching between direct Anthropic API and Foundry is basically a client constructor change — your request/response code stays identical, which matters if you want to keep a provider-agnostic AI layer in your enterprise architecture.


Use Case 2: Effort Controls — Tune Cost vs Intelligence Per Request

Haiku 5.5 is the first Haiku model with effort controls. You can now adjust reasoning depth per request without swapping models. The default is medium — Anthropic reports it matches previous flagship quality at fewer output tokens for most tasks.

Output – Case 2

Use case: a customer-support triage service that runs at low effort for routine categorization (fastest, cheapest), and escalates to high only when the first pass flags ambiguity or high-value accounts — real cost control without model routing logic.


Use Case 3: Refusal Handling — Required Pattern for Production

Handle the API’s refusal stop reason explicitly rather than assuming every successful HTTP response contains an answer. The shared PrintResponse function already does this, but here’s how you might branch on refusals in real logic:

Output – Case 3

Dev takeaway: refusals can come back as normal HTTP 200 responses, not exceptions. Always check StopReason before processing output. Authentication failures, throttling, and transport errors are separate failures handled at the entry point. In enterprise systems, refusals often need human review — don’t silently retry or route around them without logging.


Use Case 4: High-Volume Bulk Classification — Where Haiku Shines

This is where Haiku’s speed and cost efficiency actually matter. Processing thousands of items in a loop — the kind of thing you’d run as a background job processing incoming support tickets, user-generated content, or log entries:

Output – Case 4

Use case: a nightly job that classifies 10,000 incoming support tickets. At $0.10/M input and ~200 tokens per ticket (prompt + response), you’re looking at roughly $0.50–$1 for the entire batch — economically viable to run daily at scale.


Use Case 5: Subagent Pattern — Pairing Haiku with Opus

The multi-agent orchestration pattern where a larger model plans complex work and delegates subtasks to Haiku. This is what companies like Asana are using in production for their AI Teammates product:

Output – Case 5

Use case: a complex data analysis pipeline where Opus plans the overall strategy (costly but needed for quality), while Haiku executes bounded subtasks like extracting specific metrics, summarizing sections, or flagging anomalies — making it practical to run many parallel agents without cost exploding. Devin AI reports this pattern holds top-tier coding scores while cutting cost and latency significantly.


Use Case 6: Context Compression — Processing Large Documents

Haiku’s 1M token context window lets you process entire documents or codebases in a single pass. Here’s how to handle large files without chunking logic:

Output – Case 6

Use case: processing technical documentation, legal contracts, or large codebases where you need the model to understand context across the entire document — no chunking logic, no manual summarization pipeline, just load and process. The 1M token window means you can include entire books, multi-year log files, or full repository snapshots in a single request.


Haiku 5.5 vs Opus 5.5: When to Use Which?

This is the question that actually matters for architecture decisions. Here’s the practical breakdown:

Use Haiku 5.5 when:

  • You need sub-second response times for real-time user experiences (chat, live support)
  • Processing high-volume tasks where cost per request directly impacts economics (10k+ requests/day)
  • Running many parallel agents in a multi-agent system — the cost savings compound at scale
  • Tasks are well-defined and bounded: classification, summarization, extraction, routing
  • You want to enable automation that wasn’t economically viable before

Use Opus 5.5 when:

  • Complex reasoning across ambiguous or novel domains (strategic planning, creative work)
  • Multi-step professional tasks requiring deep domain expertise (legal analysis, complex code refactoring)
  • Accuracy is more important than speed or cost (high-stakes decisions, compliance review)
  • Visual reasoning on dense charts, diagrams, or screenshots where precision matters most

The smart move: use both

Pair them in a multi-agent system. Let Opus plan and reason through complex problems, while Haiku handles execution of bounded subtasks — classification, summarization, data extraction, database queries. This is what companies like Asana and HubSpot are doing in production for their AI agent products.

Cost Comparison: The Numbers That Matter

Here’s the actual pricing that drives architecture decisions (per million tokens):

Model Input (≤100k) Output (≤100k) Cache Reads
Haiku 5.5 $0.10 $0.50 $0.01
Sonnet 5.5 $2.00 $10.00 $0.10
Opus 5.5 $4.00 $20.00 $0.20

At scale, these differences compound dramatically:

  • Processing 1M support tickets at ~300 tokens each: Haiku costs ~$65 vs. Opus at ~$7,800
  • Running a customer-facing chat bot with 10k daily conversations: Haiku keeps it economically viable while maintaining quality
  • Multi-agent systems making hundreds of API calls per workflow: Haiku as subagent makes the math work

Performance Benchmarks Worth Knowing

Anthropic’s benchmarks show where Haiku actually performs well versus where you need larger models:

Knowledge work (GDPval-AA v2.1): Haiku 5.5 scores 1620 vs. Opus at ~1900 — strong enough for most enterprise tasks
Computer use (OSWorld 2.1): Haiku achieves 72.4% accuracy on form-filling and data-entry tasks
Coding (FrontierCode 1.1): Haiku scores 46.4%, making it viable for bounded coding work but not complex refactoring

Customer evals are even more telling: HubSpot’s CRM audit task showed Haiku completing the fastest with highest hit rate and lowest false positive rate across all models tested. Box reported 11 points higher accuracy than Haiku 4.5 at about half the latency for document analysis tasks.

Final Thoughts

Claude Haiku 5.5 showing up in Microsoft Foundry feels like one of those releases that actually enables new workloads rather than just incremental improvements. The combination of sub-second speed, 75% cost reduction, and effort controls makes it practical to build high-volume automation at scale — the kind of thing where you might have used rule-based systems or couldn’t afford to run AI before.

The multi-agent pattern is particularly interesting for enterprise .NET teams. Pairing Haiku with Opus in orchestrated workflows lets you get flagship-level planning and reasoning while keeping execution costs manageable. Companies like Asana report over 30% latency reduction and 2.5x faster inference using this approach in production AI agent products.

If your team already lives in Azure, already experiments with AI agents or high-volume automation… this is definitely one worth trying. The economics have shifted enough that workloads which didn’t make sense before might now be viable.

Try it out and let me know what you build — I’m always interested to hear real-world use cases beyond the marketing benchmarks. 🙂

Resources

Microsoft-Decision-1-Csharp-Developer

Most of the calls inside a production .NET agent are not “write me a paragraph.” They are small, repeated judgments: which team owns this ticket, is this reply promising a refund, how severe is this incident, should the agent continue or hand off.

Those steps still get sent to a frontier chat model because that is the client everyone already wired up. It works. It is also slow, expensive, and a little awkward — you ask for JSON, then you parse prose that almost looks like JSON, then you invent a confidence score the model never actually returned.

Microsoft-Decision-1, now in public preview in the Foundry model catalog, is built for the other job. It does not draft an answer. It scores a fixed set of options and hands your code a typed decision plus probabilities.

This post is the C# version of that idea. The official quickstart is Python. The API is just HTTP, so a console app and HttpClient are enough.

Sources for the numbers below: the Foundry announcement (October 9, 2026), the Command Line deep dive, and the Foundry how-to.


What a decision model actually returns

A generative model produces text. Microsoft-Decision-1 produces a judgment about text or JSON you already have.

You send:

  • a state — the thing being judged (a string, or a JSON object)
  • one or more questions, each with a type and a closed set of options

You get back an answers object keyed by your question names. No rationale. No tool calls. No “here is my reasoning.” Your application is supposed to act on the numbers: route, gate, rank, or escalate.

Microsoft describes four places this shows up inside an app:

  • Classification — intents, themes, document types
  • Routing — which model, tool, team, or workflow
  • Evaluation — does this draft meet the rubric
  • Workflow control — continue, retry, stop, or send for review

The current model is post-trained from Qwen3.5-9B for single-pass decision scoring. Microsoft says later versions will be rebased on MAI and OpenAI models. Treat the weights as a preview, not a frozen contract.


Three question types, not a prompt template

The request is not a chat completion. It goes to the Microsoft provider route on your Foundry resource:

POST {resource-endpoint}/providers/microsoft/v1/systemone

The model field is your deployment name, not the catalog name. The response model field can still say microsoft-decision-1. That mismatch is expected.

Question JSON type What you get
Is this true? noul A probability from 0 to 1
Which option is it? choice One selected label, plus a probability for every label
How much? score A value on an ordered scale, plus a probability per level

criteria is a dictionary for choice and noul (optional on noul). For score it is an array ordered from lowest to highest. The score is a probability-weighted average of the level indexes, so a four-level scale (0 through 3) can land between levels. Use it for ordering and thresholds, not as a calibrated star rating.

Questions that share the same state can ride in one request. That is the pattern worth copying: route the ticket, score severity, and check “is this a repeat?” without three round trips.


The numbers worth arguing about

Microsoft published these from internal evals. They are not your workload. They are the reason to run your own labeled set before you swap a GPT deployment out.

Claim Source figure
Latency vs GPT-6 Sol About 35× faster (P50); also described as 35× quicker in the 36-benchmark timing run
Latency vs H2O-Lightning-4B v1.1 2.5× quicker than the runner-up
Held-out quality Highest accuracy in a 36-benchmark comparison, nearly 150,000 questions kept blind from training
Robustness Decision flips on 1.3% of perturbations on average; 0 flips when option text is paraphrased or options are reversed or shuffled
Safety screen 5,250 requests across 11 benchmarks (harmful content, jailbreaks, prompt injection)
Xbox Research labeling 10,000+ feedback items. Command Line: competitive with GPT-6 Sol, 14× faster, 200× cheaper. The Foundry blog states a different comparison: competitive with GPT-5, 80–100× faster. Do not collapse those into one number.
Copilot response grading Competitive with GPT-5.6 Luna, about 100× faster
Microsoft Discovery replanning 46× more consistent than the LLM score, 3× the scoring speed, nearly 4× end-to-end replanning speed
Price $0.042 / 1M input tokens. Output tokens are not billed. US and EU Datazone are both listed at that input rate.

Deployment types in docs are DataZoneStandard (inference stays in the data zone, where available) and GlobalStandard. Preview capacity and region list will move — check the catalog page before you promise a latency SLO.

Also available through OpenRouter. This post stays on the Foundry resource endpoint and Entra ID.


Where it fits in a .NET app

Use it when the next step is a closed choice:

  • Route a support ticket before a human or a bigger model ever sees it
  • Pick which tool or model an agent should call
  • Grade a draft against a rubric and accept, revise, or escalate
  • Gate a tool call (“does this touch production data?”)
  • Label feedback, scan code against a checklist, rank search hits

Do not use it when the product needs the words. Summaries, rewrites, explanations, and open-ended plans still belong on a generative model. The useful architecture is both: Decision-1 decides, the chat model writes.

Two constraints from the docs that should be in the design review, not the footnote:

  • It does not explain itself. If a regulator or a user asks “why,” you need a different model or a human.
  • Do not let it be the only decision-maker for credit, employment, housing, healthcare, or legal outcomes. Microsoft’s own guidance is decision support plus review. It can also reflect bias from the base model, and calibration is strongest on task types it has seen.

Low top-probability is your abstain signal. Add an explicit cannot tell option when a forced label would be worse than a queue.


Calling it from C#

There is no dedicated .NET SDK method in the quickstart. Azure.Identity plus HttpClient matches the documented contract: bearer token for https://cognitiveservices.azure.com/.default, JSON in, JSON out.

Deploy Microsoft-Decision-1 from the catalog first (GlobalStandard, or DataZoneStandard when you care which data zone runs the inference). The secret value must be the deployment name shown on the deployment page.

Output


What I would measure before production

The three-row sample in Microsoft’s quickstart is a smoke test, not an eval. Before this sits on a hot path:

  1. Build a labeled set from your own tickets, including the ambiguous ones.
  2. Report accuracy and the cases where the top probability was high and the label was wrong. Calibration matters more than the leaderboard once you threshold at 0.8.
  3. Time it from the same region as the app. Client plus network time is what users feel. Sequential calls do not tell you p99 under load.
  4. Shuffle option order on a copy of the set. Microsoft reports zero flips on shuffle for their suite; confirm that on yours.
  5. Put the abstain path in the same PR as the happy path. A classifier with no “not sure” bucket will invent confidence.

Cost is the easy part of the spreadsheet. At $0.042 per million input tokens and no output charge, the bill is dominated by how much state you stuff into every call. Keep the state to the fields the question needs. Do not paste the whole thread if the question is “which team.”


A practical split

If you already have a Foundry chat deployment for drafts and summaries, leave it there. Put Microsoft-Decision-1 in front of it for the closed questions: route, severity, policy gate, “is this draft good enough to send.”

That is the design the model is actually for. Not a smarter chatbot. A fast, cheap, typed branch in the application you already shipped.

Wrapping up

Most of what a .NET app does in a loop is not writing. It is choosing: which team, which tool, continue or stop, accept or revise. Microsoft-Decision-1 is built for those choices, and it returns numbers your code can act on.

I would not replace a chat model with it. I would put it in front of one. Run it on a labeled sample from your own workload first, look at the confident mistakes, and only then wire the threshold into production.

Resources

Building AI features in C#? I write about practical, no-hype prompt engineering and Azure AI patterns for .NET developers. Check out Prompt Engineering for .NET Developers — free, no Python required. You can also subscribe for more posts.

GPT-6.1-Sol-CSharp-Developers

When I wrote about GPT-6 Astra, the interesting question was: Can an agent take a messy problem, investigate it, and hand back something worth reviewing? The examples were deliberately substantial: bug investigations, BI recommendations, template-based reports, approval-gated record updates, and long-document synthesis.

Now there is a different question: Can you afford to do that every time the work shows up? Microsoft’s GPT-6.1 Sol announcement says GPT-6.1 Sol is generally available in Microsoft Foundry. It upgrades GPT-6 Sol, not Astra, and improves agentic coding, computer use, and professional work. Microsoft says it approaches Astra on its cited evaluations while offering a better capability-to-cost balance for agents that run all day. That is a positioning and evaluation claim, not a promise that Sol wins every task or that any particular deployment will be cheaper.

For a .NET team, I would not start with another one-off chatbot. I would start with the work that repeats: each PR, each support request, and each weekly review. No Python required; the patterns below use C# and Microsoft.Extensions.AI, and every sample prints the token usage you need to measure cost.

What changed since Astra?

A quick note on naming, because there are three models in play. GPT-6 Astra is the flagship I covered last time. GPT-6 Sol is the earlier Sol model. GPT-6.1 Sol is the upgrade to GPT-6 Sol. In the table, the Astra column summarizes how I used Astra; the GPT-6.1 Sol column describes what Microsoft says improved compared with GPT-6 Sol, not compared with Astra.

Question GPT-6 Astra GPT-6.1 Sol (changes vs. GPT-6 Sol)
Best starting point The most demanding reasoning and high-stakes reviews A candidate default for recurring production agents and complex workflows
Agentic coding Investigate bugs and propose changes for review Improved planning, editing, testing, and iteration across multi-tool workflows
Computer use Navigate approved interfaces with oversight Improved reliability across multi-step interface workflows
Professional work Synthesize, analyze, and produce review-ready work Stronger recurring analysis, drafting, and factual accuracy
Context and modalities Large text/image inputs Text and image inputs, text output, up to a 1M-token total context window; not a claim of more context than Astra

The comparison matters: 6.1 Sol is an upgrade to Sol; Astra remains Microsoft’s starting point for the hardest reasoning. Microsoft’s model reference lists a 1,050,000-token context window for both Astra and 6.1 Sol (maximum input 922,000; maximum output 128,000). A million tokens is capacity, not a suggestion to ship your whole repository on every request. Long prompts have real latency and cost consequences. Check the current catalog for your region and deployment options before building around any limit.

Foundry’s announcement lists Standard deployments across Global and US, EU, and APAC Data Zones; at launch it lists Provisioned Throughput in Global and US Data Zone. Serving location, capacity, and pricing are separate design choices. Check current availability and the Azure OpenAI pricing page for your own deployment rather than treating a launch-day price table as a quote.

Already running GPT-6 Sol?

In code, moving to 6.1 Sol is a configuration change: create a new deployment and point your deployment name at it. With Microsoft.Extensions.AI nothing else in your C# changes. Treat it as a model change anyway. Run your existing prompts and evaluation set against both deployments side by side, compare outcomes and token usage, and only then switch traffic. A model that reasons differently can spend a different number of tokens on the same prompt.

The .NET setup

Deploy gpt-6.1-sol from the Foundry model catalog and note two values from the deployment’s details page:

  • Endpoint: the resource endpoint, https://your-resource.services.ai.azure.com, not a Foundry project endpoint ending in /api/projects/….
  • Deployment name: the name you gave the deployment, which may differ from the model name.

Then give your identity access. The sample uses Microsoft Entra ID through DefaultAzureCredential, not API keys:

  1. Assign the Cognitive Services OpenAI User role on the resource to whoever runs the code: your own account for local development, a managed identity in production.
  2. Locally, sign in with az login (or Visual Studio / VS Code Azure sign-in). DefaultAzureCredential picks that up.
  3. Role assignments can take a few minutes to apply. A 401 or 403 right after assigning the role usually means “wait”, not “wrong code”.

Create the project. I compiled every sample in this post against the package versions below on .NET 10; pinning them keeps the code from drifting as Microsoft.Extensions.AI evolves. Any .NET 8+ SDK works.

The endpoint and deployment name live in .NET user secrets, which are stored in your user profile outside the project folder, so they never end up in source control.

A few choices in that setup are deliberate:

  • Timeouts and retries. Reasoning models can take a while on hard prompts, so the network timeout is raised and every call gets a cancellation token with an overall budget. The Azure client already retries transient failures (such as 429 and 503) with backoff, so you don’t need to wrap calls in your own retry loop. Do count those retries when you measure cost and latency.
  • UseFunctionInvocation() lets the model call the C# tools you register. It’s harmless for samples without tools, which simply never trigger it.
  • UseOpenTelemetry() emits a trace span per model call, including token counts, following the OpenTelemetry GenAI conventions. Nothing is exported until you add the OpenTelemetry SDK and an exporter (Azure Monitor, OTLP, or console); then the same data lands next to Foundry’s tracing.
  • Report prints input, cached-input, output, and reasoning tokens plus wall-clock time for each call. Those are the numbers you’ll need for the cost comparison later in the post.

The snippets below are alternatives to append after that setup, not three workloads to fire at once. Tool bodies and inputs are illustrative, not a live GitHub, browser, or CRM integration. Tool calling through UseFunctionInvocation() can invoke your C# methods: give those methods narrowly scoped permissions and validate inputs server-side. For a new deployment, also verify the supported API surface in the model documentation.

Use case 1: PR triage on every pull request

The Astra bug demo asked the model to correlate logs with a commit. Sol’s production pitch is to run a similar loop on every PR: inspect CI, flag likely breakages, propose a focused test, and let a human decide whether to merge. The interesting part is not generating a paragraph of review comments; it is knowing when evidence is insufficient.

The program reads CI output from a file when you pass one, and falls back to a sample otherwise:

Output – Case 1

Illustrative result: “Observed: the expired single-promo test failed; 203 others passed. Hypothesis: the resolver now accepts an expired code in one path. Next: reproduce that test locally and inspect expiry validation in the changed method. Do not merge until the failure is resolved.” No invented diff, no claim to have run tests.

Wiring it into CI

To run it on every pull request, put the program in its own project (say tools/PrTriage) and call it from your pipeline. Here is a minimal GitHub Actions workflow. It runs the tests, asks the model for triage only when they fail (that’s where it helps, and it keeps cost down), and writes the result to the job summary:

The triage step writes the endpoint and deployment name from repository variables into the runner’s user secrets, so the same Program.cs runs unchanged locally and in CI. azure/login with OIDC means no API key is stored in GitHub; the workflow’s federated identity needs the same Cognitive Services OpenAI User role as before. Notice what the model can’t do: it gets read-only test output, it writes only to the job summary, and merge rights stay with your branch protection rules. Treat PR content as untrusted input (a test name or log line can contain prompt-injection text), which is one more reason to keep the model’s output advisory. Passing the last 200 lines of output instead of the whole log keeps input tokens predictable.

Use case 2: Back-office changes with a real approval boundary

Astra illustrated “look up a record, then propose an update.” Sol makes the pattern worth testing for frequent billing-email changes or account reconciliation. This is function calling, not a demonstration of computer-use/browser automation. If you do add browser-based computer use later, isolate the browser, scope credentials, and require human confirmation before sensitive writes.

This time the model doesn’t return prose. GetResponseAsync<T> asks for structured output matching a C# record, so your code receives a typed proposal it can route into an approval queue:

The record must come after all top-level statements, so keep it at the bottom of Program.cs.

Illustrative result: ACC-4471 billingEmail: billing-old@northwind-retail.com -> finance@northwind-retail.com (pending approval). This is the real approval boundary: the model has only a read-only tool, and its output is data, a ProposedChange your service validates (is it a well-formed email? does the account exist?) and puts in front of an authenticated human. TryGetResult returning false is a normal outcome you should handle, not an exception. Read-only tools and authenticated human-operated write paths are a stronger boundary than asking a model to be careful.

Output – Case 2

Use case 3: Weekly document review without fake citations

Astra’s report and filing examples showed what long context can do. For recurring professional work, try Sol on a smaller, source-labeled set of documents: a vendor SLA and an internal incident note. Ask for an evidence table rather than a sweeping “everything looks fine.”

Output – Case 3

Illustrative result: “The SLA requires a claim within 30 days [SLA §4]. An availability incident is recorded on September 16 [Incident INC-204]. Unknown: whether a claim was submitted; the incident note does not say [Incident INC-204]. Follow up with the contract owner before the relevant deadline.” Before sending such a summary to anyone, verify each cited claim against the source and confirm the deadline calculation and time zone with the contract owner. Large-context access does not guarantee grounded answers.

For a weekly job, the cached count in the report is worth watching. If the system prompt and long reference documents stay identical between runs and come first in the prompt, repeated input can be served from the prompt cache, which is typically billed at a lower rate.

Choosing Astra, Sol, or Luna with evidence

Microsoft positions three models for different jobs: Astra for the hardest reasoning, GPT-6.1 Sol for production agents and complex recurring workflows, and Luna for high-volume preparatory and data tasks: think classification, extraction, and cleanup that feed a larger workflow. Treat that as a shortlist, not a routing rule baked into your product.

I would put a representative set of your own PRs, support requests, and document reviews through all three and record: correct outcomes, unsupported claims, tool calls, retries, human escalations, end-to-end latency, and total cost per successfully completed task. Include failed and repeated attempts in the cost.

Reasoning effort is the other dial. Microsoft.Extensions.AI exposes it as a provider-neutral option, so comparing settings is a loop:

Output – Reasoning effort

Check which effort levels your deployment accepts before relying on one; an unsupported value can be rejected by the service. Watch the reasoning count in the output: the reasoning documentation notes that reasoning tokens are billed as output tokens, so a short answer can still be expensive. If High doesn’t produce measurably better triage on your PRs, you’re paying for tokens nobody reads.

This post uses the Chat Completions API because that’s what GetChatClient targets. Azure OpenAI also offers the Responses API, which is built for multi-turn agent work with server-side conversation state. Microsoft.Extensions.AI can sit on top of either, so your IChatClient code stays the same, but options and behavior don’t always map one-to-one between them. Pick one for your evaluation and keep it fixed while comparing models.

Keep approval checkpoints, least-privilege tool identities, audit logs, and prompt-injection defenses in place regardless of which model wins. Foundry offers evaluation, tracing, monitoring, and safety controls, but they do not remove the need to test your tools and enforce authorization in C#.

Beyond a console app

The console app keeps the samples short. In ASP.NET Core, register the same pipeline once with dependency injection and inject IChatClient wherever you need it. Run dotnet user-secrets init and the same two set commands in the web project; ASP.NET Core loads user secrets automatically in the Development environment:

For anything a person watches in real time, such as a support agent waiting on a draft, stream the response instead of waiting for the whole thing:

Background jobs like PR triage and the weekly review don’t need streaming; the non-streaming call is simpler and gives you the usage numbers in one place.

Wrapping up

Astra was my “can this do the difficult work?” model. GPT-6.1 Sol is the model I would test first for work that happens constantly: PR triage, back-office review, and routine document analysis. Its announcement is about capability per task at production frequency, not about a bigger context window or magic autonomy. Keep the human approval button, log the token counts, measure your actual outcomes, and then choose the deployment that earns its place in your .NET stack.

Resources

Building AI features in C#? I write about practical, no-hype prompt engineering and Azure AI patterns for .NET developers. Check out Prompt Engineering for .NET Developers — free, no Python required. You can also subscribe for more posts.

ClaudeOpus5.5WithVSCode

In my Claude Opus 5.5 for C# developers post I called Opus 5.5 from my own code: the Anthropic.Foundry SDK, Entra ID, and the effort parameter. This time the code calling Opus 5.5 isn’t mine. It’s Claude Code, running in my terminal and in VS Code, pointed at my Foundry resource.

Microsoft already has a good step-by-step setup guide for Claude Code on Microsoft Foundry in VS Code, so I’m not going to repeat it. If you’ve never connected Claude Code to Microsoft Foundry, start there. This post is about what happens after it connects, when the model on the other end is Opus 5.5: how to make sure you’re actually talking to it, which dial to turn, and where the tokens go when you’re not looking.

Why Opus 5.5 Changes the Claude Code Setup

A quick recap of what shipped, and what each change means inside Claude Code:

  • It’s 40% cheaper than Opus 5. $4/M input, $20/M output, and $0.20/M cache reads. Claude Code sessions are mostly re-read context, so the cache price matters more than the headline price.
  • Medium effort is the default. Claude Code respects that: Opus 5.5 starts at medium, while most other models start at high. You can raise it per session.
  • Thinking is always on. There’s no thinking toggle to hunt for. Effort is the only dial, and MAX_THINKING_TOKENS does nothing on Opus 5.5.
  • Output is 30%+ faster. You’ll feel this in the VS Code panel on long diffs.
  • More refusals. The expanded safety classifiers apply in Claude Code too. If your repo is security tooling, expect some declines.

The catch: none of this matters if Claude Code isn’t using Opus 5.5. And by default, on Foundry, it isn’t.

The Short Setup (and the Line Most Guides Miss)

Install Claud Code Cli

Install Claud Code Cli

Deploy Claude Opus 5.5 from the Foundry Model Catalog to your Foundry resource, same as any other model. Give yourself the Azure AI User or Cognitive Services User role on that resource (either one is enough to call the model), and run az login. No API key: Claude Code falls back to the Azure credential chain when no key is set, so your az login session is the credential. If you plan to use the API Key then you will need to set your env key or the json file to have the ANTHROPIC_FOUNDRY_API_KEY rather.

Remember to install the Extension in VSCode

VSCode Claude

VSCode Claude

Now the part I care about. Instead of setx-ing environment variables or pasting them into every shell, put them in ~/.claude/settings.json. Both the CLI and the VS Code extension read that file, so you configure Foundry once:

The two model lines do different jobs, and you want both:

  • ANTHROPIC_MODEL makes Opus 5.5 the model for the session. This is the line most guides miss. On Foundry, Claude Code’s default model is Sonnet 4.5, not Opus. Setting only ANTHROPIC_DEFAULT_OPUS_MODEL remaps the opus alias, but you keep chatting with Sonnet until you switch.
  • ANTHROPIC_DEFAULT_OPUS_MODEL makes the opus alias (in /model, subagent definitions, and so on) resolve to your Opus 5.5 deployment instead of an older Opus you may not have deployed.

Use your actual deployment name if it isn’t claude-opus-5-5. ANTHROPIC_FOUNDRY_RESOURCE takes the resource name only, not a URL. If you need a private endpoint or custom domain, use ANTHROPIC_FOUNDRY_BASE_URL instead. Don’t set both.

In VS Code, install the Claude Code extension and add one line to your VS Code settings.json so it doesn’t push you toward an Anthropic login:

Then check it, in the terminal or the VS Code panel: /status

You’re looking for the API provider set to Microsoft Foundry, your resource name, and your Opus 5.5 deployment as the model. If the model line says Sonnet, the ANTHROPIC_MODEL line isn’t being picked up.

Dev takeaway: “Deployed in Foundry” and “used by Claude Code” are two different things. /status is the five-second check that tells you which one you’ve got.


Effort: The Dial You’ll Actually Touch

In the SDK post, effort was a property on the request. In Claude Code it’s a session setting, and there are three ways to set it:

  • /effort sets it for the current session: /effort high, /effort low, or /effort auto to go back to the model default.
  • The /model picker has an effort slider (left/right arrows). Whatever you pick there is remembered per model, so Opus 5.5 can keep its own setting.
  • CLAUDE_CODE_EFFORT_LEVEL in the environment or the env block wins over everything else, including /effort.

That last point is easy to trip over: put CLAUDE_CODE_EFFORT_LEVEL in your settings while testing, forget about it, and later /effort high appears to do nothing. For interactive work, leave the env var out and use /effort or the /model slider. Save the env var for scripted or CI runs where you want one fixed level. (The top-level effortLevel user setting also won’t apply to Opus 5.5, which is one more reason to use the per-model slider.)

Here’s how I map the levels to Claude Code work:

Effort What I use it for in Claude Code
low “Explain this file”, rename a symbol, write a commit message
medium (default) Everyday feature work, bug fixes, writing tests
high / xhigh Multi-file refactors, framework migrations, tricky concurrency bugs
max Rarely, and only for the session: /effort max when xhigh clearly isn’t getting there

Thinking tokens are billed as output, at $20/M. Raising effort for the whole day costs you; raising it for one hard problem and dropping back is cheap.


Where the Opus Bill Hides

Pinning everything to Opus 5.5 is easy. The surprise is how much else then runs on Opus 5.5 too.

Background tasks. Claude Code does small jobs behind the scenes, such as generating session titles. On the Anthropic API those go to Haiku. On Foundry they run on your primary model, which is now Opus 5.5, unless you deploy a Haiku model and point ANTHROPIC_DEFAULT_HAIKU_MODEL at it.

Subagents. When Claude Code fans work out to subagents (the Explore agent searching your repo, for example), each one uses the main conversation’s model unless something says otherwise. That’s Opus 5.5 for every file search. If you deploy a cheaper model, route subagents to it:

Again, those are deployment names, so use yours. Opus 5.5 does the planning and the edits in the main conversation; a cheaper model does the searching and reading.

Only reference models you actually deployed. Foundry has no startup model check, so Claude Code won’t warn you about a typo or a missing deployment when it launches. You find out mid-session. While drafting this post, a subagent in my own session died with:

It had tried a model my resource didn’t have. Everything else kept working, which is exactly why it’s easy to miss. If you only deployed Opus 5.5, leave the Sonnet and Haiku lines out and accept that everything runs on Opus.

Dev takeaway: with one deployment, every token is an Opus token. That can be fine, since Opus 5.5 is cheaper than Opus 5, but make it a decision rather than a surprise.


Make the $0.20 Cache Reads Count

Cache reads at $0.20/M are the best part of the Opus 5.5 price sheet, and Claude Code is a cache-heavy workload: every turn re-sends your instructions, CLAUDE.md, and the conversation so far. Caching is on automatically. Three things decide whether you actually get those cheap reads:

  • The default cache lifetime on Foundry is 5 minutes. Step away for coffee, come back, and the next turn re-writes the whole context at full price. For long sessions with gaps, set ENABLE_PROMPT_CACHING_1H to 1 in the env block. One-hour cache writes are billed at a higher rate than 5-minute writes, so this pays off for long, stop-and-start sessions, not quick ones. (Recent Claude Code versions also have CLAUDE_CODE_PROMPT_CACHE_TTL=1h, which applies only to the main conversation.)
  • Pick your model at the start and stay on it. Switching from Opus 5.5 to Sonnet and back mid-session throws away the cache each time.
  • Set up MCP servers before you start. Some Azure-hosted deployments reject Claude Code’s tool search, so it loads all MCP tools up front. Then connecting or removing an MCP server mid-session resets the cache.

Refusals Show Up in Your Editor Now

In the SDK post I made refusal handling a required pattern, because a refusal is a successful HTTP response with no answer in it. In Claude Code you don’t write that handler, but you’ll still see the result: Opus 5.5 declines more requests than Opus 5 in the biology, cybersecurity, and reasoning-extraction categories.

If you work on security tooling (scanners, fuzzers, detection rules), you’ll occasionally hit a decline on a request that looks reasonable to you. Rephrase the request with the defensive context, or do that piece by hand. Don’t try to engineer around the classifier; on a work resource, that’s a conversation for your security team, not a prompt trick.


Checking What You Actually Spent

Inside Claude Code, run /usage (/cost is an alias). On Foundry you get the session’s token counts, a prompt cache line, and an estimated dollar cost at list price. That estimate is great for “did turning effort up just double my session?”, and the cache line tells you whether the 5-minute or 1-hour setting is actually working.

It is not your bill. The real numbers live in Azure Cost Management for the Foundry resource, at whatever price your agreement gives you. Anthropic’s usage dashboards don’t see Foundry traffic at all. For per-developer numbers across a team, Claude Code can export usage through OpenTelemetry. Tagging the Foundry resource (team=…, env=dev) makes chargeback easier.


When Something’s Off

These are the Opus 5.5-specific problems I’d check first:

Symptom Likely cause Fix
/status shows Sonnet, not Opus 5.5 Only ANTHROPIC_DEFAULT_OPUS_MODEL is set Add ANTHROPIC_MODEL with your Opus 5.5 deployment name
model … is not available on your foundry deployment An alias or subagent points at a model you didn’t deploy Deploy it, or remove that line from env
/effort seems to do nothing CLAUDE_CODE_EFFORT_LEVEL is set and overrides it Remove the env var for interactive use
Bill higher than /usage suggests per session Background tasks and subagents running on Opus 5.5 Deploy Haiku/Sonnet and set the Haiku and subagent model lines
Every turn after a break is expensive 5-minute cache lifetime expired ENABLE_PROMPT_CACHING_1H=1 for long sessions
VS Code panel asks you to sign in to Anthropic Login prompt not disabled “claudeCode.disableLoginPrompt”: true
401 / 403 Missing role, or az login in the wrong tenant Azure AI User or Cognitive Services User on the resource; az login –tenant <id>

One more: there’s no /logout on Foundry. To switch accounts or tenants, change your az login.


Bottom Line

Opus 5.5 is the first Opus worth testing as your all-day default in Claude Code. It’s cheaper, faster, and medium effort is enough for most work. But “default” has to be deliberate on Foundry. Set ANTHROPIC_MODEL, confirm it with /status, decide whether background tasks and subagents should really run on Opus, and turn effort up only for the problem that needs it.

Configure it once in ~/.claude/settings.json, and the CLI and VS Code both pick it up. Then keep an eye on /usage for a week before you roll it out to the team.

Building AI features in C#? I write about practical, no-hype prompt engineering and Azure AI patterns for .NET developers. Check out Prompt Engineering for .NET Developers — free, no Python required. You can also subscribe for more posts.

ClaudeOpus5.5forCSharpDevelopers

Anthropic’s newest model, Claude Opus 5.5, just landed — meaning if you’re already building with Claude, you can call Anthropic’s most capable coding-and-reasoning model with a resource API key. Here’s what’s actually new, and how it looks from C#.

What Actually Shipped

A few facts worth knowing before you touch any code:

  • 40% cheaper than Opus 5. Input tokens at $4/M, output at $20/M (vs. $5/$25), with cache reads at just $0.20/M — a 60% drop that hits hard for agentic workloads where re-read context dominates the bill.
  • Medium effort is now the default. Anthropic reports Opus 5.5 matches Opus 5’s quality at noticeably fewer output tokens when running at the medium effort level. You control reasoning depth with the effort parameter (low → max) instead of the old thinking toggle.
  • Adaptive thinking is always on. You can no longer disable thinking. The effort parameter is your one dial for reasoning depth, latency, and cost.
  • 30%+ faster output. Opus 5.5 generates text noticeably faster than Opus 5 — meaningful when sessions run for hours unattended.
  • Sharper vision. Reads dense charts, diagrams, and screenshots more precisely, so a lot of prompt-side image preprocessing you may have built for earlier models becomes unnecessary.
  • New safety classifiers. Opus 5.5 will decline more requests than Opus 5 did (biology, cybersecurity, and reasoning-extraction categories), which means your error handling needs to check for refusals explicitly now.

Why This Matters for .NET Developers Specifically

The use cases Anthropic is calling out map directly onto real .NET workloads:

  • Long-running agentic coding. Overnight refactors, codebase-wide migrations, and multi-step debugging that would have taken engineering teams days — Opus 5.5 handles these with fewer turns and lower cost.
  • Enterprise knowledge work. Financial analysis, contract review, research synthesis across large document sets, and professional-grade spreadsheets and presentations.
  • Vision-powered workflows. Analyzing screenshots, technical diagrams, and PDFs directly — no separate OCR or vision model pipeline.
  • Cost-efficient scaling. The 40% cost reduction plus cheaper cache reads means you can run Opus 5.5 at larger scale without the bill spiraling — especially for agentic workloads where context per request has grown 2.6x in the last six months.

One thing worth knowing up front if you’re coming from OpenAI models in Foundry: Claude doesn’t use Azure.AI.OpenAI or Microsoft.Extensions.AI‘s OpenAI connector. It has its own official SDK — Anthropic, plus a Foundry-specific Anthropic.Foundry package for Azure-native authentication. As always: no Python, no notebooks — just C# and dotnet run.

Getting Started

Claude ships its own official .NET SDK, and Foundry gets its own package on top of it — this is not the Azure.AI.OpenAI pattern you might already have wired up for GPT models in Foundry.

Deploy Claude Opus 5.5 from the Foundry Model Catalog to your Foundry resource — same process as any other model. You need your resource name and a Foundry resource API key, not a separate Anthropic API key. Replace the placeholders locally; local/key authentication must be enabled on the Foundry resource for this sample to work.

API-key authentication is used in this sample. Using Anthropic.Foundry and AnthropicFoundryApiKeyCredentials with the resource key and resource name. Never commit API keys to source control or include them in screenshots or logs. User secrets keep keys out of the project files but are not encrypted and are for local development only. For production, use a managed secret store or environment variables supplied securely by your hosting environment.

Five Use Cases in One Program.cs

The explicit Anthropic reference pins the Messages API types separately from the Foundry authentication adapter.

Replace the generated Program.cs with the C# blocks below, in order: shared setup first, then Use Cases 1–5. They form one program, not five standalone top-level snippets. All using directives and executable startup code belong in this first block; subsequent blocks declare local functions. No other C# source files are needed. The console project and NuGet packages are still required.

The program runs case 1 by default. Pass 1–5 to select a case, or all to run them sequentially. For example, dotnet run — 2 runs the effort example, and dotnet run — all runs the full demo. Live calls incur charges. Case 3 is an offline refusal-handler test; case 4 skips if no screenshot is present; case 5 is a bounded, read-only agent demonstration, not an unattended repository editor.

Here’s the shared client setup and entry point:

Use your actual deployment name if it differs from claude-opus-5-5; set AZURE_AI_FOUNDRY_DEPLOYMENT through user secrets or an environment variable. Set AZURE_AI_FOUNDRY_RESOURCE and AZURE_AI_FOUNDRY_API_KEY for that same resource, with local/key authentication enabled. Compiling does not verify deployment availability, key validity, resource authentication settings, or model features.

Now append each use-case block below to that same file. Function-local parameters and message variables can safely reuse their names.


Use Case 1: A Basic Call — Same Messages API Shape

Whether you’re reviewing code, summarizing test failures, or asking a question about a codebase, the Messages API shape stays the same. Opus 5.5 just handles longer context and more complex reasoning better than its predecessor:

Dev takeaway: switching between direct Anthropic API and Foundry is basically a client constructor change — your request/response code stays identical, which matters if you want to keep a provider-agnostic AI layer.

Case 1 – Sample Output


Use Case 2: Effort — The New Cost/Quality Dial

This is the biggest operational change from Opus 5. Thinking can no longer be disabled. Instead, the effort parameter controls how much the model reasons through a problem before answering. The default is medium — Anthropic reports it matches Opus 5’s quality at noticeably fewer output tokens.

Use case: a build-pipeline bot that triages CI failures at low effort by default, and only escalates to high when the first summary is ambiguous — real cost control without a model swap.

Case 2 – Sample Output


Use Case 3: Refusal Handling — Now a Required Pattern

Handle the API’s refusal stop reason explicitly rather than assuming every successful HTTP response contains an answer. The shared PrintResponse function already does this for every live call. To exercise that branch reliably without trying to provoke a refusal, use this synthetic response fixture. It is a local handler test, not a model request or a complete API response.

Dev takeaway: a refusal can come back as a normal HTTP 200, not an exception. Always check StopReason; surface a clear message or escalate for review rather than automatically routing around the refusal. Authentication failures, throttling, and transport errors are separate failures handled at the entry point.

Case 3 – Sample Output


Use Case 4: Vision — Reading Screenshots Without a Preprocessing Pipeline

Opus 5.5’s sharper vision means you can send raw screenshots and get accurate analysis without a separate OCR step:

For example, dotnet run — 4 “C:\screenshots\error-dialog.png” selects this case. Relative paths are resolved from the current working directory. Only send screenshots you are authorized to share with the model; remove secrets and personal information first.

Use case: a support-ticket triage tool in your backend that reads user-submitted crash screenshots directly, skipping a separate OCR step.

Case 4 – Sample Output


Use Case 5: Long-Running Agent — The Overnight Refactor

Long-running coding work requires more than a single request: the application must preserve conversation history, execute allowed tools, and return each result with its matching tool-use ID. This runnable example demonstrates that loop with a read-only, in-memory sample repository and an eight-request limit. It asks for a migration plan, not file edits; no shell commands or model-generated code are executed.

That’s the final C# block: your single Program.cs now contains the startup code, the response helper, and all five use cases.

Validation scope: the original combined code was compiled with .NET SDK 10.0.302 and the package versions listed above. The offline refusal fixture, argument handling, missing-image behavior, and invalid-PNG guard were exercised locally. Live Foundry requests and the multi-turn agent exchange were not tested against an Azure deployment; those still require a valid Foundry resource API key, local/key authentication enabled, and a compatible model deployment. This code check does not verify the article’s pricing or model-performance claims.

Case 5 – Sample Output

Dev takeaway: the model proposes tool calls; your application decides what actually runs. A production overnight refactor additionally needs an isolated workspace, explicit approval for writes, a restricted test runner, checkpoints, cost limits, and telemetry. Direct Anthropic.Foundry calls do not automatically register this loop with Foundry Agent Service or provide end-to-end tracing; that integration requires separate setup.


Cost Optimization: Making Opus 5.5 Work Harder for Less

Opus 5.5 is already 40% cheaper than Opus 5, but there are practical steps to push costs down further on long-running workloads:

1. Pick the Right Effort Level

Not every task needs max effort. Use this guide:

  • low — CI triage, test summaries, quick b reviews
  • medium (default) — general-purpose coding, design tasks, knowledge work
  • high / xhigh — complex refactors, multi-file migrations, financial analysis
  • max — frontier-level benchmarks, extremely complex reasoning

2. Protect Your Cached Reads

Cache reads are just $0.20/M tokens — a fifth of what they cost on competing models — but they still add up at scale. As agentic coding has matured, organizations have shifted from asking developers to scale at all costs to asking developers to scale efficiently:

  • Pick your model at the start of a session rather than switching midway
  • Compact before you step away rather than after
  • If you’re on API keys or cloud providers, set the one-hour cache lifetime for long sessions
  • Forked subagents start from the parent’s cache instead of paying for the same context again

3. Measure Open-Ended Tasks

On well-scoped tasks, both Opus 5.5 and Opus 5 finish in about the same number of turns — the price cut is all you get. The gap is biggest on open-ended tasks, where a model can spend many turns on the wrong approach. Opus 5.5’s efficiency gains compound on harder, more ambiguous work.


Opus 5 vs. Opus 5.5 — Quick Comparison

Feature Opus 5 Opus 5.5
Input price / MTok $5 $4
Output price / MTok $25 $20
Cache read / MTok $0.50 $0.20
Default effort high medium
Thinking toggleable always on (effort parameter)
Output speed baseline 30%+ faster
Safety classifiers standard expanded (bio, cyber, reasoning)
Available on Foundry yes yes

Bottom Line

Opus 5.5 isn’t just a bigger model — it’s a shift from one-shot demos to sustained, hours-long work. Whether you’re refactoring a 680K-line bbase, analyzing financial filings, or building multi-step agents that run overnight, the 40% cost reduction plus the efficiency gains mean this is the first Opus model you should seriously evaluate for production workloads on Azure.

Deploy it from Foundry, configure your resource name and Foundry resource API key, and start with medium effort on your agentic workloads. You’ll see the cost savings immediately — and on harder, more open-ended tasks, the quality improvement compounds.

Ready to try it? Deploy claude-opus-5-5 from the Foundry Model Catalog and start with the code above. The Anthropic SDK for .NET is the only thing you need — no Python, no notebooks, just C#.

Source code: https://github.com/taswar/GptImage2.5-flare-sunburst-demo


Building AI features in C#? I write about practical, no-hype prompt engineering and Azure AI patterns for .NET developers. Check out Prompt Engineering for .NET Developers — free, no Python required. Also subscribe to my mailing list for the latest blogs, tips and tricks I share.

GPT-Image-2.5-Flare-Subburst

Picture a home design app. A customer types, “Show me a modern kitchen with dark cabinets and a large center island.” An image appears in seconds. They follow up: “Make it brighter, and add natural wood accents.” The app updates the image without redrawing the whole scene, without losing the layout that was already right. That’s the interaction GPT-image-2.5 — split into two models, Flare and Sunburst — is built for: fast, iterative image generation and editing that actually holds up across a real revision loop, not just a single lucky prompt.

Both models are now Generally Available from OpenAI or most providers. As always: no Python, no notebooks. Just Azure.AI.OpenAI‘s ImageClient, Microsoft.Extensions.Configuration, and dotnet run.

What Actually Shipped

  • Two models, one job split by speed vs. precision. Flare is the smaller, faster model for most production workloads — higher-quality images than GPT-image-2 at 50% lower latency, which is what keeps a user inside a live iteration loop instead of waiting on every change. Sunburst is for creative workflows that need greater precision and control — high-fidelity campaign assets and polished visuals where quality outranks speed.
  • More accurate editing. Update targeted elements while preserving the rest of the image — not a full re-roll every time you ask for a small change.
  • Stronger multi-turn editing. Refine through successive instructions without the image drifting or degrading as edits accumulate. This is the thing that actually breaks in a lot of image models: edit three quietly changes something edit one got right.
  • Better instruction following. More accurate interpretation of complex visual instructions, layouts, and stylistic direction.
  • Transparent background generation. Generate logos, product cutouts, UI assets, icons, and stickers directly with a transparent background — set background=”transparent” and output_format=”png” (PNG or WebP required; JPEG doesn’t support transparency).
  • Both GA, both production-ready. Unlike some of the other models in this catalog, there’s no preview caveat here — Flare and Sunburst are both fully supported for production workloads today.

Why This Matters for .NET Developers Specifically

The use cases map directly onto real .NET workloads:

  • Marketing and campaign production — generate and resize campaign assets from an approved creative direction, with legible headline text rendered directly in the image
  • Retail and e-commerce catalogs — produce and maintain large volumes of consistent product imagery at scale
  • Virtual try-on and personalization — let a shopper preview an item, then adjust color, style, or setting through successive edits without the result drifting
  • Education and training content — generate diagrams and illustrations that evolve as a lesson or explanation develops
  • Travel, real estate, and discovery apps — turn a description into personalized imagery a user can react to and refine

Both models sit behind the exact same ImageClient you may already be using for GPT-image-2 or GPT-image-1 — swapping in Flare or Sunburst is a deployment-name change, not a rewrite.

Getting Started

Deploy gpt-image-2.5-flare and gpt-image-2.5-sunburst from the Foundry Model Catalog to your project — same process as any other model. Grab your endpoint, and you’re ready to go.

Here’s the shared client setup every example below builds on:

Now let’s put both models to work on the scenarios that we are targeting.

Use Case 1: Home Design — Iterative Generation That Holds Its Shape

The scenario from the announcement, minus the voice layer: a customer describes a kitchen, sees it rendered, and asks for a change — and the change should read as a revision, not a brand-new image that happens to share a theme. Flare is the right choice here since this is a live iteration loop where responsiveness matters more than maximum fidelity.

Expected Output

kitchen-v1

kitchen-v1

The important detail is which API call each step uses: the first pass is a plain generation, but the revision is an edit against the actual first image — not a second generation call with an updated prompt. That distinction is what keeps the island and the camera angle consistent between v1 and v2 instead of getting a completely different kitchen that happens to also have wood accents.

Use Case 2: Travel Planning — Exploration with Flare, Final Asset with Sunburst

Exploring destinations and itineraries generates a lot of throwaway previews for every one image a traveler actually keeps. This is the two-tier pattern the Flare/Sunburst split is built for: cheap, fast previews during exploration, then a single higher-fidelity render once a direction is locked.

Expected Output

preview-0

preview-0

preview-1

preview-1

itinerary-day3-final-small

itinerary-day3-final-small

Paying full Sunburst price for every exploratory preview doesn’t make sense when most of them get discarded — this pattern only spends the higher-cost, higher-fidelity call once a customer has actually committed to a direction.

Use Case 3: Education — Diagrams That Evolve With the Lesson

A student discusses a concept with an AI tutor and gets diagrams that evolve as the lesson progresses — not one static diagram handed over up front. Flare regenerates a diagram each time the topic shifts, which only works if generation is fast enough to keep pace with a real conversation.

Expected Output

lesson-diagram-0

lesson-diagram-0

lesson-diagram-1

lesson-diagram-1

Wire this into a chat-driven tutoring UI and the diagram updates the moment a student asks a follow-up question — no separate “generate a diagram” button, no need for the student to describe what they want drawn in prompt-engineering terms.

Use Case 4: Retail Campaign Creative — Legible Text, Consistent Batches

Marketing and catalog work both come down to the same requirement: consistent output at volume, with headline text that’s actually legible — historically the weak point of diffusion models. Here’s a campaign banner from Sunburst (final quality matters) followed by a Flare batch of product catalog shots (volume matters more than maximum fidelity).

Expected Output

catalog-SKU-1001

catalog-SKU-1001

catalog-SKU-1002

catalog-SKU-1002

catalog-SKU-1003

catalog-SKU-1003

campaign-summer-sale-banner

campaign-summer-sale-banner

Open the campaign banner and check the headline text specifically — that’s the failure mode this model generation is explicitly built to fix. And because the catalog template is fixed with only the description swapped per SKU, lighting and framing stay consistent across the whole batch — swap the hardcoded array for a real product database and this loop becomes an overnight catalog-refresh job.

Use Case 5: Virtual Try-On — Multi-Turn Editing Without Drift

Virtual try-on lets a shopper preview an item and then adjust color, style, or setting — successive edits that need to stay consistent with each other, not drift with every change. This is Sunburst’s precision-editing strength: each edit builds on the last while the customer’s pose, framing, and identity stay intact.

Expected Output

customer-tryon-photo

customer-tryon-photo

tryon-navy

tryon-navy

tryon-navy-outdoors

tryon-navy-outdoors

Two edits deep, the customer’s face, pose, and the jacket’s shape are all still consistent — only the color and background changed, exactly as requested. That’s “stronger multi-turn editing” in practice: the kind of drift where edit three quietly changes something from edit one is exactly what this release is built to avoid, and it’s the difference between a try-on feature customers trust and one they give up on after two tries.

Where This Fits (and Where It Doesn’t)

Reach for Flare when:

  • You’re iterating live with a user in the loop and latency matters more than maximum fidelity
  • You’re generating at volume — catalogs, previews, personalization

Reach for Sunburst when:

  • The output is a final, ship-ready asset — a campaign hero image, a locked try-on result
  • Editing precision matters more than speed, especially across multiple successive edits

Don’t reach for either when:

  • You need pixel-perfect brand-guideline compliance with zero human review — treat generated output as a strong first draft, not an approval-free final asset
  • Your workload depends on non-text modalities or file attachments the image APIs don’t cover — check current capability docs before committing to a design

Wrapping Up

The pitch for GPT-image-2.5 isn’t “one bigger image model” — it’s a genuine two-tier portfolio: iterate fast with Flare, ship precise with Sunburst, and trust that a multi-turn edit chain won’t quietly drift by the third revision. For .NET developers, both models sit behind the exact same ImageClient you already know from GPT-image-2 — the new surface area is picking which model fits which step of your workflow, not learning a new SDK. Note: I had issues with the edit calls returing 404, thus I switched to HTTP Client

Source code: https://github.com/taswar/GptImage2.5-flare-sunburst-demo


Building AI features in C#? I write about practical, no-hype prompt engineering and Azure AI patterns for .NET developers. Check out Prompt Engineering for .NET Developers — free, no Python required. Also subscribe to my mailing list for the latest blogs, tips and tricks I share.

Azure 5 Highlights Thursday

This is the bonus content for the #124 edition of 5 Highlights Thursday — 7 highlights this week instead of 5. If you haven’t seen the main newsletter yet, check it out on LinkedIn.

1. What’s your favorite new GitHub Copilot feature?

A Copilot-focused video covering the workflow named in the title, useful for developers looking to apply AI assistance more consistently in day-to-day work.

2. What if an agent could refactor your agent?

A developer-focused look at AI agents, grounded in the specific build or platform scenario named in the title.

3. Event-driven agents, powered by MCP

A developer-focused look at Model Context Protocol patterns, grounded in the specific platform or workflow scenario named in the title.

4. A unified MCP layer with Toolboxes in Microsoft Foundry

A developer-focused look at Model Context Protocol patterns, grounded in the specific platform or workflow scenario named in the title.

5. When chatbots grow buttons: Building MCP apps with FastMCP

A developer-focused look at Model Context Protocol patterns, grounded in the specific platform or workflow scenario named in the title.

6. Building MCP servers with VS Code — Level up your MCP

A developer-focused look at Model Context Protocol patterns, grounded in the specific platform or workflow scenario named in the title.

7. What’s the deal with these IQs?

A current Microsoft developer update focused on the scenario named in the title, selected for this week’s digest based on recency and view count.


As always, please give me feedback on LinkedIn. Which bullet above is your favorite? What do you want more or less of? Other suggestions? Please let me know.

Download my Free Ebook Prompt Engineering for .NET Developers.

Last by not least, know someone who might be interested in this newsletter? Share it with them.

Subscribe to my Newsletter

Have a wonderful Thursday 😉

Taswar

MAI-Image-2.6

Every time a new image model ships, I ask the same unglamorous question: can I actually put this in a pipeline, or is it just good at one pretty hero shot? Most image models nail the demo and fall apart the moment you need the fiftieth consistent variant of the same product, or a single surgical edit that doesn’t quietly redraw everything else in the frame.

Microsoft AI just shipped two models that answer that question directly: MAI-Image-2.6 and MAI-Image-2.6-Flash, both now in public preview in Microsoft Foundry. They’re not “one model, two names” — they’re a genuine two-tier portfolio: one for maximum quality, one for maximum throughput, sharing the same capabilities underneath.

As always: no Python, no notebooks. Just C#, HttpClient, and a dotnet run.

What Actually Shipped

A few facts worth knowing before you touch any code:

  • MAI-Image-2.6 is independently verified as frontier-tier. No. 2 on the Arena text-to-image leaderboard at launch, ahead of Google’s Nano Banana family and Meta’s Muse Image. No. 3 on Arena’s image-editing leaderboard, and No. 1 for image editing on Artificial Analysis. This isn’t a marketing claim you have to take on faith — it’s ranked against the models you’re probably already comparing against.
  • Multi-reference editing. MAI-Image-2.6 accepts up to five reference images in a single request. Lock a product, a character, or a brand mark, and it stays consistent as you revise, resize, and reformat it. One approved concept travels across channel formats without drifting.
  • Web grounding. The model can pull real-world context from Bing Search instead of relying only on training data — meaningfully better accuracy for real places, objects, events, and subjects.
  • Explicit control over format and resolution. Adaptive aspect ratios, 1.5K output resolution, and levers over how much the model deliberates before generating — so the same model family serves both a fast iteration loop and a final production render.
  • MAI-Image-2.6-Flash is the throughput tier. More than 2x faster than GPT-Image-2-Medium and roughly 72–78% more efficient than GPT-Image-2, depending on the metric. Built for interactive apps, automated pipelines, and personalization at volume.
  • Pricing. MAI-Image-2.6 starts at $5/1M text input tokens, $8/1M image input tokens, $38/1M image output tokens. MAI-Image-2.6-Flash starts at $1.75/1M text input, $2.50/1M image input, $19/1M image output — genuinely cheap enough to generate per-user variants without flinching.
  • Enterprise-ready by default. Delivered as a Foundry Model sold directly by Azure — Entra ID auth, RBAC, key-based access, Azure data-handling commitments. Prompts and outputs are not used to train the models.

Choosing Between Them

This isn’t “pick the cheap one or the good one.” It’s a real division of labor:

  • MAI-Image-2.6 — final campaign assets, complex multi-reference edits, high-fidelity text rendering, anything where precision is the point
  • MAI-Image-2.6-Flash — rapid iteration, interactive experiences, personalization, high-volume generation, anything where throughput is the point

The intended workflow: explore and iterate with Flash, then render the final asset with MAI-Image-2.6 once the direction is locked. You’ll see exactly that pattern in the code below.

Prerequisites

Deploy both MAI-Image-2.6 and MAI-Image-2.6-Flash from the Foundry Model Catalog to your project — same process as any other model.

📝 Note: MAI-Image models aren’t compatible with the Azure.AI.OpenAI SDK’s ImageClient — they require the raw REST call against Foundry’s images endpoint, same as MAI-Image-2.5. The exact API surface is still settling in public preview, so confirm request/response shapes against the Foundry Model Catalog before shipping anything to production.

Here’s a small shared helper both examples below build on — auth token + a reusable POST helper:

Now let’s put both models to work on the actual use cases Microsoft is targeting.

Use Case 1: Marketing & Campaign Production — Legible Text, First Try

Text rendering inside generated images has historically been the weak point of diffusion models — garbled letters, wrong spacing, headlines that look right at a glance and fall apart on inspection. MAI-Image-2.6’s quality step-up specifically targets this.

Open the file and check the headline text specifically — that’s the thing to inspect closely, since it’s the failure mode this model is explicitly built to fix. If your marketing team currently routes every hero banner through a designer for text placement and kerning, this is the workflow to pilot first: generate ten headline variants overnight, let the team pick the one that needs the least manual cleanup.

Use Case 2: Retail & E-Commerce Catalogs — Consistent Imagery at Volume

Catalogs live and die on consistency: same lighting, same framing, same background across hundreds of SKUs. Here’s a batch pattern using Flash for the volume — this is exactly the “millionth personalized variant” scenario Flash is priced for.

Because the style template is fixed and only the product description changes, lighting and framing stay consistent across the whole batch. Swap this loop to read SKUs from your actual product database and you have an overnight catalog-refresh job instead of a photo studio booking.

Use Case 3: Brand & Creative Operations — Multi-Reference Editing

This is the capability that’s genuinely new in 2.6: up to five reference images in a single request, so a locked brand asset — a mascot, a product shape, a logo mark — stays consistent as you reformat it for different channels. Here’s a helper for a multi-reference edit call, followed by locking a product across three different channel formats.

Same mascot, same product, same brand colors — three different channel-native compositions, generated from two locked reference images instead of a designer manually recreating the layout three times. This is the actual “one approved concept travels across formats without drifting” pitch, and it’s the reason multi-reference editing is the headline feature of this release.

Use Case 4: Personalization at Scale — Flash in an Interactive Loop

Flash’s pricing and latency profile make per-user or per-segment generation viable inside a live request path, not just a batch job. Here’s a minimal pattern for a personalized greeting card generator — the kind of feature you’d wire into an app, not run overnight.

(Timings above are illustrative — measure against your own Foundry deployment region and load. The point of the pattern is that Flash’s latency profile makes this loop viable inside a request/response cycle, not that these exact numbers are guaranteed.)

Swap the hardcoded array for real user data from your app, and this same loop becomes a “generate a personalized asset on demand” endpoint behind an API controller.

Use Case 5: Image Cleanup & Surgical Editing

The other side of multi-reference editing is single-image precision editing — targeted object edits, replacements, inpainting, text updates, and artifact removal, without regenerating the whole scene. This is the same surgical-edit pattern from MAI-Image-2.5, still very much present in 2.6.

This is the unglamorous, high-volume use case that actually pays for itself: a warehouse team’s phone-camera product shots turned into catalog-ready images without a reshoot. The product itself is untouched — only the blur and background changed.

Where This Fits (and Where It Doesn’t)

Reach for MAI-Image-2.6 when:

  • You need final, ship-ready campaign assets with legible, precise text rendering
  • You’re locking a brand asset across multiple reference images and need it to survive reformatting
  • Editing precision matters more than generation speed

Reach for MAI-Image-2.6-Flash when:

  • You’re generating at volume — catalogs, personalization, high-throughput pipelines
  • Latency matters because the call sits inside an interactive user-facing path
  • You’re iterating on concepts before committing to a final MAI-Image-2.6 render

Don’t reach for either when:

  • You need pixel-perfect brand-guideline compliance without any human review — treat generated output as a strong first draft, not a final approval-free asset
  • Your workload depends on an SDK-level ImageClient integration today — you’re on raw REST calls for now, and the API surface is still settling in public preview

Wrapping Up

MAI-Image-2.6 and MAI-Image-2.6-Flash aren’t “the same model, one slower.” They’re a genuine quality/throughput portfolio: iterate fast with Flash, ship precise with 2.6, and use multi-reference editing to keep one approved creative direction consistent across every format your marketing or product team actually needs. If your team is currently paying someone to manually generate the fiftieth catalog variant or resize one approved hero image into six channel formats by hand — this is worth a real pilot, not just a demo.

Resources


Building AI features in C#? I write about practical, no-hype prompt engineering and Azure AI patterns for .NET developers. Check out Prompt Engineering for .NET Developers — free, no Python required. Also subscribe to my mailing list for the latest blogs, tips and tricks I share.

UA-4524639-2