Azure News - 2026-09-04
2026-09-04
最終更新: 2026-09-06 05:46:28 JST
AI による概要
この日は OpenAI の新しいフロンティアモデル GPT-6 Astra が主題でした。Microsoft Foundry の Limited Access Program を通じて展開が始まり、参加する顧客へ順次広がっていきます。同じ内容が提供開始と一般提供という複数の告知で繰り返し流れており、業務向けのフロンティアインテリジェンスという位置づけが強調されています。あわせて、この数週間の Microsoft への評価は、モデル・インフラストラクチャ・データ・アプリケーション・開発者ツールが AI の本番投入時に 1 つのシステムとして噛み合っている点に帰着する、という主張の記事も公開されました。アーキテクチャブログでは、Private Link で Azure AI Foundry を閉じてもエージェントの送信 (egress) までは覆えない、という指摘が実践的に扱われています。AI Foundry を Private Link で固めたうえで、別の仮想ネットワークの VM 上にある MCP サーバーをエージェントから呼ばせ、すべてをプライベートに保ったまま図ではなく実証で示す、という依頼に対して、後半が想定どおりにいかなかった経緯と実際に構築したものが書かれています。小売業向けのデモ 3IQ Retail Assistant も 3 部構成で公開されました。Fabric IQ、Foundry IQ、Work IQ を組み合わせ (Web IQ はまだパブリックプレビュー前)、テンプレートがすべてのサービスを VNET 配下のプライベートエンドポイントのみで構成することや、Copilot Studio で SharePoint リストにつながる Copilot エージェントを作って他の 2 つのエージェントと接続する手順が扱われています。事例としては、Microsoft の物理セキュリティエンジニアリングチームが Azure Arc と Azure Virtual Desktop でハイブリッド運用を簡素化し、可視性を高めてグローバルに展開した取り組みが紹介されました。サービス更新は Azure Virtual Network Manager の IP アドレス管理 (IPAM) のリージョン拡大で、US Gov Virginia、US Gov Texas、US Gov Arizona、および China North 3、China East 3 で一般提供になりました。セキュリティでは、AI モデルから指示を隠す手口として広まった不可視の Unicode 文字が、メールフィルターが解析する前の段階で単語を難読化する用途に転用され、フィッシングの回避にも使われ始めているという分析が公開されています。
主要トピック
モデル: OpenAI の GPT-6 Astra が Microsoft Foundry の Limited Access Program で展開開始
AI セキュリティ: Private Link で AI Foundry を閉じてもエージェントの送信は覆えない、という落とし穴と実際の構成
デモ: Fabric IQ / Foundry IQ / Work IQ を組み合わせた小売業向け 3IQ Retail Assistant を 3 部構成で解説
ネットワーク管理: Azure Virtual Network Manager の IPAM が US Gov (Virginia / Texas / Arizona) と中国リージョン (North 3 / East 3) で GA
ハイブリッド運用: Microsoft の物理セキュリティチームが Azure Arc と Azure Virtual Desktop で運用を統合しグローバル展開
脅威情報: AI へのプロンプトインジェクション由来の ASCII スマグリング (不可視 Unicode) が、メールフィルター回避のフィッシングへ転用
プラットフォーム論: モデル・インフラ・データ・アプリ・開発ツールが 1 つのシステムとして噛み合うことが本番 AI の要件
Azure Updates
[Launched] Generally Available: Azure Virtual Network Manager IPAM in additional Azure regions
- Link: https://azure.microsoft.com/updates?id=570557
- Published: 2026-09-04 02:17:08
- Fetched: 2026-09-04 03:56:32
Azure Blog
How Microsoft’s Physical Security Engineering Team scaled hybrid operations with Azure Arc and Azure Virtual Desktop
- Link: https://azure.microsoft.com/en-us/blog/how-microsofts-physical-security-engineering-team-scaled-hybrid-operations-with-azure-arc-and-azure-virtual-desktop/
- Published: 2026-09-04 00:00:00
- Fetched: 2026-09-04 15:37:19
Learn how Microsoft used Azure Arc and Azure Virtual Desktop to simplify hybrid security operations, improve visibility, and scale globally.
The post How Microsoft’s Physical Security Engineering Team scaled hybrid operations with Azure Arc and Azure Virtual Desktop appeared first on Microsoft Azure Blog.
GPT-6 Astra: Frontier intelligence for work, now available in Microsoft Foundry
- Link: https://azure.microsoft.com/en-us/blog/gpt-6-astra-frontier-intelligence-for-work-now-available-in-microsoft-foundry/
- Published: 2026-09-04 03:15:00
- Fetched: 2026-09-04 15:37:19
GPT-6 Astra, OpenAI's newest frontier model, begins rolling out today through the Microsoft Foundry Limited Access Program, with availability expanding to participating customers over the coming days.
The post GPT-6 Astra: Frontier intelligence for work, now available in Microsoft Foundry appeared first on Microsoft Azure Blog.
GPT-6 Astra: Frontier intelligence for work, now generally available in Microsoft Foundry
- Link: https://azure.microsoft.com/en-us/blog/gpt-6-astra-frontier-intelligence-for-work-now-available-in-microsoft-foundry/
- Published: 2026-09-04 03:15:00
- Fetched: 2026-09-05 10:37:58
GPT-6 Astra, OpenAI's newest frontier model, begins rolling out today through the Microsoft Foundry Limited Access Program, with availability expanding to participating customers over the coming days.
The post GPT-6 Astra: Frontier intelligence for work, now generally available in Microsoft Foundry appeared first on Microsoft Azure Blog.
GPT-6 Astra: Frontier intelligence for work, now generally available in Microsoft Foundry
- Link: https://azure.microsoft.com/en-us/blog/gpt-6-astra-frontier-intelligence-for-work-now-generally-available-in-microsoft-foundry/
- Published: 2026-09-04 03:15:00
- Fetched: 2026-09-06 05:46:28
GPT-6 Astra, OpenAI's newest frontier model, begins rolling out today through the Microsoft Foundry Limited Access Program, with availability expanding to participating customers over the coming days.
The post GPT-6 Astra: Frontier intelligence for work, now generally available in Microsoft Foundry appeared first on Microsoft Azure Blog.
Enterprise AI transformation relies on the end-to-end platform: Azure was built for this moment
- Link: https://azure.microsoft.com/en-us/blog/enterprise-ai-transformation-relies-on-the-end-to-end-platform-azure-was-built-for-this-moment/
- Published: 2026-09-04 04:00:00
- Fetched: 2026-09-04 15:37:19
The recognition for Microsoft over the past couple of weeks comes down to models, infrastructure, data, applications, and developer tools working as one system when AI moves into production.
The post Enterprise AI transformation relies on the end-to-end platform: Azure was built for this moment appeared first on Microsoft Azure Blog.
Microsoft Security Blog
ASCII smuggling crosses over from AI prompt injection to phishing evasion
- Link: https://www.microsoft.com/en-us/security/blog/2026/09/03/ascii-smuggling-crosses-over-from-ai-prompt-injection-to-phishing-evasion/
- Published: 2026-09-04 01:00:00
- Fetched: 2026-09-04 03:56:32
Invisible Unicode characters popularized for hiding instructions from AI models are now being used to obfuscate words before email filters parse them.
The post ASCII smuggling crosses over from AI prompt injection to phishing evasion appeared first on Microsoft Security Blog.
Azure Architecture Blog
Building 3IQ Retail Assistant Demo – Part 3
- Link: https://techcommunity.microsoft.com/t5/azure-architecture-blog/building-3iq-retail-assistant-demo-part-3/ba-p/4547233
- Published: 2026-09-04 02:23:13
- Fetched: 2026-09-04 10:36:48
詳細を表示
We are now at the last part of our demo. We will build a Copilot Agent to connect it to a SharePoint List holding data related to Support case raised by the customers. Then connect the other 2 agents (Fabric Data Agent and Foundry Prompt Agent) to it. But before doing it ensure Work IQ is activated with your Copilot, and you can build agents in Copilot Studio using Work IQ. Contact your Admin if it is not available. Also, Go ahead and rescale the Fabric Capacity to F64 and Resume it from the Azure Portal.
Setting up SharePoint List
Create a list in your M365 SharePoint site of choice and add the following entries. I referred to the customer/sales data available in our Fabric Lakehouse:
You can add more entries referring to the related data from Lakehouse. These 2 entries are enough for the time being for our demo purpose.
Setting up Copilot Agent
Now open your Copilot Studio and start creating an agent. Give it a name of your choice and select “GPT-5 Chat” as the model. Once created, in the Agents tab click on “Add an agent” and then “Connect to an external agent”. You can add both your Fabric Data Agent and Foundry Prompt Agent through this.
Next, open the Knowledge tab and click on “Add knowledge” and then on “SharePoint (Powered by Work IQ)”. Here you add your SharePoint list and add it to the agent.
At the end, In the instruction write the following. Change the name of your Data and Prompt agents and SharePoint knowledge source suitably:
“You are an intelligent agent assisting customer service representatives of Adventure Works Inc. You have different sources to retrieve data. Give least priority to answers generated by the LLM model and give highest priorities to the data retrieved from these data sources.
To start with if the requirement is customer support, then ask for customer name, sales order id, and if they are calling due to an existing support request then support case id. Then use following sources to get data:
- Foundry IQ Agent - use this connected agent to answers questions on Adventure Works Inc. Retail Customer Support Representative Guide, Retail Customer Terms and Conditions, Retail Customer Payment, Purchase, Shipping & Refund Information.
- AWDataAgent - use this connected agent to retrieve sales data about orders by the customers, about sellers/employees, about products and product subcategories and categories. This is based on Ontology that defines the relationships among the entities.
- Use the knowledge source Support_Data through SharePoint to fetch data about the support request/case/ticket raised by the customer previously. If the customer has previous support case open bring that info additionally once you get information about the customer.
If given a Sales Order ID, or Customer Name, Customer ID and the question is not relevant to support case then use AWDataAgent connected agent. If it is specific to existing support request, then use SharePoint List knowledge source.”
That’s it. Our demo is ready. Now test it with a series of relevant questions:
“I have to help a customer”.
“The Sales Order ID is 58970”.
“Is there any support case opened by this customer?”.
“Customer is asking the Half Finger Gloves are not up to the quality and she wants to return. But she used it. Can we do that?”.
That’s it. Your demo is ready for the show.
Building 3IQ Retail Assistant Demo – Part 2
- Link: https://techcommunity.microsoft.com/t5/azure-architecture-blog/building-3iq-retail-assistant-demo-part-2/ba-p/4547231
- Published: 2026-09-04 02:24:04
- Fetched: 2026-09-04 10:36:48
詳細を表示
In part 1 while setting up the Azure environment, I informed the template puts everything under VNET and all the services are having only private endpoints. Which is great from the security point of view. We also spoke about creating a jumpbox as a Bastion host to work on those services. If you did it already – great, if not, we can bypass the situation by opening the public endpoint from Networking menu for each of these following services.
Setting up Blob Storage Container
Unlike structured data used for Foundry, we will use some unstructured data (pdf files) for Foundry and build knowledge source and knowledge base and will use those with our Foundry agent. To start with, I used 3 PDF files as listed below:
- Adventure Works Inc Retail Customer Support Representative Guide.pdf
- Adventure Works Inc. – Retail Customer Terms and Conditions.pdf
- Adventure Works Inc. – Retail Customer Payment, Purchase, Shipping & Refund Information.pdf
I used synthetic data for these PDF files. You can use Copilot, ChatGPT, Gemini, or Claude to generate the content.
Once done, we will create a Blob Container. There is a Storage Account created already by the template. You can use it to create the Blob Container. Now upload these 3 files there. You may have to add your account as a Storage Blob Data Contributor to upload the files if not already there.
We need to add few more permissions to this container. Add Storage Blob Data Reader access to:
- Foundry account's managed identity
- Foundry Project's managed identity
- Azure AI Search service's managed identity
Setting up Search
A search service is already provisioned by the template. Use this to set up your knowledgebase and knowledgesource. Create the knowledgesource with similar set up:
Then create a knowledgebase using this knowledgesource and with the following description: “Use this to answer questions related to Adventure Works Inc.'s retail customer policies, including the Support Representative Guide, Terms and Conditions, and Payment, Purchase, Shipping & Refund information”. I kept the Retrieval Reasoning Effect as Minimal and didn’t add any Chat completion model as such.
Setting up Foundry Agent
It’s time now to set up our Foundry Agent. Create a simple prompt agent and use any Chat completion model. It can be any LLM or SLM of your choice. This agent can be pro-code one using either Agent Service SDK or a hosted agent using MAF or LangGraph. But we would like to keep it simple for this demo.
For the Instructions I have written –
“You are an intelligent agent to answer questions on Adventure Works Inc. Retail Customer Support Representative Guide, Retail Customer Terms and Conditions, Retail Customer Payment, Purchase, Shipping & Refund Information.
Please answer from the knowledgebase only. If answer is not available within knowledgebase say not available politely”.
And now add the knowledgebase you created within the search service. That’s pretty much it. Your Foundry Agent with IQ is ready and you can now ask a few complex questions to it like – “Can customer get refund if the delivery is returned due to wrong address?”, "Can customer get refund if the shipping is delayed?", “Customer wants to return but she doesn't have the bill. Can she return the product?” etc.
At last, make sure you turn your Foundry service public on Azure Portal by going to Resource Management > Networking > Firewall and Virtual Networks. This is required to publish the Foundry Agent to M365 Copilot:
As of today, you cannot publish the agent if it has a private endpoint. There are workarounds by creating the Bot service separately (the publish option does the magic silently) and exposing the Agent endpoint using APIM/App Gateway etc. I haven’t taken that route for this demo to make it simple. But here are some links just in case someone would like to explore:
Publish Foundry Agents to Teams Behind a Private Endpoint · Russ Rimmerman
Building 3IQ Retail Assistant Demo – Part 1
- Link: https://techcommunity.microsoft.com/t5/azure-architecture-blog/building-3iq-retail-assistant-demo-part-1/ba-p/4547228
- Published: 2026-09-04 02:24:53
- Fetched: 2026-09-04 10:36:48
詳細を表示
Introduction
Recently I received a request from one of our GSI partners to demonstrate them 4IQs on a retail industry scenario. Unfortunately, Web IQ is still not in public preview. Hence, I promised them to come back with an example later with Web IQ. But even with the remaining Fabric IQ, Foundry IQ and Work IQ, the issue is finding the right set of data and then build a story around it to demonstrate an agentic solution addressing some practical real-life scenario.
After doing some research with available data, I formulated a plan to prepare an assistant for customer reps to address incoming questions and requests from customers. This article describes how to build such an environment to demonstrate the capability of 3IQs together.
First, we need an Azure subscription with option to provision Fabric capacity, need Foundry, M365, and Copilot Studio access. Once you have those, let’s move to set up our environment.
Environment Set Up
I have limited time in hand. So, I went ahead with existing templates to implement Foundry and surrounding services on Azure. I used this Bicep template: foundry-samples/infrastructure/infrastructure-setup-bicep/16-private-network-standard-agent-apim-setup at main · microsoft-foundry/foundry-samples. There are several other templates available on that page. You can choose any one of those based on your preference. This template puts all resources including Foundry behind private endpoints with no public internet access. You can add a jumpbox as a Bastion host to connect to all these services. Or time to time you can make those services public to complete your work.
Setting up Fabric
We will start with data layer which is Fabric. It is not provisioned yet. I provisioned a Fabric capacity with minimum size/SKU (F2) within the Resource Group generated by the Bicep template earlier. Fabric is an expensive service, especially the higher SKUs are. So, we need to be careful not spend too much and surpass our monthly Azure quota. Once provisioned, go to https://app.fabric.microsoft.com/ and create a Workspace using the same Fabric Capacity we provisioned earlier.
Here “Fabric3IQ” is the name of my Fabric capacity. As the workspace is created now, let’s create a Lakehouse inside the Workspace and start loading data into the Lakehouse. But prior to that, let’s go to the Fabric capacity on Azure Portal and increase the size to a bigger SKU such as F64. We will load AdventureWorks sales data into the Lakehouse. There is a detail description here showing how to do it: Quickstart: Create Your First Graph in Microsoft Fabric - Microsoft Fabric | Microsoft Learn. Only follow the “Load Sample Data” section. One done, it should look like this:
Now is the time to create our Ontology. People who are not familiar can find a guide in this tutorial: Tutorial Part 1: Create an Ontology - Microsoft Fabric | Microsoft Learn. We added each table from Lakehouse as entities and build relationship within those entities. Here is how it looks like now:
Next is adding a Data Agent to the Fabric Workspace. Once added, now add a data source and select the Ontology you created earlier.
Now, as your Data Agent is ready ask few complex questions like: “What are the top 5 categories sold?”, “Give me the seller's name who handled most orders in numbers and not in total sale amount?”, “List those customers who didn't purchase anything” and see the result. Once, satisfied, let’s pause the Fabric Capacity from Azure Portal and reduce the size of the capacity to F2. We will resume and rescale it once everything is ready.
Your Private Endpoint Does Not Cover Agent Egress: Locking Down Azure AI Foundry in Both Directions
- Link: https://techcommunity.microsoft.com/t5/azure-architecture-blog/your-private-endpoint-does-not-cover-agent-egress-locking-down/ba-p/4547864
- Published: 2026-09-04 23:59:04
- Fetched: 2026-09-05 00:15:41
詳細を表示
I got asked a question a few weeks ago that sounded simple. Lock down Azure AI Foundry with Private Link, and let the agents call an MCP server hosted on a VM in a different virtual network. Everything private, nothing over the public internet, and proof rather than a diagram.
I said yes, that is straightforward. I was wrong about the second half.
What follows is what I actually built, what broke along the way, and the one thing that cost me most of an afternoon. Everything here was deployed and verified on a live subscription. The scripts and the raw logs are on GitHub if you want to reproduce it:
GitHub - raffaeu/azure-foundry-private-link: Provision Azure AI Foundry behind a Private Endpoint with private DNS, then prove it works: HTTP 200 from inside the VNet over a private IP, HTTP 403 from outside. Numbered az CLI scripts, managed-identity auth, and a one-command test harness.
Provision Azure AI Foundry behind a Private Endpoint with private DNS, then prove it works: HTTP 200 from inside the VNet over a private IP, HTTP 403 from outside. Numbered az CLI scripts, managed-identity auth, and a one-command test harness. - raffaeu/azure-foundry-private-link
The mistake almost everyone makes
Here is the thing I want you to take away, even if you read nothing else.
A private endpoint on your Foundry resource secures traffic going into Foundry. It does absolutely nothing about the traffic your agents send out.
Those are two different features, configured in two completely different ways, with two completely different sets of failure modes. If you configure the private endpoint, disable public network access, see your test call succeed from inside the VNet, and call it done, you have secured exactly half of the problem. Your agent can still be reaching out to a tool endpoint from a Microsoft owned public IP address, and nothing in the portal will tell you that.
| Direction | Mechanism | |
|---|---|---|
| Inbound | client to Foundry | Private endpoint |
| Outbound | Foundry agent to your API | Network injection |
I built and proved both. Let me take them in order.
Part one: the inbound half
This part is well documented and mostly behaves. The shape of it:
- A VNet with a subnet for private endpoints, with
private-endpoint-network-policiesdisabled, which is mandatory and easy to forget - A Foundry account created with a custom domain, which is required for Private Link to work at all
- Private DNS zones, and here is the first trap
- A private endpoint with a DNS zone group
publicNetworkAccessset toDisabled
The DNS trap is that you need three zones, not one:
privatelink.openai.azure.com
privatelink.services.ai.azure.com
privatelink.cognitiveservices.azure.com
The Foundry endpoint answers on several FQDNs, and if you only create the zone matching the hostname you happen to be testing with, the others silently resolve to the public IP. Traffic still works, which is exactly what makes it dangerous. It looks fine.
All three zones have to be linked to the VNet, and the DNS zone group on the private endpoint is what actually writes the A records. Miss the zone group and you get zones with nothing in them.
Proving it, properly
This is where I want to push back on how these setups usually get validated. People run one test, from inside the VNet, see a 200, and declare victory.
That proves nothing on its own.
A 200 from inside the VNet is perfectly compatible with a resource whose public endpoint is also wide open. You need both halves:
from inside the VNet -> DNS resolves to 10.0.1.5, call returns HTTP 200
from my laptop -> HTTP 403, "Public access is disabled"
Only when both are true have you proven anything. I wrote a small script that runs both and prints a single verdict, because I know that if it is two commands, one of them eventually gets skipped.
A couple of things bit me here that are worth knowing.
The tenant had key based authentication disabled by policy. Every api-key call returned 403 AuthenticationTypeDisabled, and attempts to set disableLocalAuth back to false silently reverted. Not a problem, Entra ID tokens are the better practice anyway, but if you are following an older tutorial with api-key headers you will lose time wondering why your key is rejected. Inside the VM I used the managed identity via IMDS, so there were no secrets to copy around at all.
The subscription also blocked public IP creation, which meant Azure Bastion could not be deployed. That turned out not to matter. az vm run-command invoke runs scripts inside a VM over the Azure control plane, no SSH, no public IP, no Bastion required. I now prefer it for this kind of testing.
Part two: the outbound half, where it got interesting
Now the actual request. The agent needs to call an MCP server on a VM in a separate VNet, and I need to prove the call arrives from a private address.
The mechanism is network injection, officially "Standard Setup with Bring Your Own Virtual Network". You give Foundry a delegated subnet in your VNet, and the agent runtime gets network interfaces in it, so its outbound calls originate from your address space.
Three requirements caught me out before I wrote a single line.
The delegation is Microsoft.App/environments. Not Microsoft.CognitiveServices, which is what I assumed. Agent compute runs on Azure Container Apps under the hood, which is why the delegation belongs to the Microsoft.App namespace. You also have to register both Microsoft.App and Microsoft.ContainerService as resource providers. Skip that and ARM happily accepts your account, then puts it in provisioningState: Failed several minutes later.
Network injection is creation time only. You cannot add it to an existing Foundry account. I had a perfectly good account from part one and it was useless for this. Plan for a rebuild, or better, make the decision before you deploy anything.
Private networking forces Standard Setup, which means bring your own Storage, Cosmos DB and AI Search. These are not optional extras you can add later for convenience. The capability host will not provision without all three. That is real money, AI Search Basic alone is around 75 dollars a month, so budget for it and remember to tear it down.
For the proof I wrote a deliberately dumb mock MCP server. About sixty lines of Node.js, JSON-RPC on port 8080, no authentication, running as a systemd unit. Its only real job is forensic: log req.socket.remoteAddress for every single caller to a file.
const ip = (req.socket.remoteAddress || '').replace(/^::ffff:/, '');
log(`CALLER=${ip} ${req.method} ${req.url} ua="${req.headers['user-agent']}"`);
That log file is the entire experiment. Everything else is scaffolding.
The thing that cost me the afternoon
I built everything. Subnet delegated correctly, verified. Providers registered, verified. Account created with networkInjections.scenario = "agent", and I could read the property straight back off the resource to confirm it. Peering connected in both directions. The MCP server responding happily to curl from a VM in the other VNet, logging the caller as 10.0.2.4, so cross-VNet private routing was definitely working.
Then I ran the agent and got this:
BadRequestError: Error code: 400 - {'error': {'message': 'Server returned 424: None',
'type': 'external_connector_error', 'param': 'tools', 'code': 'http_error'}}
And the MCP server log showed nothing at all. Not a failed connection, not a rejected handshake. Zero packets.
That "424" tells you almost nothing. My first instinct was networking, because that is what the error smells like, and because I had just spent an hour on networking. I checked the NSG. I went back over the peering. I confirmed the delegation again. All fine.
The actual answer is that there are two capability hosts, and I had only one.
The account level capability host is created implicitly for you when you set networkInjections. You will see it exist, it will say Succeeded, and it looks like the job is done.
The project level capability host has to be created explicitly, along with connections to your three BYO resources. Until that exists, the agent runtime has nowhere to run. Every tool call fails with that opaque 424, and because the runtime never starts, your tool endpoint never sees a packet, which sends you looking at the network instead of at the thing that is actually missing.
I also had to grant the project's managed identity data plane roles on Storage, Cosmos and Search, or the capability host provisioning itself fails.
Worth noting: the documentation says to expect 30 to 35 minutes for this on a network injected account. Mine completed in about four. Do not cancel it either way, but do not block your afternoon on the higher number.
The proof
With the project capability host in place, I ran it again. The agent's response:
The MCP server reports that your request arrived from source IP 10.0.4.119.
And from the MCP server's own access log:
2026-08-17T15:07:02.378Z CALLER=10.0.4.119 POST / ua="AzureAIFoundryAgentRuntime/231188750"
{"method":"initialize","params":{"protocolVersion":"2025-11-25",...}}
2026-08-17T15:07:02.508Z CALLER=10.0.4.119 POST / ua="AzureAIFoundryAgentRuntime/231188750"
{"method":"tools/list","params":{},"id":2,"jsonrpc":"2.0"}
2026-08-17T15:07:03.829Z CALLER=10.0.4.119 POST / ua="AzureAIFoundryAgentRuntime/231188750"
{"method":"tools/call","params":{"name":"whoami","arguments":{}},"id":2,"jsonrpc":"2.0"}
10.0.4.119 is an address from the delegated agent subnet, 10.0.4.0/24. The user agent is the Foundry agent runtime identifying itself. The full MCP handshake is there, initialize, then tools/list, then tools/call.
That is the whole point of the exercise, in one line of a log file. The agent reached a server in a different virtual network, over peering, from a private IP address, and I can show you the packet arriving rather than asking you to trust an architecture diagram.
Smaller things that wasted my time
In case you hit the same walls:
az vm createwould not resolve my subnet. By name it tried to create a new one at10.0.0.0/24, which was not what I asked for at all, and by full resource ID it insisted the subnet did not exist. I gave up and created the NIC explicitly withaz network nic create, then attached it with--nics. Worked immediately.az cosmosdb createhas no-l/--location. It wants--locations regionName=... failoverPriority=0.az vm run-commandexecutes under/bin/sh, not bash. My script started withset -euo pipefailand died on line one with "Illegal option -o pipefail".azure-ai-projects2.x changed shape.list_agentsis gone. I usedclient.get_openai_client()and the Responses API with a nativemcptool type instead, which worked cleanly. It also needshttpxinstalled and does not pull it in.- Role names differ per tenant. "Azure AI User" did not exist in mine. "Azure AI Developer" and "Azure AI Administrator" did.
- And an early self inflicted one, I put
set -euo pipefailin a variables file that was meant to be sourced. That applies the flags to your interactive shell, so the first command returning non-zero closes your terminal window. If a file is designed to be sourced, leave strict mode out of it.
If your DNS lives on premises
This came up straight after, so it is worth including.
Azure Private DNS zones are not reachable from on premises. 168.63.129.16 is a VNet internal address and is not routable over VPN or ExpressRoute, so your own DNS server cannot query the zone directly.
Deploy an Azure DNS Private Resolver with an inbound endpoint in the VNet, then conditional forward from the on premises resolver to that private IP. Forward only the privatelink.* zones. Do not forward openai.azure.com wholesale, because the public lookup returns the CNAME that the whole chain depends on, and taking that over breaks other Azure endpoints.
What I would tell the next person
- Test both directions, and test the negative case. A 200 from inside proves nothing on its own.
- Decide on network injection before you create the account, because you cannot add it later.
- If you get a
424 external_connector_errorand your endpoint logs are empty, stop looking at the network. Check whether the project level capability host exists. - Budget for Cosmos and AI Search from the start, they are mandatory, not optional.
- Prove it with a log from the destination. A source IP in an access log is evidence. A diagram is a claim.
Everything is on GitHub, including the raw run logs, so you can see the failures as well as the working version: github.com/raffaeu/azure-foundry-private-link
If you have done this in a hub and spoke topology with a firewall in the path, I would genuinely like to hear how the UDRs worked out for you, because that is the next thing on my list.