<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>The .NET Blog</title><link>https://thedotnetblog.com/ru/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>ru</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Mon, 14 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/ru/index.xml" rel="self" type="application/rss+xml"/><item><title>NDC Oslo 2026</title><link>https://thedotnetblog.com/ru/events/ndc-oslo-2026/</link><pubDate>Mon, 14 Sep 2026 00:00:00 +0000</pubDate><guid>https://thedotnetblog.com/ru/events/ndc-oslo-2026/</guid><description>Одна из крупнейших конференций для разработчиков в Европе — 5 дней воркшопов, сессий и нетворкинга в Oslo Spektrum с более чем 150 спикерами и 160 сессиями.</description><content:encoded>&lt;p&gt;&lt;strong&gt;NDC Oslo 2026&lt;/strong&gt; проходит с &lt;strong&gt;14 по 18 сентября 2026 года&lt;/strong&gt; в &lt;strong&gt;Oslo Spektrum&lt;/strong&gt;, Осло, Норвегия.&lt;/p&gt;
&lt;p&gt;NDC Oslo — одна из крупнейших и наиболее уважаемых конференций для разработчиков в Европе, охватывающая всё: от .NET и облачных технологий до безопасности, архитектуры, ИИ и другого. Выпуск 2026 года сейчас на этапе бронирования, с масштабной программой в процессе формирования.&lt;/p&gt;
&lt;h2 id="в-цифрах"&gt;В цифрах&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;160 сессий&lt;/strong&gt; (бронирование)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;150 спикеров&lt;/strong&gt; (бронирование)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;15 воркшопов&lt;/strong&gt; (бронирование)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;5 дней&lt;/strong&gt; — воркшопы + конференция&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="подтверждённые-спикеры"&gt;Подтверждённые спикеры&lt;/h2&gt;
&lt;p&gt;Список спикеров формируется, среди подтверждённых имён:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nick Chapsas&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maddy Montaquila&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Troy Hunt&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kevlin Henney&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Venkat Subramaniam&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jeff Fritz&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Philippe De Ryck&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nhlanhla Lucky Nkosi&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aleksander Stensby&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="билеты"&gt;Билеты&lt;/h2&gt;
&lt;p&gt;Билеты Early Bird доступны — предложение Early Bird действует до &lt;strong&gt;22 мая 2026 года&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;CFP (Call for Papers) также открыт.&lt;/p&gt;
&lt;h2 id="другие-мероприятия-ndc-в-2026-году"&gt;Другие мероприятия NDC в 2026 году&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NDC Sydney — 22–24 апреля 2026&lt;/li&gt;
&lt;li&gt;NDC Toronto — 5–8 мая 2026&lt;/li&gt;
&lt;li&gt;NDC Copenhagen — 1–4 июня 2026&lt;/li&gt;
&lt;li&gt;NDC AI — 8–10 июня 2026&lt;/li&gt;
&lt;li&gt;NDC TechTown — 21–24 сентября 2026&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ссылки"&gt;Ссылки&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ndcoslo.com/"&gt;Сайт мероприятия&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ndcoslo.com/tickets"&gt;Билеты&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ndcoslo.com/call-for-papers"&gt;Call for Papers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ndcoslo.com/speakers"&gt;Спикеры&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>.NET Day Switzerland 2026</title><link>https://thedotnetblog.com/ru/events/dotnet-day-switzerland-2026/</link><pubDate>Tue, 25 Aug 2026 00:00:00 +0000</pubDate><guid>https://thedotnetblog.com/ru/events/dotnet-day-switzerland-2026/</guid><description>Некоммерческая конференция сообщества для .NET-разработчиков, архитекторов и экспертов — .NET, C#, ASP.NET Core, Azure и другие темы — в Цюрихе.</description><content:encoded>&lt;p&gt;&lt;strong&gt;.NET Day Switzerland 2026&lt;/strong&gt; пройдёт &lt;strong&gt;25 августа 2026 года&lt;/strong&gt; в &lt;strong&gt;Arena Cinemas Sihlcity&lt;/strong&gt; (Kalanderplatz 8, 8045 Цюрих).&lt;/p&gt;
&lt;p&gt;Это независимая некоммерческая конференция сообщества для разработчиков, архитекторов и экспертов, посвящённая .NET, C#, ASP.NET Core, Azure и экосистеме разработки Microsoft. Все спикеры и организаторы участвуют добровольно, а излишки от продажи билетов направляются на благотворительность или развитие швейцарского .NET-сообщества.&lt;/p&gt;
&lt;h2 id="что-вас-ждёт"&gt;Что вас ждёт&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Качественные доклады от международных экспертов&lt;/li&gt;
&lt;li&gt;Нетворкинг с другими участниками&lt;/li&gt;
&lt;li&gt;Еда, закуски и напитки во время перерывов, обеда и аперо&lt;/li&gt;
&lt;li&gt;Карьерные возможности через взаимодействие со спонсорами&lt;/li&gt;
&lt;li&gt;Прямое общение со спикерами в перерывах&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="билеты"&gt;Билеты&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Категория&lt;/th&gt;
&lt;th&gt;Цена&lt;/th&gt;
&lt;th&gt;Доступность&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Very Early Bird (1–30 апр)&lt;/td&gt;
&lt;td&gt;299 CHF&lt;/td&gt;
&lt;td&gt;Макс. 100 билетов&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Early Bird&lt;/td&gt;
&lt;td&gt;399 CHF&lt;/td&gt;
&lt;td&gt;Макс. 100 билетов&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Обычный&lt;/td&gt;
&lt;td&gt;449 CHF&lt;/td&gt;
&lt;td&gt;До распродажи&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Спикеры и расписание ещё не объявлены — приём заявок открыт на &lt;a href="https://sessionize.com/net-day-switzerland-2026/"&gt;Sessionize&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="организаторы"&gt;Организаторы&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/FabianGosebrink"&gt;Fabian Gosebrink&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/manumeyer1"&gt;Manuel Meyer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/gassmannt"&gt;Thomas Gassmann&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ссылки"&gt;Ссылки&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dotnetday.ch/"&gt;Сайт мероприятия&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://eepurl.com/dDoFEn"&gt;Подписка на рассылку&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>SDD Conference 2026</title><link>https://thedotnetblog.com/ru/events/sdd-conference-2026/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://thedotnetblog.com/ru/events/sdd-conference-2026/</guid><description>5-дневная конференция по разработке ПО в Barbican Centre в Лондоне с 78 сессиями и 14 воркшопами по архитектуре, .NET, ИИ, Azure, DevOps и другим темам.</description><content:encoded>&lt;p&gt;&lt;strong&gt;SDD 2026&lt;/strong&gt; проходит с &lt;strong&gt;11 по 15 мая 2026 года&lt;/strong&gt; в &lt;strong&gt;Barbican Centre в Лондоне&lt;/strong&gt;. Основная 3-дневная конференция — со вторника по четверг, с опциональными однодневными воркшопами в понедельник и пятницу.&lt;/p&gt;
&lt;p&gt;С &lt;strong&gt;78 сессиями&lt;/strong&gt; и &lt;strong&gt;14 воркшопами&lt;/strong&gt; это одна из самых насыщенных конференций для разработчиков в Европе.&lt;/p&gt;
&lt;h2 id="темы"&gt;Темы&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Архитектурное мышление&lt;/li&gt;
&lt;li&gt;Функциональный код на C# 13&lt;/li&gt;
&lt;li&gt;Serverless-дизайн&lt;/li&gt;
&lt;li&gt;Семантический ИИ&lt;/li&gt;
&lt;li&gt;Azure Kubernetes Services&lt;/li&gt;
&lt;li&gt;Lean DevOps стратегии&lt;/li&gt;
&lt;li&gt;Протокол контекста модели (MCP)&lt;/li&gt;
&lt;li&gt;Агентный ИИ в .NET&lt;/li&gt;
&lt;li&gt;Рефакторинг монолита&lt;/li&gt;
&lt;li&gt;Быстрее программировать с LLM&lt;/li&gt;
&lt;li&gt;Криптография в постквантовом мире&lt;/li&gt;
&lt;li&gt;Local-First разработка&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="спикеры"&gt;Спикеры&lt;/h2&gt;
&lt;p&gt;Программу мирового класса представляют &lt;strong&gt;Kevlin Henney&lt;/strong&gt;, &lt;strong&gt;Neal Ford&lt;/strong&gt;, &lt;strong&gt;Sander Hoogendoorn&lt;/strong&gt;, &lt;strong&gt;Andrew Clymer&lt;/strong&gt;, &lt;strong&gt;Jacqui Read&lt;/strong&gt;, &lt;strong&gt;Christian Weyer&lt;/strong&gt;, &lt;strong&gt;Jeff Prosise&lt;/strong&gt;, &lt;strong&gt;Jules May&lt;/strong&gt;, &lt;strong&gt;Oliver Sturm&lt;/strong&gt; и &lt;strong&gt;Raju Gandhi&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="билеты-и-информация"&gt;Билеты и информация&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sddconf.com/"&gt;Сайт мероприятия&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sddvault.s3.amazonaws.com/assets/SDD_2026_schedule.pdf"&gt;PDF полного расписания&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sddconf.com/register"&gt;Варианты регистрации&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;98% участников SDD 2025 оценили общее впечатление как хорошее, очень хорошее или отличное.&lt;/p&gt;</content:encoded></item><item><title>Azure DevOps MCP Сервер Апрельское Обновление: WIQL-Запросы, PAT Аутентификация и Экспериментальные MCP Apps</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-mcp-server-april-2026-wiql-pat-apps/</link><pubDate>Mon, 27 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-mcp-server-april-2026-wiql-pat-apps/</guid><description>Azure DevOps MCP Сервер получает WIQL-запросы к рабочим элементам, аутентификацию Personal Access Token, аннотации MCP и экспериментальную функцию MCP Apps.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/posts/emiliano-montesdeoca/azure-devops-mcp-server-april-2026-wiql-pat-apps/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Azure DevOps MCP Сервер продолжает совершенствоваться. Апрельское обновление Дэна Хеллема охватывает оба сервера.&lt;/p&gt;
&lt;h2 id="поддержка-wiql-запросов"&gt;Поддержка WIQL-Запросов&lt;/h2&gt;
&lt;p&gt;Новый инструмент &lt;code&gt;wit_query_by_wiql&lt;/code&gt; позволяет запускать Work Item Query Language запросы прямо из MCP-клиента.&lt;/p&gt;
&lt;h2 id="personal-access-tokens"&gt;Personal Access Tokens&lt;/h2&gt;
&lt;p&gt;PAT аутентификация на локальном сервере — важна для интеграционных сценариев без интерактивной аутентификации.&lt;/p&gt;
&lt;h2 id="аннотации-mcp"&gt;Аннотации MCP&lt;/h2&gt;
&lt;p&gt;Метаданные для read-only, destructive и open-world инструментов — основа надёжности агентов.&lt;/p&gt;
&lt;h2 id="консолидация-wiki-инструментов"&gt;Консолидация Wiki-Инструментов&lt;/h2&gt;
&lt;p&gt;5 отдельных wiki-инструментов → 2 более мощных. Меньше инструментов = лучше производительность LLM.&lt;/p&gt;
&lt;h2 id="экспериментально-mcp-apps"&gt;Экспериментально: MCP Apps&lt;/h2&gt;
&lt;p&gt;Упакованные рабочие процессы в среде MCP-сервера. Направление правильное.&lt;/p&gt;
&lt;p&gt;Оригинальный пост Дэна Хеллема: &lt;a href="https://devblogs.microsoft.com/devops/azure-devops-mcp-server-april-update/"&gt;Azure DevOps MCP Server April Update&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>SQL Server 2025 как База Данных для Агентов: Безопасность, Бэкап и MCP в Одном Движке</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/sql-server-2025-agent-ready-security-mcp/</link><pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/sql-server-2025-agent-ready-security-mcp/</guid><description>Финальная часть серии Polyglot Tax разбирает сложные задачи производства: единая Row-Level Security по реляционным, JSON, граф и векторным данным, плюс MCP-интеграция.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/posts/emiliano-montesdeoca/sql-server-2025-agent-ready-security-mcp/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Я следил за серией Polyglot Tax Адитьи Бадрамраджу с большим интересом. Часть 4 завершает серию частями, которые реально определяют, доверяли бы вы этой архитектуре в продакшне.&lt;/p&gt;
&lt;h2 id="одна-модель-безопасности-для-всех-моделей-данных"&gt;Одна Модель Безопасности для Всех Моделей Данных&lt;/h2&gt;
&lt;p&gt;Одна политика Row-Level Security покрывает все таблицы — реляционные, JSON, граф, векторы. Одна политика, одно доказательство для аудитора.&lt;/p&gt;
&lt;h2 id="единый-бэкап--атомарное-восстановление"&gt;Единый Бэкап = Атомарное Восстановление&lt;/h2&gt;
&lt;p&gt;В полиглотном стеке point-in-time recovery через пять баз данных — это кошмар согласованности. С одной базой данных восстановление атомарно по определению.&lt;/p&gt;
&lt;h2 id="mcp-интеграция-агенты-без-middleware"&gt;MCP-Интеграция: Агенты Без Middleware&lt;/h2&gt;
&lt;p&gt;SQL Server 2025 напрямую поддерживает SQL MCP Server. Агенты вызывают инструменты, движок автоматически обеспечивает изоляцию тенантов и маскировку столбцов.&lt;/p&gt;
&lt;p&gt;Оригинальный пост Адитьи Бадрамраджу: &lt;a href="https://devblogs.microsoft.com/azure-sql/the-polyglot-tax-part-4/"&gt;The Polyglot Tax – Part 4&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>.NET 10 поставляется с Ubuntu 26.04 LTS — Что Нового</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-ubuntu-2604-resolute-raccoon-net10/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-ubuntu-2604-resolute-raccoon-net10/</guid><description>Ubuntu 26.04 LTS (Resolute Raccoon) вышел с .NET 10 в качестве первоклассного тулчейна. Native AOT, Chiseled-контейнеры, Linux 7.0.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост переведён автоматически. Чтобы просмотреть оригинал, &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-ubuntu-2604-resolute-raccoon-net10/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;День Ubuntu LTS. &lt;a href="https://canonical.com/blog/canonical-releases-ubuntu-26-04-lts-resolute-raccoon"&gt;Ubuntu 26.04 (Resolute Raccoon)&lt;/a&gt; вышел сегодня вместе с &lt;a href="https://devblogs.microsoft.com/dotnet/whats-new-for-dotnet-in-ubuntu-2604/"&gt;.NET 10&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;LTS на LTS — пять лет поддержки ОС, совпадающих с окном долгосрочной поддержки .NET 10.&lt;/p&gt;
&lt;h2 id="установить-net-10-двумя-командами"&gt;Установить .NET 10 двумя командами&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install dotnet-sdk-10.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;.NET является одним из &lt;a href="https://ubuntu.com/toolchains"&gt;официально поддерживаемых тулчейнов на Ubuntu&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="контейнеры-обновить--noble-на--resolute"&gt;Контейнеры: обновить &lt;code&gt;-noble&lt;/code&gt; на &lt;code&gt;-resolute&lt;/code&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sed -i &lt;span class="s2"&gt;&amp;#34;s/noble/resolute/g&amp;#34;&lt;/span&gt; Dockerfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Все существующие варианты образов — включая &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-dotnet-chiseled-containers/"&gt;Chiseled&lt;/a&gt; — доступны.&lt;/p&gt;
&lt;h2 id="native-aot-запуск-за-3мс-бинарник-14мб"&gt;Native AOT: запуск за 3мс, бинарник 1,4МБ&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install -y dotnet-sdk-aot-10.0 clang
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet publish app.cs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# нативный бинарник 1,4МБ, запуск за 3мс&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Для cloud-native рабочих нагрузок, где время холодного запуска важно — Functions, контейнеры, serverless — реальная игра меняется.&lt;/p&gt;
&lt;h2 id="нужен-net-8-или-9"&gt;Нужен .NET 8 или 9?&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install -y software-properties-common
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;add-apt-repository ppa:dotnet/backports
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;apt install -y dotnet-sdk-8.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/whats-new-for-dotnet-in-ubuntu-2604/"&gt;Полный пост&lt;/a&gt; содержит больше деталей о cgroup v2, пост-квантовой криптографии и Linux 7.0.&lt;/p&gt;</content:encoded></item><item><title>Azure MCP Server Теперь .mcpb — Установка без Какого-либо Runtime</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-server-mcpb-no-runtime-install/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-server-mcpb-no-runtime-install/</guid><description>Azure MCP Server теперь доступен как MCP Bundle (.mcpb) — скачайте, перетащите в Claude Desktop, и готово. Node.js, Python или .NET не нужны.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост переведён автоматически. Чтобы просмотреть оригинал, &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-server-mcpb-no-runtime-install/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Знаете, что раздражало в настройке MCP-серверов? Нужен был runtime. Node.js для npm-версии, Python для pip/uvx, .NET SDK для dotnet-варианта.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/azure-sdk/azure-mcp-server-mcpb-support/"&gt;Azure MCP Server только что изменил это&lt;/a&gt;. Теперь он доступен как &lt;code&gt;.mcpb&lt;/code&gt; — MCP Bundle — и настройка выполняется перетаскиванием.&lt;/p&gt;
&lt;h2 id="что-такое-mcp-bundle"&gt;Что такое MCP Bundle?&lt;/h2&gt;
&lt;p&gt;Думайте о нём как о расширении VS Code (&lt;code&gt;.vsix&lt;/code&gt;) или расширении браузера (&lt;code&gt;.crx&lt;/code&gt;), но для MCP-серверов. Файл &lt;code&gt;.mcpb&lt;/code&gt; — это автономный ZIP-архив с бинарным файлом сервера и всеми его зависимостями.&lt;/p&gt;
&lt;h2 id="как-установить"&gt;Как установить&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1. Скачайте bundle для вашей платформы&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Перейдите на &lt;a href="https://github.com/microsoft/mcp/releases?q=Azure.Mcp.Server"&gt;страницу GitHub Releases&lt;/a&gt; и скачайте файл &lt;code&gt;.mcpb&lt;/code&gt; для вашей ОС и архитектуры.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Установите в Claude Desktop&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Самый простой способ: перетащите файл &lt;code&gt;.mcpb&lt;/code&gt; в окно Claude Desktop на странице настроек расширений (&lt;code&gt;☰ → Файл → Настройки → Расширения&lt;/code&gt;). Проверьте детали сервера, нажмите «Установить», подтвердите.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Аутентифицируйтесь в Azure&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;az login
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Всё. Azure MCP Server использует ваши существующие учётные данные Azure.&lt;/p&gt;
&lt;h2 id="что-можно-делать"&gt;Что можно делать&lt;/h2&gt;
&lt;p&gt;Доступ к 100+ инструментам сервисов Azure прямо из вашего ИИ-клиента:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Запрашивать и управлять Cosmos DB, Storage, Key Vault, App Service, Foundry&lt;/li&gt;
&lt;li&gt;Генерировать команды &lt;code&gt;az&lt;/code&gt; CLI для любых задач&lt;/li&gt;
&lt;li&gt;Создавать шаблоны Bicep и Terraform&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="с-чего-начать"&gt;С чего начать&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Загрузка&lt;/strong&gt;: &lt;a href="https://github.com/microsoft/mcp/releases?q=Azure.Mcp.Server-"&gt;GitHub Releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Репозиторий&lt;/strong&gt;: &lt;a href="https://aka.ms/azmcp"&gt;aka.ms/azmcp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Документация&lt;/strong&gt;: &lt;a href="https://aka.ms/azmcp/docs"&gt;aka.ms/azmcp/docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Смотрите &lt;a href="https://devblogs.microsoft.com/azure-sdk/azure-mcp-server-mcpb-support/"&gt;полный пост&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Azure SDK Апрель 2026: AI Foundry 2.0 и Что Должны Знать .NET-Разработчики</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-sdk-april-2026-ai-foundry-2-stable/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-sdk-april-2026-ai-foundry-2-stable/</guid><description>Апрельский релиз Azure SDK включает стабильный Azure.AI.Projects 2.0.0 со значительными ломающими изменениями, критические исправления безопасности Cosmos DB и новые библиотеки Provisioning для .NET.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/posts/emiliano-montesdeoca/azure-sdk-april-2026-ai-foundry-2-stable/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Ежемесячные SDK-релизы часто легко пропустить. В этом есть несколько вещей, заслуживающих внимания.&lt;/p&gt;
&lt;h2 id="azureaiprojects-200--ломающие-изменения-которые-имеют-смысл"&gt;Azure.AI.Projects 2.0.0 — Ломающие Изменения, Которые Имеют Смысл&lt;/h2&gt;
&lt;p&gt;Разделение пространств имён, переименование типов, последовательное соглашение &lt;code&gt;Is*&lt;/code&gt; для булевых свойств.&lt;/p&gt;
&lt;h2 id="cosmos-db-java-критическое-исправление-безопасности-rce"&gt;Cosmos DB Java: Критическое Исправление Безопасности (RCE)&lt;/h2&gt;
&lt;p&gt;Версия 4.79.0 исправляет &lt;strong&gt;уязвимость удалённого выполнения кода (CWE-502)&lt;/strong&gt;. Обновитесь немедленно.&lt;/p&gt;
&lt;h2 id="новые-provisioning-библиотеки-для-net"&gt;Новые Provisioning-Библиотеки для .NET&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/Azure.Provisioning.Network/1.0.0"&gt;Azure.Provisioning.Network 1.0.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/Azure.Provisioning.PrivateDns/1.0.0"&gt;Azure.Provisioning.PrivateDns 1.0.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Оригинальный пост: &lt;a href="https://devblogs.microsoft.com/azure-sdk/azure-sdk-release-april-2026/"&gt;Azure SDK Release (April 2026)&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>CodeAct в Agent Framework: Как сократить задержку агента вдвое</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/codeact-agent-framework-hyperlight-50-percent-faster/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/codeact-agent-framework-hyperlight-50-percent-faster/</guid><description>CodeAct сворачивает многошаговые цепочки инструментов в один изолированный блок кода — снижая задержку на 52% и использование токенов на 64%.</description><content:encoded>&lt;p&gt;&lt;em&gt;Эта статья была переведена автоматически. Для просмотра оригинала &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/codeact-agent-framework-hyperlight-50-percent-faster/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;В каждом проекте с агентами наступает момент, когда смотришь на трассировку и думаешь: «Почему это так долго работает?» Модель в порядке. Инструменты работают. Но для получения результата, который можно вычислить за один раз, происходит семь туров обмена данными.&lt;/p&gt;
&lt;p&gt;Именно эту проблему решает CodeAct — и &lt;a href="https://devblogs.microsoft.com/agent-framework/codeact-with-hyperlight/"&gt;команда Agent Framework только что выпустила альфа-поддержку&lt;/a&gt; через новый пакет &lt;code&gt;agent-framework-hyperlight&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="что-такое-codeact"&gt;Что такое CodeAct?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://arxiv.org/abs/2402.01030"&gt;Паттерн CodeAct&lt;/a&gt; элегантно прост: вместо того чтобы давать модели список инструментов для поочерёдного вызова, вы даёте ей единственный инструмент &lt;code&gt;execute_code&lt;/code&gt; и позволяете выразить &lt;em&gt;весь план&lt;/em&gt; как короткую программу на Python.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Подход&lt;/th&gt;
&lt;th&gt;Время&lt;/th&gt;
&lt;th&gt;Токены&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Традиционный&lt;/td&gt;
&lt;td&gt;27,81с&lt;/td&gt;
&lt;td&gt;6 890&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CodeAct&lt;/td&gt;
&lt;td&gt;13,23с&lt;/td&gt;
&lt;td&gt;2 489&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Улучшение&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;52,4%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;63,9%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="безопасность-микро-vm-hyperlight"&gt;Безопасность: Микро-VM Hyperlight&lt;/h2&gt;
&lt;p&gt;Пакет &lt;code&gt;agent-framework-hyperlight&lt;/code&gt; использует микро-VM &lt;a href="https://github.com/hyperlight-dev/hyperlight"&gt;Hyperlight&lt;/a&gt;. Каждый вызов &lt;code&gt;execute_code&lt;/code&gt; получает собственную свежесозданную микро-VM. Запуск измеряется в миллисекундах. Изоляция практически бесплатна.&lt;/p&gt;
&lt;p&gt;Ваши инструменты продолжают работать на хосте. Сгенерированный моделью &lt;em&gt;связующий код&lt;/em&gt; выполняется в песочнице. Это правильное разделение.&lt;/p&gt;
&lt;h2 id="минимальная-настройка"&gt;Минимальная настройка&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;agent_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;agent_framework_hyperlight&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HyperlightCodeActProvider&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Return the current weather for a city.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;temperature_c&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;21.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;conditions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;partly cloudy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;codeact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HyperlightCodeActProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;approval_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;never_require&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CodeActAgent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;You are a helpful assistant.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;context_providers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;codeact&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="когда-использовать-codeact-и-когда-не-стоит"&gt;Когда использовать CodeAct (и когда не стоит)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Используйте CodeAct, когда:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Задача включает много небольших вызовов инструментов (поиск, объединение, вычисления)&lt;/li&gt;
&lt;li&gt;Важны задержка и стоимость токенов&lt;/li&gt;
&lt;li&gt;Нужна надёжная изоляция для кода, генерируемого моделью&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Оставайтесь на традиционном вызове инструментов, когда:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Агент делает лишь один-два вызова за ход&lt;/li&gt;
&lt;li&gt;Каждый вызов имеет побочные эффекты, требующие индивидуального одобрения&lt;/li&gt;
&lt;li&gt;Описания инструментов скудны или неоднозначны&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="попробуйте-сейчас"&gt;Попробуйте сейчас&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install agent-framework-hyperlight --pre
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Читайте &lt;a href="https://devblogs.microsoft.com/agent-framework/codeact-with-hyperlight/"&gt;полную статью в блоге Agent Framework&lt;/a&gt; для углублённого изучения.&lt;/p&gt;</content:encoded></item><item><title>GPT-5.5 Уже Здесь и Приходит в Azure Foundry — Что Нужно Знать .NET-разработчикам</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/gpt-55-foundry-ga-what-dotnet-developers-need-to-know/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/gpt-55-foundry-ga-what-dotnet-developers-need-to-know/</guid><description>GPT-5.5 доступен в Microsoft Foundry для всех. Эволюция от GPT-5 до 5.5, что реально улучшилось и как начать использовать его в своих агентах уже сегодня.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост переведён автоматически. Чтобы просмотреть оригинал, &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/gpt-55-foundry-ga-what-dotnet-developers-need-to-know/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Microsoft только что объявила, что &lt;a href="https://azure.microsoft.com/en-us/blog/openais-gpt-5-5-in-microsoft-foundry-frontier-intelligence-on-an-enterprise-ready-platform/"&gt;GPT-5.5 доступен в Microsoft Foundry&lt;/a&gt;. Если вы создаёте агентов на Azure, это обновление, которого вы ждали.&lt;/p&gt;
&lt;h2 id="эволюция-gpt-5"&gt;Эволюция GPT-5&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GPT-5&lt;/strong&gt;: объединил рассуждение и скорость в единую систему&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPT-5.4&lt;/strong&gt;: более мощное многошаговое рассуждение, ранние агентские возможности для enterprise&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPT-5.5&lt;/strong&gt;: более глубокое рассуждение в длинном контексте, более надёжное агентское выполнение, лучшая эффективность токенов&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="что-реально-изменилось"&gt;Что реально изменилось&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Улучшенное агентное кодирование&lt;/strong&gt;: GPT-5.5 удерживает контекст на больших кодовых базах, диагностирует архитектурные сбои и предвидит требования к тестированию. Модель рассуждает о том, &lt;em&gt;на что ещё&lt;/em&gt; влияет исправление, прежде чем действовать.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Эффективность токенов&lt;/strong&gt;: Выходные данные более высокого качества с меньшим количеством токенов и меньшим числом повторных попыток. Непосредственно снижает стоимость и задержку в производстве.&lt;/p&gt;
&lt;h2 id="цены"&gt;Цены&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Модель&lt;/th&gt;
&lt;th&gt;Входные данные ($/M токенов)&lt;/th&gt;
&lt;th&gt;Кэшированный ввод&lt;/th&gt;
&lt;th&gt;Выходные данные ($/M токенов)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.5&lt;/td&gt;
&lt;td&gt;$5,00&lt;/td&gt;
&lt;td&gt;$0,50&lt;/td&gt;
&lt;td&gt;$30,00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.5 Pro&lt;/td&gt;
&lt;td&gt;$30,00&lt;/td&gt;
&lt;td&gt;$3,00&lt;/td&gt;
&lt;td&gt;$180,00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="почему-важен-foundry"&gt;Почему важен Foundry&lt;/h2&gt;
&lt;p&gt;Foundry Agent Service позволяет определять агентов в YAML или подключать их с Microsoft Agent Framework, GitHub Copilot SDK, LangGraph или OpenAI Agents SDK — и запускать их как изолированных хостированных агентов с постоянной файловой системой, идентичностью Microsoft Entra и тарификацией по принципу scale-to-zero.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aiProjectClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;gpt-5.5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Вы полезный помощник.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;МойАгент&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Смотрите &lt;a href="https://azure.microsoft.com/en-us/blog/openais-gpt-5-5-in-microsoft-foundry-frontier-intelligence-on-an-enterprise-ready-platform/"&gt;полное объявление&lt;/a&gt; для всех подробностей.&lt;/p&gt;</content:encoded></item><item><title>VS Code 1.118: Copilot CLI получает имена сессий, значки модели и TypeScript 7.0 Nightly</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-118-copilot-cli-session-names-model-badge/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-118-copilot-cli-session-names-model-badge/</guid><description>Visual Studio Code 1.118 — сфокусированный релиз с улучшениями Copilot CLI: именование сессий, значки модели, автоматический выбор модели и подключение TypeScript 7.0 Nightly.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Для просмотра оригинала &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-118-copilot-cli-session-names-model-badge/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.visualstudio.com/updates/v1_118"&gt;Visual Studio Code 1.118&lt;/a&gt; — небольшой сфокусированный релиз, в основном с улучшениями Copilot CLI.&lt;/p&gt;
&lt;h2 id="copilot-cli-сессии-получают-настоящие-имена"&gt;Copilot CLI: сессии получают настоящие имена&lt;/h2&gt;
&lt;p&gt;API заголовков сессий SDK Copilot CLI теперь используются как источник истины для имён сессий. Вместо автоматически сгенерированных меток сессии показывают реальное имя из SDK.&lt;/p&gt;
&lt;h2 id="быстрое-переключение-между-сессиями"&gt;Быстрое переключение между сессиями&lt;/h2&gt;
&lt;p&gt;В приложение Agents теперь добавлены &lt;code&gt;Ctrl+1&lt;/code&gt;, &lt;code&gt;Ctrl+2&lt;/code&gt; и т.д. для быстрого переключения между сессиями.&lt;/p&gt;
&lt;h2 id="значки-модели-в-чате"&gt;Значки модели в чате&lt;/h2&gt;
&lt;p&gt;Ответы Copilot CLI в панели чата теперь показывают значок модели — можно с первого взгляда понять, какая модель обработала каждый запрос.&lt;/p&gt;
&lt;h2 id="автоматический-выбор-модели-в-copilot-cli"&gt;Автоматический выбор модели в Copilot CLI&lt;/h2&gt;
&lt;p&gt;Функция автоматического выбора модели теперь работает и в агенте Copilot CLI.&lt;/p&gt;
&lt;h2 id="подключение-typescript-70-nightly"&gt;Подключение TypeScript 7.0 Nightly&lt;/h2&gt;
&lt;p&gt;Теперь можно включить тестирование ночных сборок TypeScript 7.0 прямо из настроек VS Code. TypeScript 7.0 — значительный релиз (&lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-beta/"&gt;бета вышла несколько дней назад&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Смотрите &lt;a href="https://code.visualstudio.com/updates/v1_118"&gt;полные примечания к релизу&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Где Ваш Агент Помнит Вещи? Практическое Руководство по Хранению Истории Чата</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/chat-history-storage-patterns-agent-framework/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/chat-history-storage-patterns-agent-framework/</guid><description>Управляется сервисом или клиентом? Линейная или ветвящаяся? Архитектурное решение, которое определяет, что ваш ИИ-агент реально умеет — с примерами кода на C# и Python.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост переведён автоматически. Чтобы просмотреть оригинал, &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/chat-history-storage-patterns-agent-framework/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;При создании ИИ-агента вы тратите большую часть энергии на модель, инструменты и промпты. Вопрос о том, &lt;em&gt;где хранится история разговора&lt;/em&gt;, кажется деталью реализации — но это одно из важнейших архитектурных решений, которые вам предстоит принять.&lt;/p&gt;
&lt;p&gt;Оно определяет, могут ли пользователи ветвить беседы, отменять ответы, возобновлять сессии после перезапуска и покидают ли ваши данные вашу инфраструктуру. &lt;a href="https://devblogs.microsoft.com/agent-framework/chat-history-storage-patterns-in-microsoft-agent-framework/"&gt;Команда Agent Framework опубликовала глубокий анализ&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="два-основных-паттерна"&gt;Два основных паттерна&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Управляемое сервисом&lt;/strong&gt;: ИИ-сервис хранит состояние разговора. Ваше приложение хранит ссылку, и сервис автоматически включает нужную историю в каждый запрос.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Управляемое клиентом&lt;/strong&gt;: ваше приложение поддерживает полную историю и отправляет нужные сообщения с каждым запросом. Сервис не имеет состояния. Вы контролируете всё.&lt;/p&gt;
&lt;h2 id="как-agent-framework-это-абстрагирует"&gt;Как Agent Framework это абстрагирует&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentSession&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateSessionAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Меня зовут Алиса.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Как меня зовут?&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Меня зовут Алиса.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Как меня зовут?&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="быстрый-справочник-по-поставщикам"&gt;Быстрый справочник по поставщикам&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Поставщик&lt;/th&gt;
&lt;th&gt;Хранилище&lt;/th&gt;
&lt;th&gt;Модель&lt;/th&gt;
&lt;th&gt;Компрессия&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI/Azure Chat Completions&lt;/td&gt;
&lt;td&gt;Клиент&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Вы&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Foundry Agent Service&lt;/td&gt;
&lt;td&gt;Сервис&lt;/td&gt;
&lt;td&gt;Линейная&lt;/td&gt;
&lt;td&gt;Сервис&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Responses API (по умолчанию)&lt;/td&gt;
&lt;td&gt;Сервис&lt;/td&gt;
&lt;td&gt;Ветвящаяся&lt;/td&gt;
&lt;td&gt;Сервис&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic Claude, Ollama&lt;/td&gt;
&lt;td&gt;Клиент&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Вы&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="как-выбрать"&gt;Как выбрать&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Нужны ветвление или «отмена»?&lt;/strong&gt; → Responses API, управляемый сервисом&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Нужен полный контроль над данными?&lt;/strong&gt; → Управляемое клиентом с DB-бэкендом&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Простой чатбот?&lt;/strong&gt; → Линейное, управляемое сервисом, — достаточно&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Читайте &lt;a href="https://devblogs.microsoft.com/agent-framework/chat-history-storage-patterns-in-microsoft-agent-framework/"&gt;полный пост&lt;/a&gt; для полного дерева решений.&lt;/p&gt;</content:encoded></item><item><title>Aspire 13.2: Поддержка Bun, Улучшенные Контейнеры и Меньше Трений при Отладке</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-bun-container-enhancements/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-bun-container-enhancements/</guid><description>Aspire 13.2 добавляет первоклассную поддержку Bun для Vite-приложений, исправляет надёжность Yarn и улучшает контейнеры, делая поведение при локальной разработке более предсказуемым.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/posts/emiliano-montesdeoca/aspire-132-bun-container-enhancements/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Если вы строите .NET-бэкенды с JavaScript-фронтендами в Aspire, 13.2 — это обновление, которое тихо делает ваш день лучше.&lt;/p&gt;
&lt;h2 id="bun-теперь-первоклассный"&gt;Bun теперь первоклассный&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addViteApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;frontend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./frontend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withBun&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Если ваша команда уже использует Bun, Aspire больше не заставляет плыть против течения.&lt;/p&gt;
&lt;h2 id="yarn-стал-надёжнее"&gt;Yarn стал надёжнее&lt;/h2&gt;
&lt;p&gt;Пользователи Yarn получают меньше загадочных сбоев с &lt;code&gt;withYarn()&lt;/code&gt; и &lt;code&gt;addViteApp()&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="улучшения-контейнеров"&gt;Улучшения контейнеров&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ImagePullPolicy.Never&lt;/code&gt; для использования локального образа без обращения к registry. PostgreSQL 18+ с томами данных теперь работает корректно.&lt;/p&gt;
&lt;h2 id="улучшения-отладки"&gt;Улучшения отладки&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;DebuggerDisplayAttribute&lt;/code&gt; на основных типах, лучшие сообщения об ошибках для &lt;code&gt;WaitFor&lt;/code&gt;, &lt;code&gt;BeforeResourceStartedEvent&lt;/code&gt; срабатывает в нужный момент.&lt;/p&gt;
&lt;p&gt;Оригинальный пост Дэвида Пайна: &lt;a href="https://devblogs.microsoft.com/aspire/aspire-bun-support-and-container-enhancements/"&gt;Aspire 13.2: Bun Support and Container Enhancements&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>68 Минут в День на Переобъяснение Кода? Есть Решение</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/auto-memory-stop-re-explaining-code-to-copilot/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/auto-memory-stop-re-explaining-code-to-copilot/</guid><description>Context rot — это реально: ваш ИИ-агент теряет ориентир после 30 ходов, и вы платите налог на компактизацию каждый час. auto-memory даёт GitHub Copilot CLI хирургическую память без сжигания тысяч токенов.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/posts/emiliano-montesdeoca/auto-memory-stop-re-explaining-code-to-copilot/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Знаете тот момент, когда сессия Copilot достигает &lt;code&gt;/compact&lt;/code&gt; и агент полностью забывает, над чем вы работали? Следующие пять минут вы тратите на повторное объяснение структуры файлов, неудачного теста, трёх подходов, которые уже пробовали. Затем это происходит снова.&lt;/p&gt;
&lt;p&gt;Деси Вильянуэва измерил: &lt;strong&gt;68 минут в день&lt;/strong&gt; — только на переориентацию. Не на написание кода, не на ревью PR. Просто на то, чтобы снова ввести ИИ в курс дела.&lt;/p&gt;
&lt;h2 id="ложь-о-контекстном-окне"&gt;Ложь о Контекстном Окне&lt;/h2&gt;
&lt;p&gt;Реальная математика: из 200K токенов, MCP инструменты съедают ~65K, файлы инструкций ~10K. В итоге &lt;strong&gt;~125K до того, как вы напечатали хоть слово&lt;/strong&gt;. LLM деградируют при 60% заполнении — реальный лимит &lt;strong&gt;45K токенов&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="налог-на-компактизацию"&gt;Налог на Компактизацию&lt;/h2&gt;
&lt;p&gt;Жестокая часть: &lt;strong&gt;память уже существует.&lt;/strong&gt; Copilot CLI записывает каждую сессию в локальную SQLite базу по адресу &lt;code&gt;~/.copilot/session-store.db&lt;/code&gt;. Агент просто не может её прочитать.&lt;/p&gt;
&lt;h2 id="auto-memory-слой-отзыва-не-система-памяти"&gt;auto-memory: Слой Отзыва, Не Система Памяти&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install auto-memory
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;~1900 строк Python. Нулевые зависимости. Устанавливается за 30 секунд.&lt;/p&gt;
&lt;p&gt;Вместо того чтобы заполнять контекст результатами grep, вы даёте агенту хирургический доступ к тому, что реально важно — &lt;strong&gt;50 токенов вместо 10 000&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="заключение"&gt;Заключение&lt;/h2&gt;
&lt;p&gt;Context rot — это реальное архитектурное ограничение. auto-memory обходит его, давая агенту дешёвый и точный механизм отзыва.&lt;/p&gt;
&lt;p&gt;Посмотрите: &lt;a href="https://github.com/dezgit2025/auto-memory"&gt;auto-memory на GitHub&lt;/a&gt;. Оригинальный пост Деси Вильянуэвы: &lt;a href="https://devblogs.microsoft.com/all-things-azure/i-wasted-68-minutes-a-day-re-explaining-my-code-then-i-built-auto-memory/"&gt;I Wasted 68 Minutes a Day&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Foundry Toolboxes: Единый эндпоинт для всех инструментов агентов</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-toolboxes-curate-manage-tools-ai-agents/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-toolboxes-curate-manage-tools-ai-agents/</guid><description>Microsoft Foundry выпустила Toolboxes в Public Preview — способ централизованно управлять инструментами ИИ-агентов и предоставлять их через единый MCP-совместимый эндпоинт.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-toolboxes-curate-manage-tools-ai-agents/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Есть проблема, которая кажется скучной, пока не столкнёшься с ней лично: организация строит несколько ИИ-агентов, каждому нужны инструменты, и каждая команда настраивает их с нуля. Та же интеграция веб-поиска, та же конфигурация Azure AI Search, то же подключение к GitHub MCP-серверу — но в другом репозитории, другой командой, с другими учётными данными и без общего управления.&lt;/p&gt;
&lt;p&gt;Microsoft Foundry только что выпустила &lt;a href="https://devblogs.microsoft.com/foundry/introducing-toolboxes-in-foundry/"&gt;Toolboxes&lt;/a&gt; в Public Preview — прямой ответ на эту проблему.&lt;/p&gt;
&lt;h2 id="что-такое-toolbox"&gt;Что такое Toolbox?&lt;/h2&gt;
&lt;p&gt;Toolbox — это именованный, многократно используемый набор инструментов, который определяется один раз в Foundry и предоставляется через единый MCP-совместимый эндпоинт. Любая среда выполнения агента, говорящая на MCP, может его потреблять — никакой привязки к Foundry Agents.&lt;/p&gt;
&lt;p&gt;Обещание простое: &lt;strong&gt;build once, consume anywhere&lt;/strong&gt;. Определить инструменты, настроить аутентификацию централизованно (OAuth passthrough, управляемые удостоверения Entra), опубликовать эндпоинт. Каждый агент, которому нужны эти инструменты, подключается к эндпоинту и получает их все.&lt;/p&gt;
&lt;h2 id="четыре-столпа-два-доступны-сегодня"&gt;Четыре столпа (два доступны сегодня)&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Столп&lt;/th&gt;
&lt;th&gt;Статус&lt;/th&gt;
&lt;th&gt;Что делает&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Скоро&lt;/td&gt;
&lt;td&gt;Находить одобренные инструменты без ручного поиска&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Build&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Доступен&lt;/td&gt;
&lt;td&gt;Собирать инструменты в многократно используемый bundle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consume&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Доступен&lt;/td&gt;
&lt;td&gt;Единый MCP-эндпоинт предоставляет все инструменты&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Govern&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Скоро&lt;/td&gt;
&lt;td&gt;Централизованная аутентификация + observability для всех вызовов&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="практический-пример"&gt;Практический пример&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.identity&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DefaultAzureCredential&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.projects&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;FOUNDRY_PROJECT_ENDPOINT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;toolbox_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;beta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toolboxes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_toolbox_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;toolbox_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;customer-feedback-triaging-toolbox&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Поиск по документации и ответы на GitHub-issues.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;web_search&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Поиск в публичной документации&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;azure_ai_search&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;index_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;internal-docs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;mcp_server&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;server_url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://your-github-mcp-server.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;После публикации Foundry предоставляет единый эндпоинт. Одно подключение — все инструменты.&lt;/p&gt;
&lt;h2 id="нет-привязки-к-foundry-agents"&gt;Нет привязки к Foundry Agents&lt;/h2&gt;
&lt;p&gt;Toolboxes &lt;strong&gt;создаются и управляются&lt;/strong&gt; в Foundry, но поверхность потребления — открытый протокол MCP. Их можно использовать из кастомных агентов (Microsoft Agent Framework, LangGraph), GitHub Copilot и других MCP-совместимых IDE.&lt;/p&gt;
&lt;h2 id="почему-это-важно-сейчас"&gt;Почему это важно сейчас&lt;/h2&gt;
&lt;p&gt;Волна мульти-агентов добирается до продакшена. Каждый новый агент — это новая поверхность для дублированной конфигурации, устаревших учётных данных и непоследовательного поведения. Основа Build + Consume достаточна, чтобы начать централизацию. Когда придёт столп Govern, появится полностью наблюдаемый, централизованно управляемый инструментальный слой для всего парка агентов.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Пока рано — Public Preview, сначала Python SDK, Discover и Govern ещё впереди. Но модель надёжная, а MCP-нативный дизайн означает, что она работает с инструментами, которые уже строятся. Подробности в &lt;a href="https://devblogs.microsoft.com/foundry/introducing-toolboxes-in-foundry/"&gt;официальном анонсе&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Windows App Dev CLI v0.3: F5 из терминала и UI-автоматизация для агентов</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/windows-app-dev-cli-v03-run-ui-automation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/windows-app-dev-cli-v03-run-ui-automation/</guid><description>Windows App Development CLI v0.3 принес winapp run для отладочного запуска из терминала, winapp ui для автоматизации интерфейса и новый NuGet-пакет, позволяющий dotnet run работать с упакованными приложениями.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Оригинал можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/windows-app-dev-cli-v03-run-ui-automation/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Опыт F5 в Visual Studio великолепен. Но открывать VS только для запуска и отладки упакованного Windows-приложения — это лишнее, особенно в CI-пайплайне, автоматизированном воркфлоу или когда AI-агент прогоняет тесты.&lt;/p&gt;
&lt;p&gt;Windows App Development CLI v0.3 только что &lt;a href="https://devblogs.microsoft.com/ifdef-windows/windows-app-development-cli-v0-3-new-run-and-ui-commands-plus-dotnet-run-support-for-packaged-apps/"&gt;вышел&lt;/a&gt; и решает это напрямую с двумя ключевыми функциями: &lt;code&gt;winapp run&lt;/code&gt; и &lt;code&gt;winapp ui&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="winapp-run-f5-из-любого-места"&gt;winapp run: F5 из любого места&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;winapp run&lt;/code&gt; принимает папку распакованного приложения и манифест, выполняя всё то, что VS делает при отладочном запуске: регистрирует loose-пакет, запускает приложение и сохраняет &lt;code&gt;LocalState&lt;/code&gt; между повторными деплоями.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Собери приложение, затем запусти как упакованное&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winapp run ./bin/Debug
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Работает для WinUI, WPF, WinForms, Console, Avalonia и других. Режимы рассчитаны как на разработчиков, так и на автоматизированные воркфлоу:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--detach&lt;/code&gt;&lt;/strong&gt;: Запускает и немедленно возвращает управление терминалу. Идеально для CI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--unregister-on-exit&lt;/code&gt;&lt;/strong&gt;: Удаляет зарегистрированный пакет при закрытии приложения.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--debug-output&lt;/code&gt;&lt;/strong&gt;: Захватывает сообщения &lt;code&gt;OutputDebugString&lt;/code&gt; и исключения в реальном времени.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="новый-nuget-пакет-dotnet-run-для-упакованных-приложений"&gt;Новый NuGet-пакет: dotnet run для упакованных приложений&lt;/h2&gt;
&lt;p&gt;Для .NET-разработчиков появился новый NuGet-пакет: &lt;code&gt;Microsoft.Windows.SDK.BuildTools.WinApp&lt;/code&gt;. После установки &lt;code&gt;dotnet run&lt;/code&gt; берёт на себя весь inner loop: сборка, подготовка loose-layout-пакета, регистрация в Windows и запуск — всё в один шаг.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winapp init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# или&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet add package Microsoft.Windows.SDK.BuildTools.WinApp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="winapp-ui-ui-автоматизация-из-командной-строки"&gt;winapp ui: UI-автоматизация из командной строки&lt;/h2&gt;
&lt;p&gt;Это функция, открывающая агентные сценарии. &lt;code&gt;winapp ui&lt;/code&gt; предоставляет полный доступ UI Automation к любому запущенному Windows-приложению — WPF, WinForms, Win32, Electron, WinUI3 — прямо из терминала.&lt;/p&gt;
&lt;p&gt;Что можно делать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Перечислить все окна верхнего уровня&lt;/li&gt;
&lt;li&gt;Обходить полное дерево UI Automation любого окна&lt;/li&gt;
&lt;li&gt;Искать элементы по имени, типу или ID автоматизации&lt;/li&gt;
&lt;li&gt;Кликать, вызывать и устанавливать значения&lt;/li&gt;
&lt;li&gt;Делать снимки экрана&lt;/li&gt;
&lt;li&gt;Ждать появления элементов — идеально для синхронизации тестов&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Сочетание &lt;code&gt;winapp ui&lt;/code&gt; с &lt;code&gt;winapp run&lt;/code&gt; создаёт полный воркфлоу build → запуск → проверка из терминала. Агент может запустить приложение, проверить состояние UI, программно взаимодействовать с ним и валидировать результат.&lt;/p&gt;
&lt;h2 id="другие-нововведения"&gt;Другие нововведения&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;winapp unregister&lt;/code&gt;&lt;/strong&gt;: Удаляет sideloaded-пакет после завершения работы.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;winapp manifest add-alias&lt;/code&gt;&lt;/strong&gt;: Добавляет алиас для запуска приложения по имени из терминала.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Автодополнение&lt;/strong&gt;: Одна команда для настройки дополнения в PowerShell.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="как-получить"&gt;Как получить&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winget install Microsoft.WinAppCli
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# или&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g @microsoft/winappcli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CLI находится в публичном превью. Полная документация — в &lt;a href="https://github.com/microsoft/WinAppCli"&gt;репозитории на GitHub&lt;/a&gt;, все подробности — в &lt;a href="https://devblogs.microsoft.com/ifdef-windows/windows-app-development-cli-v0-3-new-run-and-ui-commands-plus-dotnet-run-support-for-packaged-apps/"&gt;оригинальном анонсе&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Хуки azd на Python, TypeScript и .NET: прощай, shell-скрипты</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-hooks-python-javascript-typescript-dotnet/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-hooks-python-javascript-typescript-dotnet/</guid><description>Azure Developer CLI теперь поддерживает хуки на Python, JavaScript, TypeScript и .NET. Больше не нужно переключаться на Bash ради одного скрипта миграции.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-hooks-python-javascript-typescript-dotnet/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Если вы когда-нибудь вели проект полностью на .NET и всё равно писали Bash-скрипты для хуков azd — вы знаете эту боль. Зачем переходить к синтаксису shell в шаге pre-provisioning, когда весь остальной проект написан на C#?&lt;/p&gt;
&lt;p&gt;Эта проблема теперь решена официально. Azure Developer CLI &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-multi-language-hooks/"&gt;выпустила поддержку нескольких языков для хуков&lt;/a&gt;, и это ровно так хорошо, как звучит.&lt;/p&gt;
&lt;h2 id="что-такое-хуки"&gt;Что такое хуки&lt;/h2&gt;
&lt;p&gt;Хуки — это скрипты, выполняемые в ключевых точках жизненного цикла &lt;code&gt;azd&lt;/code&gt; — до провизионинга, после деплоя и не только. Они определяются в &lt;code&gt;azure.yaml&lt;/code&gt; и позволяют внедрять пользовательскую логику без изменений в CLI.&lt;/p&gt;
&lt;p&gt;Раньше поддерживались только Bash и PowerShell. Теперь можно использовать &lt;strong&gt;Python, JavaScript, TypeScript или .NET&lt;/strong&gt; — остальное &lt;code&gt;azd&lt;/code&gt; обрабатывает автоматически.&lt;/p&gt;
&lt;h2 id="как-работает-определение-языка"&gt;Как работает определение языка&lt;/h2&gt;
&lt;p&gt;Просто укажите хук на файл, и &lt;code&gt;azd&lt;/code&gt; определит язык по расширению:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/setup.py&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;postdeploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/seed.ts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;postprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/migrate.cs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Дополнительная конфигурация не нужна. При неоднозначном расширении можно явно указать &lt;code&gt;kind: python&lt;/code&gt; (или нужный язык).&lt;/p&gt;
&lt;h2 id="важные-детали-по-языкам"&gt;Важные детали по языкам&lt;/h2&gt;
&lt;h3 id="python"&gt;Python&lt;/h3&gt;
&lt;p&gt;Разместите &lt;code&gt;requirements.txt&lt;/code&gt; или &lt;code&gt;pyproject.toml&lt;/code&gt; рядом со скриптом (или в родительской директории). &lt;code&gt;azd&lt;/code&gt; автоматически создаёт виртуальное окружение, устанавливает зависимости и запускает скрипт.&lt;/p&gt;
&lt;h3 id="javascript-и-typescript"&gt;JavaScript и TypeScript&lt;/h3&gt;
&lt;p&gt;Тот же принцип — &lt;code&gt;package.json&lt;/code&gt; рядом со скриптом, и &lt;code&gt;azd&lt;/code&gt; сначала выполнит &lt;code&gt;npm install&lt;/code&gt;. Для TypeScript используется &lt;code&gt;npx tsx&lt;/code&gt; без этапа компиляции и без &lt;code&gt;tsconfig.json&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="net"&gt;.NET&lt;/h3&gt;
&lt;p&gt;Два режима:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Режим проекта&lt;/strong&gt;: если рядом со скриптом есть &lt;code&gt;.csproj&lt;/code&gt;, &lt;code&gt;azd&lt;/code&gt; автоматически выполнит &lt;code&gt;dotnet restore&lt;/code&gt; и &lt;code&gt;dotnet build&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single-file режим&lt;/strong&gt;: на .NET 10+ автономные &lt;code&gt;.cs&lt;/code&gt;-файлы запускаются напрямую через &lt;code&gt;dotnet run script.cs&lt;/code&gt;. Файл проекта не нужен.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="конфигурация-по-исполнителю"&gt;Конфигурация по исполнителю&lt;/h2&gt;
&lt;p&gt;Каждый язык поддерживает опциональный блок &lt;code&gt;config&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/setup.ts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;packageManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pnpm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;postprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/migrate.cs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Release&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;net10.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="почему-это-важно-для-net-разработчиков"&gt;Почему это важно для .NET-разработчиков&lt;/h2&gt;
&lt;p&gt;Хуки были последним местом в проекте на базе azd, где приходилось менять язык. Теперь весь деплой-пайплайн — от кода приложения до lifecycle-хуков — может жить в одном языке. Можно переиспользовать существующие .NET-утилиты, ссылаться на общие библиотеки и забыть про поддержку shell-скриптов.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Одно из тех изменений, что выглядят незначительными, но убирают много трения из повседневной работы с azd. Поддержка нескольких языков для хуков доступна прямо сейчас — подробная документация в &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-multi-language-hooks/"&gt;официальном посте&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Обновитесь Прямо Сейчас: .NET 10.0.7 Внеплановое Обновление Безопасности (ASP.NET Core Data Protection)</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-10-0-7-oob-security-patch-data-protection/</link><pubDate>Wed, 22 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-10-0-7-oob-security-patch-data-protection/</guid><description>.NET 10.0.7 — внеплановый релиз, исправляющий уязвимость безопасности в Microsoft.AspNetCore.DataProtection: управляемый аутентифицированный шифратор вычислял HMAC над неправильными байтами, что могло привести к повышению привилегий.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был автоматически переведён. Для оригинальной версии &lt;a href="https://thedotnetblog.com/posts/emiliano-montesdeoca/dotnet-10-0-7-oob-security-patch-data-protection/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Это обновление не является опциональным. Если ваше приложение использует &lt;code&gt;Microsoft.AspNetCore.DataProtection&lt;/code&gt;, необходимо обновиться до 10.0.7.&lt;/p&gt;
&lt;h2 id="что-произошло"&gt;Что Произошло&lt;/h2&gt;
&lt;p&gt;После Patch Tuesday релиза &lt;code&gt;.NET 10.0.6&lt;/code&gt; пользователи начали сообщать об ошибках дешифрования. В ходе расследования была обнаружена уязвимость &lt;strong&gt;CVE-2026-40372&lt;/strong&gt;: тег HMAC-валидации вычислялся над &lt;strong&gt;неправильными байтами&lt;/strong&gt;, что могло привести к повышению привилегий.&lt;/p&gt;
&lt;h2 id="как-исправить"&gt;Как Исправить&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet add package Microsoft.AspNetCore.DataProtection --version 10.0.7
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Затем &lt;strong&gt;пересоберите и переразверните&lt;/strong&gt; приложение.&lt;/p&gt;
&lt;p&gt;Оригинальное объявление Рахула Бхандари: &lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-10-0-7-oob-security-update/"&gt;.NET 10.0.7 Out-of-Band Security Update&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>azd + GitHub Copilot: настройка проекта с помощью ИИ и умное исправление ошибок</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-copilot-integration-ai-setup-troubleshooting/</link><pubDate>Tue, 21 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-copilot-integration-ai-setup-troubleshooting/</guid><description>Azure Developer CLI теперь интегрируется с GitHub Copilot для генерации инфраструктуры проекта и устранения ошибок деплоя — прямо из терминала.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Эта статья переведена автоматически. Оригинальную версию на английском можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-copilot-integration-ai-setup-troubleshooting/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Знаком ли вам момент, когда хочешь задеплоить существующее приложение в Azure и смотришь на пустой &lt;code&gt;azure.yaml&lt;/code&gt;, пытаясь вспомнить, какой тип хостинга выбрать для Express API — Container Apps или App Service? Этот момент станет намного короче.&lt;/p&gt;
&lt;p&gt;Azure Developer CLI (&lt;code&gt;azd&lt;/code&gt;) теперь интегрируется с GitHub Copilot двумя практичными способами: AI-ассистированный скаффолдинг проекта при &lt;code&gt;azd init&lt;/code&gt; и интеллектуальное устранение ошибок при сбое деплоя. Обе функции работают полностью в терминале — именно там, где они и должны быть.&lt;/p&gt;
&lt;h2 id="настройка-с-copilot-при-azd-init"&gt;Настройка с Copilot при azd init&lt;/h2&gt;
&lt;p&gt;При запуске &lt;code&gt;azd init&lt;/code&gt; теперь появляется опция &amp;ldquo;Set up with GitHub Copilot (Preview)&amp;rdquo;. Выберите её, и Copilot проанализирует вашу кодовую базу, чтобы сгенерировать &lt;code&gt;azure.yaml&lt;/code&gt;, шаблоны инфраструктуры и Bicep-модули — на основе вашего реального кода.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;azd init
# Выберите: &amp;#34;Set up with GitHub Copilot (Preview)&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Что потребуется:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;azd 1.23.11 или новее&lt;/strong&gt; — проверьте &lt;code&gt;azd version&lt;/code&gt; или обновитесь через &lt;code&gt;azd update&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Активная подписка GitHub Copilot&lt;/strong&gt; (Individual, Business или Enterprise)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub CLI (&lt;code&gt;gh&lt;/code&gt;)&lt;/strong&gt; — &lt;code&gt;azd&lt;/code&gt; запросит вход при необходимости&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Что мне по-настоящему нравится: это работает в обоих направлениях. Строите с нуля? Copilot поможет настроить правильные сервисы Azure с самого начала. Есть существующее приложение, которое давно хотели задеплоить? Направьте на него Copilot — конфигурация будет сгенерирована без необходимости что-либо переструктурировать.&lt;/p&gt;
&lt;h3 id="что-происходит-на-самом-деле"&gt;Что происходит на самом деле&lt;/h3&gt;
&lt;p&gt;Допустим, у вас есть Node.js Express API с зависимостью от PostgreSQL. Вместо того чтобы вручную выбирать между Container Apps и App Service, а затем писать Bicep с нуля, Copilot определит стек и сгенерирует:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;azure.yaml&lt;/code&gt; с правильными настройками &lt;code&gt;language&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt; и &lt;code&gt;build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Bicep-модуль для Azure Container Apps&lt;/li&gt;
&lt;li&gt;Bicep-модуль для Azure Database for PostgreSQL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Перед любыми изменениями выполняются предварительные проверки — убеждается в чистоте рабочей директории git, заранее запрашивает согласие на инструменты MCP-сервера. Ничего не произойдёт без вашего понимания того, что именно изменится.&lt;/p&gt;
&lt;h2 id="устранение-ошибок-с-помощью-copilot"&gt;Устранение ошибок с помощью Copilot&lt;/h2&gt;
&lt;p&gt;Ошибки деплоя неизбежны. Пропущенные параметры, проблемы с правами, недоступность SKU — и сообщение об ошибке редко подсказывает именно то, что нужно: &lt;em&gt;как это исправить&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Без Copilot цикл выглядит так: скопировать ошибку → искать в документации → читать три нерелевантных ответа на Stack Overflow → выполнить команды &lt;code&gt;az&lt;/code&gt; CLI → попробовать снова. С Copilot в &lt;code&gt;azd&lt;/code&gt; этот цикл рушится. При любом сбое команды &lt;code&gt;azd&lt;/code&gt; сразу предлагаются четыре варианта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Explain&lt;/strong&gt; — простое объяснение того, что пошло не так&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guidance&lt;/strong&gt; — пошаговые инструкции по исправлению&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Diagnose and Guide&lt;/strong&gt; — полный анализ + Copilot применяет исправление (с вашего одобрения) + опциональный повтор&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skip&lt;/strong&gt; — разобраться самостоятельно&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ключевой момент: у Copilot уже есть контекст вашего проекта, упавшей команды и деталей ошибки. Его предложения специфичны именно для &lt;em&gt;вашей ситуации&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="настройка-поведения-по-умолчанию"&gt;Настройка поведения по умолчанию&lt;/h3&gt;
&lt;p&gt;Если всегда выбираете одно и то же, пропустите интерактивный запрос:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;azd config set copilot.errorHandling.category troubleshoot
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Значения: &lt;code&gt;explain&lt;/code&gt;, &lt;code&gt;guidance&lt;/code&gt;, &lt;code&gt;troubleshoot&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;skip&lt;/code&gt;. Можно включить автоматическое исправление и повтор:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;azd config set copilot.errorHandling.fix allow
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Вернуться к интерактивному режиму в любой момент:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;azd config unset copilot.errorHandling.category
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="итоги"&gt;Итоги&lt;/h2&gt;
&lt;p&gt;Запустите &lt;code&gt;azd update&lt;/code&gt; для получения последней версии и попробуйте &lt;code&gt;azd init&lt;/code&gt; на следующем проекте. Это именно та интеграция Copilot, которая приносит реальную ценность.&lt;/p&gt;
&lt;p&gt;Читайте &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-copilot-integration/"&gt;оригинальное объявление здесь&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Написание нативных аддонов Node.js на C# с .NET Native AOT</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/nodejs-addons-csharp-native-aot/</link><pubDate>Tue, 21 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/nodejs-addons-csharp-native-aot/</guid><description>Команда C# Dev Kit заменила аддоны Node.js на C++ аналогами на .NET Native AOT — результат чище, безопаснее и требует только .NET SDK.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Эта статья переведена автоматически. Оригинальную версию на английском можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/nodejs-addons-csharp-native-aot/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот сценарий, который мне нравится: команда, работающая над инструментами .NET, имела нативные аддоны Node.js, написанные на C++ и скомпилированные через &lt;code&gt;node-gyp&lt;/code&gt;. Работало. Но для сборки пакета, который никто в команде не трогал напрямую, на каждой машине разработчика требовался Python — причём старая версия Python.&lt;/p&gt;
&lt;p&gt;Поэтому они задали вполне разумный вопрос: SDK .NET уже установлен — зачем вообще писать C++?&lt;/p&gt;
&lt;p&gt;Ответом стал Native AOT, и результат получился действительно элегантным.&lt;/p&gt;
&lt;h2 id="основная-идея"&gt;Основная идея&lt;/h2&gt;
&lt;p&gt;Нативный аддон Node.js — это разделяемая библиотека (&lt;code&gt;.dll&lt;/code&gt; на Windows, &lt;code&gt;.so&lt;/code&gt; на Linux, &lt;code&gt;.dylib&lt;/code&gt; на macOS), которую Node.js может загрузить во время выполнения. Интерфейс называется &lt;a href="https://nodejs.org/api/n-api.html"&gt;N-API&lt;/a&gt; — стабильный, ABI-совместимый C API. N-API не заботится о том, каким языком создана библиотека — только о том, что она экспортирует нужные символы.&lt;/p&gt;
&lt;p&gt;.NET Native AOT может создать именно это. Он компилирует C#-код ahead-of-time в нативную разделяемую библиотеку с произвольными точками входа. В этом весь трюк.&lt;/p&gt;
&lt;h2 id="настройка-проекта"&gt;Настройка проекта&lt;/h2&gt;
&lt;p&gt;Файл проекта минимален:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Microsoft.NET.Sdk&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;net10.0&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;PublishAot&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/PublishAot&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;AllowUnsafeBlocks&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/AllowUnsafeBlocks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;PublishAot&lt;/code&gt; указывает SDK создать разделяемую библиотеку при &lt;code&gt;dotnet publish&lt;/code&gt;. &lt;code&gt;AllowUnsafeBlocks&lt;/code&gt; нужен для N-API interop с указателями на функции и фиксированными буферами.&lt;/p&gt;
&lt;h2 id="экспорт-точки-входа"&gt;Экспорт точки входа&lt;/h2&gt;
&lt;p&gt;Node.js ожидает, что библиотека экспортирует &lt;code&gt;napi_register_module_v1&lt;/code&gt;. В C# это делает &lt;code&gt;[UnmanagedCallersOnly]&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;unsafe&lt;/span&gt; &lt;span class="kd"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistryAddon&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [UnmanagedCallersOnly(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; EntryPoint = &amp;#34;napi_register_module_v1&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; CallConvs = [typeof(CallConvCdecl)]&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;nint&lt;/span&gt; &lt;span class="n"&gt;Init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nint&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nint&lt;/span&gt; &lt;span class="n"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RegisterFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;readStringValue&amp;#34;&lt;/span&gt;&lt;span class="n"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ReadStringValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Несколько моментов стоит отметить: &lt;code&gt;nint&lt;/code&gt; — целое число нативного размера, управляемый эквивалент &lt;code&gt;intptr_t&lt;/code&gt;. Суффикс &lt;code&gt;u8&lt;/code&gt; создаёт &lt;code&gt;ReadOnlySpan&amp;lt;byte&amp;gt;&lt;/code&gt; с UTF-8 строковым литералом, передаваемым прямо в N-API без выделений памяти под кодировку. А &lt;code&gt;[UnmanagedCallersOnly]&lt;/code&gt; экспортирует метод с точно тем именем точки входа, которое ищет Node.js.&lt;/p&gt;
&lt;h2 id="разрешение-n-api-через-хост-процесс"&gt;Разрешение N-API через хост-процесс&lt;/h2&gt;
&lt;p&gt;Функции N-API экспортирует сам &lt;code&gt;node.exe&lt;/code&gt;, а не отдельная библиотека. Поэтому вместо линковки против чего-либо, они разрешаются против запущенного процесса при старте:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;NativeLibrary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetDllImportResolver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reflection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetExecutingAssembly&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ResolveDllImport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;nint&lt;/span&gt; &lt;span class="n"&gt;ResolveDllImport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;libraryName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt; &lt;span class="n"&gt;assembly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DllImportSearchPath&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;searchPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libraryName&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;node&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;NativeLibrary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetMainProgramHandle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;После этого объявления P/Invoke с &lt;code&gt;[LibraryImport]&lt;/code&gt; и сгенерированным маршалингом работают корректно.&lt;/p&gt;
&lt;h2 id="реальная-экспортируемая-функция"&gt;Реальная экспортируемая функция&lt;/h2&gt;
&lt;p&gt;Вот ридер реестра, который они написали:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)]&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;nint&lt;/span&gt; &lt;span class="n"&gt;ReadStringValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nint&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nint&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;keyPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetStringArg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;valueName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetStringArg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyPath&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;valueName&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ThrowError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Expected two string arguments: keyPath, valueName&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenSubKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valueName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;CreateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GetUndefined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ThrowError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$&amp;#34;Registry read failed: {ex.Message}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Важное замечание про &lt;code&gt;try/catch&lt;/code&gt;: необработанное исключение в методе &lt;code&gt;[UnmanagedCallersOnly]&lt;/code&gt; обрушит хост-процесс. Всегда перехватывайте и передавайте в JavaScript через &lt;code&gt;ThrowError&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="вызов-из-typescript"&gt;Вызов из TypeScript&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./native/win32-x64/RegistryAddon.node&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;RegistryAddon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdkPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readStringValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;SOFTWARE\\dotnet\\Setup\\InstalledVersions\\x64\\sdk&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;InstallLocation&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TypeScript → C#, без Python, без C++.&lt;/p&gt;
&lt;h2 id="что-получили"&gt;Что получили&lt;/h2&gt;
&lt;p&gt;Мгновенный выигрыш — опыт контрибьюторов: никакой конкретной версии Python, &lt;code&gt;yarn install&lt;/code&gt; работает только с Node.js и .NET SDK. CI-пайплайны также упростились. Производительность сопоставима с реализацией на C++.&lt;/p&gt;
&lt;h2 id="итоги"&gt;Итоги&lt;/h2&gt;
&lt;p&gt;Команда C# Dev Kit заменила сложность Python/C++ на чистый C#-код, который каждый в команде уже умеет писать и отлаживать. Полный разбор со всеми вспомогательными методами маршалинга строк найдёте в &lt;a href="https://devblogs.microsoft.com/dotnet/writing-nodejs-addons-with-dotnet-native-aot/"&gt;оригинальной статье в блоге .NET&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>VS Code 1.117: Агенты получают собственные ветки Git, и я полностью за</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-117-agents-autopilot-worktrees/</link><pubDate>Sun, 19 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-117-agents-autopilot-worktrees/</guid><description>VS Code 1.117 приносит изоляцию worktree для сессий агентов, постоянный режим Autopilot и поддержку субагентов. Агентный рабочий процесс кодирования стал намного реальнее.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-117-agents-autopilot-worktrees/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Грань между «ИИ-ассистентом» и «ИИ-тиммейтом» продолжает стираться. VS Code 1.117 только что вышел, и &lt;a href="https://code.visualstudio.com/updates/v1_117"&gt;полные заметки о релизе&lt;/a&gt; насыщены, но суть ясна: агенты становятся полноценными участниками вашего рабочего процесса разработки.&lt;/p&gt;
&lt;p&gt;Вот что действительно важно.&lt;/p&gt;
&lt;h2 id="режим-autopilot-наконец-запоминает-ваши-настройки"&gt;Режим Autopilot наконец запоминает ваши настройки&lt;/h2&gt;
&lt;p&gt;Раньше приходилось заново включать Autopilot каждый раз при запуске новой сессии. Раздражало. Теперь режим разрешений сохраняется между сессиями, и вы можете настроить значение по умолчанию.&lt;/p&gt;
&lt;p&gt;Agent Host поддерживает три конфигурации сессии:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Default&lt;/strong&gt; — инструменты запрашивают подтверждение перед запуском&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bypass&lt;/strong&gt; — автоматически одобряет всё&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autopilot&lt;/strong&gt; — полностью автономный, сам отвечает на свои вопросы и продолжает работу&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если вы создаёте новый .NET-проект с миграциями, Docker и CI — установите Autopilot один раз и забудьте. Эта настройка сохранится.&lt;/p&gt;
&lt;h2 id="worktree-и-git-изоляция-для-сессий-агентов"&gt;Worktree и git-изоляция для сессий агентов&lt;/h2&gt;
&lt;p&gt;Это главное. Сессии агентов теперь поддерживают полную изоляцию worktree и git. Это значит, что когда агент работает над задачей, он получает собственную ветку и рабочую директорию. Ваша основная ветка остаётся нетронутой.&lt;/p&gt;
&lt;p&gt;Ещё лучше — Copilot CLI генерирует осмысленные имена веток для этих worktree-сессий. Никаких больше &lt;code&gt;agent-session-abc123&lt;/code&gt;. Вы получаете название, которое действительно описывает, чем занимается агент.&lt;/p&gt;
&lt;p&gt;Для .NET-разработчиков, управляющих несколькими feature-ветками или исправляющих баги, пока длительная задача скаффолдинга выполняется, это кардинально меняет ситуацию. Можно поручить агенту создавать API-контроллеры в одном worktree, пока вы отлаживаете проблему в сервисном слое в другом. Никаких конфликтов. Никакого стеширования. Никакого хаоса.&lt;/p&gt;
&lt;h2 id="субагенты-и-команды-агентов"&gt;Субагенты и команды агентов&lt;/h2&gt;
&lt;p&gt;Agent Host Protocol теперь поддерживает субагентов. Агент может запускать других агентов для обработки частей задачи. Считайте это делегированием — ваш главный агент координирует, а специализированные агенты занимаются отдельными частями.&lt;/p&gt;
&lt;p&gt;Это пока на ранней стадии, но потенциал для .NET-рабочих процессов очевиден. Представьте: один агент обрабатывает ваши миграции EF Core, пока другой настраивает интеграционные тесты. Мы ещё не совсем там, но поддержка протокола появляется сейчас — значит, инструменты подтянутся быстро.&lt;/p&gt;
&lt;h2 id="вывод-терминала-автоматически-включается-когда-агенты-отправляют-ввод"&gt;Вывод терминала автоматически включается, когда агенты отправляют ввод&lt;/h2&gt;
&lt;p&gt;Мелочь, но значимая. Когда агент отправляет ввод в терминал, вывод терминала теперь автоматически включается в контекст. Раньше агенту требовался дополнительный ход, чтобы просто прочитать, что произошло.&lt;/p&gt;
&lt;p&gt;Если вы когда-нибудь наблюдали, как агент запускает &lt;code&gt;dotnet build&lt;/code&gt;, терпит неудачу, а потом делает ещё один round-trip, чтобы увидеть ошибку — это трение исчезло. Он видит вывод мгновенно и реагирует.&lt;/p&gt;
&lt;h2 id="приложение-agents-на-macos-обновляется-автоматически"&gt;Приложение Agents на macOS обновляется автоматически&lt;/h2&gt;
&lt;p&gt;Автономное приложение Agents на macOS теперь обновляется самостоятельно. Больше не нужно вручную скачивать новые версии. Оно просто остаётся актуальным.&lt;/p&gt;
&lt;h2 id="мелочи-которые-стоит-знать"&gt;Мелочи, которые стоит знать&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Подсказки package.json&lt;/strong&gt; теперь показывают и установленную версию, и последнюю доступную. Полезно, если вы управляете npm-инструментами наряду с .NET-проектами.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Изображения в комментариях JSDoc&lt;/strong&gt; корректно отображаются в подсказках и автодополнении.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сессии Copilot CLI&lt;/strong&gt; теперь показывают, были ли они созданы в VS Code или извне — удобно, когда переключаетесь между терминалами.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copilot CLI, Claude Code и Gemini CLI&lt;/strong&gt; распознаются как типы оболочек. Редактор знает, что вы запускаете.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;VS Code 1.117 — это не броский набор фич. Это инфраструктура. Изоляция worktree, постоянные разрешения, протоколы субагентов — это строительные блоки для рабочего процесса, в котором агенты выполняют реальные параллельные задачи, не затрагивая ваш код.&lt;/p&gt;
&lt;p&gt;Если вы разрабатываете на .NET и ещё не погрузились в агентный рабочий процесс, честно говоря, сейчас самое время начать.&lt;/p&gt;</content:encoded></item><item><title>Global Azure Spain 2026</title><link>https://thedotnetblog.com/ru/events/global-azure-spain-2026/</link><pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate><guid>https://thedotnetblog.com/ru/events/global-azure-spain-2026/</guid><description>Крупнейшее Azure-мероприятие сообщества в Испании — полный день сессий по Azure, ИИ, данным, безопасности и облачной разработке с 38 спикерами на 3 треках.</description><content:encoded>&lt;p&gt;Global Azure Spain 2026 проходит &lt;strong&gt;18 апреля 2026 года&lt;/strong&gt; в &lt;strong&gt;Kinépolis Diversia&lt;/strong&gt; в Алькобендасе, Мадрид. Это крупнейшее сообщественное Azure-мероприятие в Испании, объединяющее 38 спикеров на 3 параллельных треках: ИИ-агенты, сети Azure, Cosmos DB, Fabric, IoT, безопасность и многое другое.&lt;/p&gt;
&lt;p&gt;Мероприятие проходит с &lt;strong&gt;08:30 до 18:30&lt;/strong&gt; и включает в себя кейноут, кофе-брейки, обед и заключительную сессию вопросов и ответов.&lt;/p&gt;
&lt;h2 id="основные-моменты-программы"&gt;Основные моменты программы&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Domando Agentes de IA&lt;/strong&gt;: управление, инструменты и API с Azure AI Foundry и Azure API Management&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Construyendo agentes con LibreChat en Azure&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How Can I Steal Your Data with Azure Private Endpoints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stop Building APIs. Forge Agents with Azure&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agentic DevOps Meets IoT: Real-Time Systems with Fabric and GitHub Copilot&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El regreso de los tamagotchis!&lt;/strong&gt;: мультиагентные системы в действии&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Foundry Control Plane como plataforma de Agentes global&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rompiendo el perímetro: Zero Trust aplicado en Azure&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="билеты"&gt;Билеты&lt;/h2&gt;
&lt;p&gt;Регистрация — символическое пожертвование. Вся стоимость билета направляется в &lt;strong&gt;Plan International&lt;/strong&gt; на поддержку прав детей и равенства по всему миру. Количество мест ограничено, поэтому бронируйте заранее.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.eventbrite.es/e/entradas-global-azure-spain-2026-en-madrid-1981594189564"&gt;Билеты на Eventbrite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://globalazure.es/"&gt;Сайт мероприятия&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="azure-tour-2026"&gt;Azure Tour 2026&lt;/h2&gt;
&lt;p&gt;Помимо Мадрида, Global Azure Tour 2026 также проходит в &lt;strong&gt;Сарагосе&lt;/strong&gt;, &lt;strong&gt;Тенерифе&lt;/strong&gt; и &lt;strong&gt;Севилье&lt;/strong&gt;.&lt;/p&gt;</content:encoded></item><item><title>RFT в Foundry стал дешевле и умнее — Вот что изменилось</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-fine-tuning-april-2026-rft-graders/</link><pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-fine-tuning-april-2026-rft-graders/</guid><description>Microsoft Foundry выпустил три обновления RFT в этом месяце: глобальное обучение для o4-mini, новые модельные грейдеры GPT-4.1 и руководство по лучшим практикам, которое сэкономит вам часы отладки.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-fine-tuning-april-2026-rft-graders/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы разрабатываете .NET-приложения, которые зависят от дообученных моделей, обновления Foundry этого месяца заслуживают внимания. Reinforcement Fine-Tuning стал более доступным и значительно дешевле.&lt;/p&gt;
&lt;p&gt;Полные подробности — в &lt;a href="https://devblogs.microsoft.com/foundry/whats-new-in-foundry-finetune-april-2026/"&gt;официальном анонсе&lt;/a&gt;, а здесь — практическая выжимка.&lt;/p&gt;
&lt;h2 id="глобальное-обучение-для-o4-mini"&gt;Глобальное обучение для o4-mini&lt;/h2&gt;
&lt;p&gt;o4-mini — это основная модель для задач, требующих рассуждений, и агентных нагрузок. Главная новость: теперь вы можете запускать задачи файнтюнинга из 13+ регионов Azure с более низкими тарифами за токен по сравнению со Standard-обучением. Та же инфраструктура, то же качество, более широкий охват.&lt;/p&gt;
&lt;p&gt;Если ваша команда распределена по разным географиям, это важно. Вы больше не привязаны к нескольким регионам для обучения.&lt;/p&gt;
&lt;p&gt;Вот REST API вызов для запуска глобальной задачи обучения:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -X POST &lt;span class="s2"&gt;&amp;#34;https://&amp;lt;your-resource&amp;gt;.openai.azure.com/openai/fine_tuning/jobs?api-version=2025-04-01-preview&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;api-key: &lt;/span&gt;&lt;span class="nv"&gt;$AZURE_OPENAI_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &lt;span class="s1"&gt;&amp;#39;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;model&amp;#34;: &amp;#34;o4-mini&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;training_file&amp;#34;: &amp;#34;&amp;lt;your-training-file-id&amp;gt;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;method&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;type&amp;#34;: &amp;#34;reinforcement&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;reinforcement&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;grader&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;type&amp;#34;: &amp;#34;string_check&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;name&amp;#34;: &amp;#34;answer-check&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;input&amp;#34;: &amp;#34;{{sample.output_text}}&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;reference&amp;#34;: &amp;#34;{{item.reference_answer}}&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;operation&amp;#34;: &amp;#34;eq&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;hyperparameters&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;n_epochs&amp;#34;: 2,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;compute_multiplier&amp;#34;: 1.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;trainingType&amp;#34;: &amp;#34;globalstandard&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Флаг &lt;code&gt;trainingType: globalstandard&lt;/code&gt; — это ключевое отличие.&lt;/p&gt;
&lt;h2 id="новые-модельные-грейдеры-семейство-gpt-41"&gt;Новые модельные грейдеры: семейство GPT-4.1&lt;/h2&gt;
&lt;p&gt;Грейдеры определяют сигнал вознаграждения, под который оптимизируется ваша модель. До сих пор модельные грейдеры были ограничены небольшим набором моделей. Теперь у вас есть три новых варианта: GPT-4.1, GPT-4.1-mini и GPT-4.1-nano.&lt;/p&gt;
&lt;p&gt;Когда стоит использовать модельные грейдеры вместо детерминированных? Когда вывод вашей задачи открытый, когда вам нужна частичная оценка по нескольким измерениям, или когда вы строите агентные рабочие процессы, где корректность вызовов инструментов зависит от семантического контекста.&lt;/p&gt;
&lt;p&gt;Суть в том, что стратегия уровней практична:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GPT-4.1-nano&lt;/strong&gt; для начальных итераций. Низкая стоимость, быстрые циклы обратной связи.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPT-4.1-mini&lt;/strong&gt; когда ваша рубрика оценки стабильна и нужна более высокая точность.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPT-4.1&lt;/strong&gt; для продакшен-оценки или сложных рубрик, где важно каждое решение по оценке.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Вы даже можете комбинировать типы грейдеров в одной задаче RFT. Используйте string-match для измерения «правильный ответ» и модельный грейдер для оценки качества рассуждений. Честно говоря, именно эта гибкость делает его полезным для реальных нагрузок.&lt;/p&gt;
&lt;h2 id="подводный-камень-формата-данных-rft"&gt;Подводный камень формата данных RFT&lt;/h2&gt;
&lt;p&gt;На этом многие спотыкаются. Формат данных RFT отличается от SFT. Последнее сообщение в каждой строке должно иметь роль User или Developer — не Assistant. Ожидаемый ответ помещается в ключ верхнего уровня, например &lt;code&gt;reference_answer&lt;/code&gt;, на который грейдер ссылается напрямую.&lt;/p&gt;
&lt;p&gt;Если вы занимались supervised fine-tuning и хотите перейти на RFT, вам нужно перестроить обучающие данные. Не пропускайте этот шаг, иначе ваши задачи будут молча завершаться с ошибкой.&lt;/p&gt;
&lt;h2 id="почему-это-важно-для-net-разработчиков"&gt;Почему это важно для .NET-разработчиков&lt;/h2&gt;
&lt;p&gt;Если вы вызываете дообученные модели из .NET-приложений через Azure OpenAI SDK, более дешёвое обучение означает, что вы можете итерировать более агрессивно. Варианты модельных грейдеров означают, что вы можете файнтюнить для нюансированных задач — не только для сценариев точного совпадения. А руководство по лучшим практикам на &lt;a href="https://github.com/microsoft-foundry/fine-tuning/blob/main/Demos/Agentic_RFT_PrivatePreview/RFT_Best_Practice.md"&gt;GitHub&lt;/a&gt; сэкономит вам реальное время отладки.&lt;/p&gt;
&lt;p&gt;Начните с малого. От десяти до ста примеров. Простой грейдер. Проверьте цикл. Затем масштабируйте.&lt;/p&gt;</content:encoded></item><item><title>Ваши AI-эксперименты в Azure сжигают деньги — Вот как это исправить</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/cloud-cost-optimization-ai-workloads-azure/</link><pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/cloud-cost-optimization-ai-workloads-azure/</guid><description>AI-нагрузки в Azure могут быстро стать дорогими. Давайте поговорим о том, что действительно работает для контроля расходов без замедления разработки.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/cloud-cost-optimization-ai-workloads-azure/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы сейчас создаёте приложения на базе ИИ в Azure, вы, вероятно, заметили кое-что: ваш счёт за облако выглядит иначе, чем раньше. Не просто выше — странно. Скачкообразно. Трудно предсказать.&lt;/p&gt;
&lt;p&gt;Microsoft только что опубликовал отличную статью о &lt;a href="https://azure.microsoft.com/en-us/blog/cloud-cost-optimization-principles-that-still-matter/"&gt;принципах оптимизации облачных затрат, которые по-прежнему актуальны&lt;/a&gt;, и, честно говоря, момент не мог быть лучше. Потому что AI-нагрузки изменили правила игры, когда речь идёт о затратах.&lt;/p&gt;
&lt;h2 id="почему-ai-нагрузки--это-другая-история"&gt;Почему AI-нагрузки — это другая история&lt;/h2&gt;
&lt;p&gt;Вот в чём дело. Традиционные .NET-нагрузки относительно предсказуемы. Вы знаете свой уровень App Service, знаете свои SQL DTU, можете довольно точно оценить ежемесячные расходы. AI-нагрузки? Не совсем.&lt;/p&gt;
&lt;p&gt;Вы тестируете несколько моделей, чтобы понять, какая подходит. Вы поднимаете инфраструктуру с GPU для дообучения. Вы делаете API-вызовы к Azure OpenAI, где потребление токенов сильно варьируется в зависимости от длины промпта и поведения пользователей. Каждый эксперимент стоит реальных денег, и вы можете провести десятки, прежде чем найдёте правильный подход.&lt;/p&gt;
&lt;p&gt;Эта непредсказуемость делает оптимизацию затрат критически важной — не как запоздалую мысль, а с первого дня.&lt;/p&gt;
&lt;h2 id="управление-vs-оптимизация--знайте-разницу"&gt;Управление vs. оптимизация — знайте разницу&lt;/h2&gt;
&lt;p&gt;Одно различие из статьи, которое, на мой взгляд, разработчики упускают: есть разница между &lt;em&gt;управлением&lt;/em&gt; затратами и &lt;em&gt;оптимизацией&lt;/em&gt; затрат.&lt;/p&gt;
&lt;p&gt;Управление — это отслеживание и отчётность. Вы настраиваете бюджеты в Azure Cost Management, получаете оповещения, смотрите дашборды. Это базовый минимум.&lt;/p&gt;
&lt;p&gt;Оптимизация — это когда вы действительно принимаете решения. Вам правда нужен этот уровень S3, или S1 справится с вашей нагрузкой? Та постоянно работающая вычислительная инстанция простаивает по выходным? Можно ли использовать спот-инстансы для задач обучения?&lt;/p&gt;
&lt;p&gt;Как .NET-разработчики, мы склонны сосредотачиваться на коде и оставлять решения по инфраструктуре «команде эксплуатации». Но если вы деплоите в Azure, эти решения — тоже ваши решения.&lt;/p&gt;
&lt;h2 id="что-действительно-работает"&gt;Что действительно работает&lt;/h2&gt;
&lt;p&gt;Основываясь на статье и собственном опыте, вот что реально даёт результат:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Знайте, на что и где вы тратите.&lt;/strong&gt; Тегируйте свои ресурсы. Серьёзно. Если вы не можете определить, какой проект или эксперимент поедает ваш бюджет, вы не сможете ничего оптимизировать. Azure Cost Management с правильным тегированием — ваш лучший друг.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Установите ограничения перед экспериментами.&lt;/strong&gt; Используйте Azure Policy для ограничения дорогих SKU в средах dev/test. Установите лимиты расходов на ваши развёртывания Azure OpenAI. Не ждите, пока придёт счёт, чтобы обнаружить, что кто-то оставил GPU-кластер работать на выходных.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Постоянно подбирайте правильный размер.&lt;/strong&gt; Та VM, которую вы выбрали при прототипировании? Она, вероятно, не подходит для продакшена. Azure Advisor даёт рекомендации — реально посмотрите на них. Пересматривайте ежемесячно, а не ежегодно.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Думайте о жизненном цикле.&lt;/strong&gt; Ресурсы разработки должны выключаться. Тестовые среды не должны работать 24/7. Используйте политики автоматического выключения. Для AI-нагрузок в частности рассмотрите бессерверные варианты, где вы платите за выполнение, вместо того чтобы держать вычислительные мощности включёнными.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Измеряйте ценность, а не только стоимость.&lt;/strong&gt; Об этом легко забыть. Модель, которая стоит дороже, но даёт значительно лучшие результаты, может быть правильным выбором. Цель — не тратить меньше всего, а тратить разумно.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Оптимизация облачных затрат — это не разовая уборка. Это привычка. И поскольку AI-нагрузки делают расходы менее предсказуемыми, чем когда-либо, формирование этой привычки на раннем этапе избавит вас от болезненных сюрпризов в будущем.&lt;/p&gt;
&lt;p&gt;Если вы .NET-разработчик, создающий решения на Azure, начните относиться к своему облачному счёту так же, как к своему коду — регулярно ревьюйте, рефакторите, когда становится беспорядочно, и никогда не деплойте, не понимая, во сколько это обойдётся.&lt;/p&gt;</content:encoded></item><item><title>Docker Sandbox позволяет агентам Copilot рефакторить ваш код без риска для машины</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/copilot-docker-sandbox-agentic-refactoring/</link><pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/copilot-docker-sandbox-agentic-refactoring/</guid><description>Docker Sandbox предоставляет агентам GitHub Copilot безопасную микро-ВМ для свободного рефакторинга — без запросов на разрешения, без риска для хоста. Вот почему это меняет всё для масштабной модернизации .NET.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/copilot-docker-sandbox-agentic-refactoring/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы использовали агентный режим Copilot для чего-то большего, чем мелкие правки, вы знаете эту боль. Каждая запись файла, каждая команда в терминале — ещё один запрос на разрешение. А теперь представьте это на 50 проектах. Совсем не весело.&lt;/p&gt;
&lt;p&gt;Команда Azure опубликовала пост о &lt;a href="https://devblogs.microsoft.com/all-things-azure/best-of-both-worlds-for-agentic-refactoring-github-copilot-microvms-via-docker-sandbox/"&gt;Docker Sandbox для агентов GitHub Copilot&lt;/a&gt;, и, честно говоря, это одно из самых практичных улучшений в агентном инструментарии, которое я видел. Система использует микро-ВМ, чтобы дать Copilot полностью изолированную среду, где он может делать всё что угодно — устанавливать пакеты, запускать сборки, выполнять тесты — не затрагивая вашу хост-систему.&lt;/p&gt;
&lt;h2 id="что-docker-sandbox-реально-даёт"&gt;Что Docker Sandbox реально даёт&lt;/h2&gt;
&lt;p&gt;Основная идея проста: запустить легковесную микро-ВМ с полноценным окружением Linux, синхронизировать в неё ваше рабочее пространство и позволить агенту Copilot свободно работать внутри. Когда он закончит, изменения синхронизируются обратно.&lt;/p&gt;
&lt;p&gt;Вот что делает это чем-то большим, чем просто «запустить что-то в контейнере»:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Двусторонняя синхронизация рабочего пространства&lt;/strong&gt; с сохранением абсолютных путей. Структура вашего проекта выглядит идентично внутри песочницы. Никаких ошибок сборки из-за путей.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Приватный Docker-демон&lt;/strong&gt; работает внутри микро-ВМ. Агент может собирать и запускать контейнеры, не монтируя Docker-сокет вашего хоста. Это серьёзное преимущество для безопасности.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP/HTTPS-фильтрующие прокси&lt;/strong&gt; контролируют, к чему агент может обращаться в сети. Вы решаете, какие реестры и эндпоинты разрешены. Атаки на цепочку поставок через вредоносный &lt;code&gt;npm install&lt;/code&gt; внутри песочницы? Заблокированы.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Режим YOLO&lt;/strong&gt; — да, именно так они его называют. Агент работает без запросов на разрешения, потому что буквально не может повредить ваш хост. Каждое деструктивное действие изолировано.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="почему-разработчикам-net-стоит-обратить-внимание"&gt;Почему разработчикам .NET стоит обратить внимание&lt;/h2&gt;
&lt;p&gt;Подумайте о работе по модернизации, с которой сейчас сталкивается так много команд. У вас есть решение на .NET Framework с 30 проектами, и его нужно перенести на .NET 9. Это сотни изменений в файлах — файлы проектов, обновления пространств имён, замена API, миграция NuGet.&lt;/p&gt;
&lt;p&gt;С Docker Sandbox вы можете направить агента Copilot на проект, позволить ему свободно рефакторить внутри микро-ВМ, запустить &lt;code&gt;dotnet build&lt;/code&gt; и &lt;code&gt;dotnet test&lt;/code&gt; для валидации и принять только те изменения, которые реально работают. Никакого риска, что он случайно разрушит вашу локальную среду разработки во время экспериментов.&lt;/p&gt;
&lt;p&gt;В посте также описывается запуск &lt;strong&gt;флота параллельных агентов&lt;/strong&gt; — каждый в своей песочнице — одновременно работающих над разными проектами. Для крупных .NET-решений или микросервисных архитектур это огромная экономия времени. Один агент на сервис, все работают изолированно, все валидируются независимо.&lt;/p&gt;
&lt;h2 id="вопрос-безопасности-имеет-значение"&gt;Вопрос безопасности имеет значение&lt;/h2&gt;
&lt;p&gt;Вот что большинство людей упускает: когда вы позволяете ИИ-агенту выполнять произвольные команды, вы доверяете ему всю вашу машину. Docker Sandbox переворачивает эту модель. Агент получает полную автономию внутри одноразовой среды. Сетевой прокси гарантирует, что он может загружать только из одобренных источников. Ваша хостовая файловая система, Docker-демон и учётные данные остаются нетронутыми.&lt;/p&gt;
&lt;p&gt;Для команд с требованиями комплаенса — а это большинство корпоративных .NET-компаний — это разница между «мы не можем использовать агентный ИИ» и «мы можем внедрить его безопасно».&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Docker Sandbox решает фундаментальное противоречие агентного программирования: агентам нужна свобода, чтобы быть полезными, но свобода на вашей хост-машине опасна. Микро-ВМ дают вам и то, и другое. Если вы планируете масштабный рефакторинг или модернизацию .NET, стоит настроить это прямо сейчас. Сочетание интеллекта Copilot в работе с кодом и безопасной среды выполнения — это именно то, чего ждали продакшн-команды.&lt;/p&gt;</content:encoded></item><item><title>Хватит нянчить терминал: отсоединённый режим Aspire меняет рабочий процесс</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-detached-mode-free-your-terminal/</link><pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-detached-mode-free-your-terminal/</guid><description>Aspire 13.2 позволяет запускать AppHost в фоновом режиме и освобождать терминал. В сочетании с новыми командами CLI и поддержкой агентов это значит больше, чем кажется.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-detached-mode-free-your-terminal/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Каждый раз, когда вы запускаете Aspire AppHost, ваш терминал пропадает. Заблокирован. Занят, пока вы не нажмёте Ctrl+C. Нужно быстро выполнить команду? Откройте ещё одну вкладку. Хотите проверить логи? Ещё одна вкладка. Мелкое неудобство, которое быстро накапливается.&lt;/p&gt;
&lt;p&gt;Aspire 13.2 решает эту проблему. James Newton-King &lt;a href="https://devblogs.microsoft.com/aspire/aspire-detached-mode-and-process-management/"&gt;описал все подробности&lt;/a&gt;, и, честно говоря, это одна из тех фич, которая сразу меняет подход к работе.&lt;/p&gt;
&lt;h2 id="отсоединённый-режим-одна-команда--терминал-свободен"&gt;Отсоединённый режим: одна команда — терминал свободен&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Это сокращение для &lt;code&gt;aspire run --detach&lt;/code&gt;. Ваш AppHost запускается в фоне, и терминал сразу возвращается к вам. Никаких лишних вкладок. Никаких мультиплексоров терминала. Просто ваш промпт, готовый к работе.&lt;/p&gt;
&lt;h2 id="управление-запущенными-процессами"&gt;Управление запущенными процессами&lt;/h2&gt;
&lt;p&gt;Суть в том, что запуск в фоне полезен только тогда, когда вы можете управлять тем, что работает. Aspire 13.2 поставляется с полным набором CLI-команд именно для этого:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# List all running AppHosts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Inspect the state of a specific AppHost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire describe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stream logs from a running AppHost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire logs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stop a specific AppHost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire stop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Это превращает Aspire CLI в полноценный менеджер процессов. Вы можете запускать несколько AppHost, проверять их статус, отслеживать логи и останавливать их — всё из одной сессии терминала.&lt;/p&gt;
&lt;h2 id="сочетание-с-изолированным-режимом"&gt;Сочетание с изолированным режимом&lt;/h2&gt;
&lt;p&gt;Отсоединённый режим естественно сочетается с изолированным. Хотите запустить два экземпляра одного проекта в фоне без конфликтов портов?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire start --isolated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire start --isolated
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Каждый получает случайные порты, отдельные секреты и собственный жизненный цикл. Используйте &lt;code&gt;aspire ps&lt;/code&gt;, чтобы увидеть оба, &lt;code&gt;aspire stop&lt;/code&gt;, чтобы остановить ненужный.&lt;/p&gt;
&lt;h2 id="почему-это-важно-для-агентов-кода"&gt;Почему это важно для агентов кода&lt;/h2&gt;
&lt;p&gt;Вот тут становится по-настоящему интересно. Агент кода, работающий в вашем терминале, теперь может:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Запустить приложение с помощью &lt;code&gt;aspire start&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Запросить его состояние через &lt;code&gt;aspire describe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Проверить логи через &lt;code&gt;aspire logs&lt;/code&gt; для диагностики проблем&lt;/li&gt;
&lt;li&gt;Остановить его командой &lt;code&gt;aspire stop&lt;/code&gt; по завершении&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Всё это без потери сессии терминала. До появления отсоединённого режима агент, запустивший ваш AppHost, блокировал сам себя в собственном терминале. Теперь он может запускать, наблюдать, итерировать и очищать — именно так, как должен работать автономный агент.&lt;/p&gt;
&lt;p&gt;Команда Aspire серьёзно вложилась в это. Запуск &lt;code&gt;aspire agent init&lt;/code&gt; настраивает файл навыков Aspire, который обучает агентов этим командам. Таким образом, инструменты вроде агента кода Copilot могут управлять вашими рабочими нагрузками Aspire из коробки.&lt;/p&gt;
&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;Отсоединённый режим — это улучшение рабочего процесса, замаскированное под простой флаг. Вы перестаёте переключаться между терминалами, агенты перестают блокировать сами себя, а новые CLI-команды дают реальную видимость того, что запущено. Это практично, это чисто, и это делает ежедневный цикл разработки заметно более плавным.&lt;/p&gt;
&lt;p&gt;Прочитайте &lt;a href="https://devblogs.microsoft.com/aspire/aspire-detached-mode-and-process-management/"&gt;полный пост&lt;/a&gt; для всех подробностей и установите Aspire 13.2 командой &lt;code&gt;aspire update --self&lt;/code&gt;.&lt;/p&gt;</content:encoded></item><item><title>Инструменты Azure MCP теперь встроены в Visual Studio 2022 — Расширение не требуется</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-tools-built-into-visual-studio-2022/</link><pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-tools-built-into-visual-studio-2022/</guid><description>Инструменты Azure MCP поставляются как часть рабочей нагрузки разработки Azure в Visual Studio 2022. Более 230 инструментов, 45 сервисов Azure, ноль расширений для установки.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Эта статья была переведена автоматически. Для просмотра оригинала &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-tools-built-into-visual-studio-2022/"&gt;нажмите здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы использовали инструменты Azure MCP в Visual Studio через отдельное расширение, вы знаете этот ритуал — установить VSIX, перезапустить, надеяться, что ничего не сломается, разбираться с несовместимостью версий. Это трение осталось в прошлом.&lt;/p&gt;
&lt;p&gt;Yun Jung Choi &lt;a href="https://devblogs.microsoft.com/visualstudio/azure-mcp-tools-now-ship-built-into-visual-studio-2022-no-extension-required/"&gt;объявила&lt;/a&gt;, что инструменты Azure MCP теперь поставляются непосредственно в составе рабочей нагрузки разработки Azure в Visual Studio 2022. Без расширения. Без VSIX. Без танцев с перезапуском.&lt;/p&gt;
&lt;h2 id="что-это-означает-на-практике"&gt;Что это означает на практике&lt;/h2&gt;
&lt;p&gt;Начиная с Visual Studio 2022 версии 17.14.30, Azure MCP Server включён в рабочую нагрузку разработки Azure. Если эта рабочая нагрузка уже установлена, достаточно включить его в GitHub Copilot Chat — и всё готово.&lt;/p&gt;
&lt;p&gt;Более 230 инструментов для 45 сервисов Azure — доступны прямо из окна чата. Просмотр учётных записей хранилища, развёртывание приложения ASP.NET Core, диагностика проблем App Service, запросы к Log Analytics — всё это без открытия вкладки браузера.&lt;/p&gt;
&lt;h2 id="почему-это-важнее-чем-кажется"&gt;Почему это важнее, чем кажется&lt;/h2&gt;
&lt;p&gt;Вот в чём суть инструментов для разработчиков: каждый лишний шаг — это трение, а трение убивает внедрение. MCP в виде отдельного расширения означал несовместимость версий, ошибки установки и ещё одну вещь, которую нужно поддерживать в актуальном состоянии. Встраивание в рабочую нагрузку означает:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Единый путь обновления&lt;/strong&gt; через Visual Studio Installer&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Никакого расхождения версий&lt;/strong&gt; между расширением и IDE&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Всегда актуально&lt;/strong&gt; — MCP Server обновляется с регулярными релизами VS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для команд, стандартизирующих на Azure, это очень важно. Устанавливаете рабочую нагрузку один раз, включаете инструменты, и они доступны в каждой сессии.&lt;/p&gt;
&lt;h2 id="что-можно-делать-с-помощью-этих-инструментов"&gt;Что можно делать с помощью этих инструментов&lt;/h2&gt;
&lt;p&gt;Инструменты охватывают полный жизненный цикл разработки через Copilot Chat:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Изучать&lt;/strong&gt; — спрашивайте о сервисах Azure, лучших практиках, архитектурных паттернах&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Проектировать и разрабатывать&lt;/strong&gt; — получайте рекомендации по сервисам, настраивайте код приложения&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Развёртывать&lt;/strong&gt; — выделяйте ресурсы и развёртывайте прямо из IDE&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Устранять неполадки&lt;/strong&gt; — запрашивайте логи, проверяйте состояние ресурсов, диагностируйте проблемы в продакшене&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Быстрый пример — введите это в Copilot Chat:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;List my storage accounts in my current subscription.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Copilot вызывает инструменты Azure MCP за кулисами, запрашивает ваши подписки и возвращает отформатированный список с именами, расположениями и SKU. Портал не нужен.&lt;/p&gt;
&lt;h2 id="как-включить"&gt;Как включить&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Обновите Visual Studio 2022 до версии &lt;strong&gt;17.14.30&lt;/strong&gt; или выше&lt;/li&gt;
&lt;li&gt;Убедитесь, что установлена рабочая нагрузка &lt;strong&gt;Azure development&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Откройте GitHub Copilot Chat&lt;/li&gt;
&lt;li&gt;Нажмите кнопку &lt;strong&gt;Select tools&lt;/strong&gt; (значок с двумя гаечными ключами)&lt;/li&gt;
&lt;li&gt;Включите &lt;strong&gt;Azure MCP Server&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Вот и всё. Настройка сохраняется между сессиями.&lt;/p&gt;
&lt;h2 id="одно-замечание"&gt;Одно замечание&lt;/h2&gt;
&lt;p&gt;Инструменты отключены по умолчанию — нужно включить их вручную. И инструменты, специфичные для VS 2026, недоступны в VS 2022. Доступность инструментов также зависит от разрешений вашей подписки Azure, как и в портале.&lt;/p&gt;
&lt;h2 id="общая-картина"&gt;Общая картина&lt;/h2&gt;
&lt;p&gt;Это часть чёткого тренда: MCP становится стандартным способом предоставления облачных инструментов в IDE для разработчиков. Мы уже видели &lt;a href="https://devblogs.microsoft.com/azure-sdk/announcing-azure-mcp-server-2-0-stable-release/"&gt;стабильный релиз Azure MCP Server 2.0&lt;/a&gt; и интеграции MCP в VS Code и других редакторах. Встраивание в систему рабочих нагрузок Visual Studio — естественное развитие.&lt;/p&gt;
&lt;p&gt;Для нас, .NET-разработчиков, которые живут в Visual Studio, это устраняет ещё одну причину переключаться на портал Azure. И честно говоря, чем меньше переключений между вкладками, тем лучше.&lt;/p&gt;</content:encoded></item><item><title>Кластеризация пинов наконец появилась в .NET MAUI Maps — Одно свойство, ноль проблем</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/maui-maps-pin-clustering-finally/</link><pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/maui-maps-pin-clustering-finally/</guid><description>.NET MAUI 11 Preview 3 добавляет нативную кластеризацию пинов в элемент управления Map. Одно свойство, отдельные группы кластеризации и обработка нажатий — всё встроено.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/maui-maps-pin-clustering-finally/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Знаете тот момент, когда загружаешь карту с сотней пинов и всё превращается в нечитаемое пятно? Да, именно так работали .NET MAUI Maps до сих пор. Больше нет.&lt;/p&gt;
&lt;p&gt;David Ortinau &lt;a href="https://devblogs.microsoft.com/dotnet/pin-clustering-in-dotnet-maui-maps/"&gt;только что объявил&lt;/a&gt;, что .NET MAUI 11 Preview 3 поставляется с кластеризацией пинов из коробки на Android и iOS/Mac Catalyst. И лучшая часть — включить её невероятно просто.&lt;/p&gt;
&lt;h2 id="одно-свойство-чтобы-править-всеми"&gt;Одно свойство, чтобы править всеми&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;maps:Map&lt;/span&gt; &lt;span class="na"&gt;IsClusteringEnabled=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вот и всё. Близлежащие пины группируются в кластеры со значком количества. Приближаете — они раскрываются. Отдаляете — сворачиваются. Поведение, которое пользователи ожидают от любой современной карты — и теперь вы получаете его одним свойством.&lt;/p&gt;
&lt;h2 id="независимые-группы-кластеризации"&gt;Независимые группы кластеризации&lt;/h2&gt;
&lt;p&gt;Вот тут становится интересно. Не все пины должны группироваться вместе. Кофейни и парки — это разные вещи, и ваша карта должна это знать.&lt;/p&gt;
&lt;p&gt;Свойство &lt;code&gt;ClusteringIdentifier&lt;/code&gt; позволяет разделять пины на независимые группы:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Pike Place Coffee&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;47.6097&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;122.3331&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ClusteringIdentifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;coffee&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Occidental Square&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;47.6064&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;122.3325&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ClusteringIdentifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;parks&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Пины с одинаковым идентификатором кластеризуются вместе. Разные идентификаторы формируют независимые кластеры, даже если пины расположены рядом. Нет идентификатора? Группа по умолчанию. Чисто и предсказуемо.&lt;/p&gt;
&lt;h2 id="обработка-нажатий-на-кластер"&gt;Обработка нажатий на кластер&lt;/h2&gt;
&lt;p&gt;Когда пользователь нажимает на кластер, вы получаете событие &lt;code&gt;ClusterClicked&lt;/code&gt; со всем необходимым:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClusterClicked&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;$&amp;#34;Cluster ({e.Pins.Count} pins)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Suppress default zoom-to-cluster behavior:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// e.Handled = true;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Аргументы события предоставляют &lt;code&gt;Pins&lt;/code&gt; (пины в кластере), &lt;code&gt;Location&lt;/code&gt; (географический центр) и &lt;code&gt;Handled&lt;/code&gt; (установите в &lt;code&gt;true&lt;/code&gt;, если хотите переопределить стандартное поведение масштабирования). Просто, практично, именно то, что ожидаешь.&lt;/p&gt;
&lt;h2 id="детали-платформ-которые-стоит-знать"&gt;Детали платформ, которые стоит знать&lt;/h2&gt;
&lt;p&gt;На Android кластеризация использует собственный алгоритм на основе сетки, который пересчитывается при изменении масштаба — без внешних зависимостей. На iOS и Mac Catalyst используется нативная поддержка &lt;code&gt;MKClusterAnnotation&lt;/code&gt; из MapKit, что означает плавные, нативные для платформы анимации.&lt;/p&gt;
&lt;p&gt;Это один из тех случаев, когда команда MAUI приняла правильное решение — опираться на платформу там, где это имеет смысл.&lt;/p&gt;
&lt;h2 id="почему-это-важно"&gt;Почему это важно&lt;/h2&gt;
&lt;p&gt;Кластеризация пинов была одной из самых запрашиваемых функций в .NET MAUI (&lt;a href="https://github.com/dotnet/maui/issues/11811"&gt;issue #11811&lt;/a&gt;), и неспроста. Каждое приложение, показывающее местоположения на карте — отслеживание доставки, поиск магазинов, недвижимость — нуждается в этом. Раньше приходилось реализовывать самостоятельно или подключать стороннюю библиотеку. Теперь это встроено.&lt;/p&gt;
&lt;p&gt;Для нас, .NET-разработчиков, создающих кроссплатформенные мобильные приложения, это именно тот тип улучшения качества жизни, который делает MAUI по-настоящему практичным выбором для сценариев с активным использованием карт.&lt;/p&gt;
&lt;h2 id="начинаем"&gt;Начинаем&lt;/h2&gt;
&lt;p&gt;Установите &lt;a href="https://dotnet.microsoft.com/download/dotnet/11.0"&gt;.NET 11 Preview 3&lt;/a&gt; и обновите рабочую нагрузку .NET MAUI. &lt;a href="https://github.com/dotnet/maui-samples/tree/main/10.0/UserInterface/Views/Map/MapDemo/WorkingWithMaps"&gt;Пример Maps&lt;/a&gt; включает новую страницу Clustering, с которой можно поэкспериментировать прямо сейчас.&lt;/p&gt;
&lt;p&gt;Создайте что-нибудь с этим — и дайте вашим картам наконец вздохнуть.&lt;/p&gt;</content:encoded></item><item><title>.NET Апрель 2026 Servicing — Патчи безопасности, которые стоит применить сегодня</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-april-2026-servicing-security-patches/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-april-2026-servicing-security-patches/</guid><description>Сервисное обновление за апрель 2026 исправляет 6 CVE в .NET 10, .NET 9, .NET 8 и .NET Framework — включая две уязвимости удалённого выполнения кода.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальная версия доступна &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-april-2026-servicing-security-patches/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-and-dotnet-framework-april-2026-servicing-updates/"&gt;Сервисные обновления за апрель 2026&lt;/a&gt; для .NET и .NET Framework вышли, и на этот раз в них есть исправления безопасности, которые стоит применить как можно скорее. Исправлено шесть CVE, включая две уязвимости удалённого выполнения кода (RCE).&lt;/p&gt;
&lt;h2 id="что-исправлено"&gt;Что исправлено&lt;/h2&gt;
&lt;p&gt;Краткая сводка:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CVE&lt;/th&gt;
&lt;th&gt;Тип&lt;/th&gt;
&lt;th&gt;Затрагивает&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-26171&lt;/td&gt;
&lt;td&gt;Обход функций безопасности&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8 + .NET Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-32178&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Удалённое выполнение кода&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8 + .NET Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-33116&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Удалённое выполнение кода&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-32203&lt;/td&gt;
&lt;td&gt;Отказ в обслуживании&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8 + .NET Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-23666&lt;/td&gt;
&lt;td&gt;Отказ в обслуживании&lt;/td&gt;
&lt;td&gt;.NET Framework 3.0–4.8.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-32226&lt;/td&gt;
&lt;td&gt;Отказ в обслуживании&lt;/td&gt;
&lt;td&gt;.NET Framework 2.0–4.8.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Две CVE с RCE (CVE-2026-32178 и CVE-2026-33116) затрагивают самый широкий спектр версий .NET и должны быть приоритетом.&lt;/p&gt;
&lt;h2 id="обновлённые-версии"&gt;Обновлённые версии&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;.NET 10&lt;/strong&gt;: 10.0.6&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.NET 9&lt;/strong&gt;: 9.0.15&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;: 8.0.26&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Все доступны через обычные каналы — &lt;a href="https://dotnet.microsoft.com/download/dotnet/10.0"&gt;dotnet.microsoft.com&lt;/a&gt;, образы контейнеров на MCR и менеджеры пакетов Linux.&lt;/p&gt;
&lt;h2 id="что-делать"&gt;Что делать&lt;/h2&gt;
&lt;p&gt;Обновите свои проекты и пайплайны CI/CD до последних версий с патчами. Если вы используете контейнеры, загрузите последние образы. Если вы на .NET Framework, проверьте &lt;a href="https://learn.microsoft.com/dotnet/framework/release-notes/release-notes"&gt;примечания к выпуску .NET Framework&lt;/a&gt; для соответствующих патчей.&lt;/p&gt;
&lt;p&gt;Для тех, кто использует .NET 10 в продакшене (это текущий релиз), обновление до 10.0.6 обязательно. То же касается .NET 9.0.15 и .NET 8.0.26, если вы на этих LTS-версиях. Две уязвимости RCE — это не то, что можно откладывать.&lt;/p&gt;</content:encoded></item><item><title>Aspire 13.2 получает MongoDB EF Core и Azure Data Lake — Две интеграции, которые стоит попробовать</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-mongodb-efcore-data-lake/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-mongodb-efcore-data-lake/</guid><description>Aspire 13.2 добавляет интеграции MongoDB Entity Framework Core и Azure Data Lake Storage с автоматическими проверками работоспособности и обнаружением сервисов без настройки. Вот как они выглядят на практике.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальная версия доступна &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-mongodb-efcore-data-lake/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Aspire 13.2 вышел с &lt;a href="https://devblogs.microsoft.com/aspire/aspire-new-database-integrations/"&gt;двумя новыми интеграциями баз данных&lt;/a&gt;, которые заслуживают внимания: MongoDB Entity Framework Core и Azure Data Lake Storage. Если вы хотели использовать EF Core с MongoDB в приложении Aspire или вам нужно было подключить рабочие нагрузки Data Lake с обнаружением сервисов, этот релиз предоставляет и то, и другое.&lt;/p&gt;
&lt;h2 id="mongodb-встречает-ef-core-в-aspire"&gt;MongoDB встречает EF Core в Aspire&lt;/h2&gt;
&lt;p&gt;Это интеграция, которая радует меня больше всего. Aspire поддерживал MongoDB уже давно, но это всегда был сырой драйвер — никакого EF Core, никакого &lt;code&gt;DbContext&lt;/code&gt;, никаких LINQ-запросов к документам. Теперь вы получаете полноценный EF Core с MongoDB, плюс автоматические проверки работоспособности и обнаружение сервисов от Aspire.&lt;/p&gt;
&lt;p&gt;Настройка следует типичному паттерну Aspire. В вашем AppHost:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mongodb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddMongoDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;mongodb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithDataVolume&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithLifetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ContainerLifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Persistent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;apiService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddProject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApiService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Затем в потребляющем проекте добавьте интеграцию EF Core:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet add package Aspire.MongoDB.EntityFrameworkCore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;И зарегистрируйте свой &lt;code&gt;DbContext&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddMongoDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;mongodb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;mydb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Дальше — стандартный EF Core. Определяйте сущности, используйте &lt;code&gt;DbContext&lt;/code&gt; как с любым другим провайдером. Интеграция берёт на себя пул соединений, трассировки OpenTelemetry и проверки работоспособности за кулисами.&lt;/p&gt;
&lt;p&gt;Для .NET-разработчиков, которые использовали MongoDB с сырым драйвером и вручную настраивали строки подключения, это приятное улучшение качества жизни. Вы получаете полную абстракцию EF Core, не теряя обнаружение сервисов Aspire.&lt;/p&gt;
&lt;h2 id="azure-data-lake-storage-присоединяется"&gt;Azure Data Lake Storage присоединяется&lt;/h2&gt;
&lt;p&gt;Второе крупное дополнение — &lt;a href="https://aspire.dev/integrations/cloud/azure/azure-storage-datalake/"&gt;интеграция Azure Data Lake Storage (ADLS)&lt;/a&gt;. Если вы строите конвейеры данных, ETL-процессы или аналитические платформы, теперь можно подключать ресурсы Data Lake так же, как любую другую зависимость Aspire.&lt;/p&gt;
&lt;p&gt;В AppHost:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddAzureStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;azure-storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;dataLake&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDataLake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;data-lake&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fileSystem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDataLakeFileSystem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;data-lake-file-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;analyticsService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddProject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AnalyticsService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;analytics&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataLake&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileSystem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;В потребляющем проекте:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddAzureDataLakeServiceClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;data-lake&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddAzureDataLakeFileSystemClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;data-lake-file-system&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Никакого ручного управления строками подключения, никакой охоты за учётными данными. Aspire выделяет ресурсы и внедряет их. Для тех из нас, кто строит облачно-нативные .NET-приложения, работающие как с операционными данными, так и с аналитическими нагрузками, Data Lake теперь ощущается как полноценный участник модели Aspire.&lt;/p&gt;
&lt;h2 id="маленькие-исправления-которые-важны"&gt;Маленькие исправления, которые важны&lt;/h2&gt;
&lt;p&gt;Помимо основных функций, есть несколько улучшений, которые стоит отметить:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Исправление строки подключения MongoDB&lt;/strong&gt; — косая черта перед именем базы данных теперь обрабатывается корректно. Если у вас был обходной путь, можете его убрать&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Экспорт SQL Server&lt;/strong&gt; — &lt;code&gt;Aspire.Hosting.SqlServer&lt;/code&gt; теперь экспортирует дополнительные параметры конфигурации сервера для более тонкого контроля&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Обновления эмуляторов&lt;/strong&gt; — эмулятор ServiceBus 2.0.0, эмулятор App Configuration 1.0.2, предварительный эмулятор CosmosDB теперь включает проверку готовности&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure Managed Redis&lt;/strong&gt; — теперь по умолчанию использует &lt;code&gt;rediss://&lt;/code&gt; (Redis Secure), так что соединения шифруются из коробки&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Последний пункт тонкий, но важный — шифрованный Redis по умолчанию означает на одну настройку меньше в продакшене.&lt;/p&gt;
&lt;h2 id="подводя-итоги"&gt;Подводя итоги&lt;/h2&gt;
&lt;p&gt;Aspire 13.2 — инкрементальный релиз, но интеграции MongoDB EF Core и Data Lake заполняют реальные пробелы. Если вы ждали нормальную поддержку EF Core для MongoDB в Aspire или вам нужен Data Lake как полноценная зависимость, &lt;a href="https://get.aspire.dev"&gt;обновитесь до 13.2&lt;/a&gt; и попробуйте. Команда &lt;code&gt;aspire add&lt;/code&gt; создаст всё необходимое.&lt;/p&gt;
&lt;p&gt;Читайте &lt;a href="https://aspire.dev/whats-new/aspire-13-2/#-integrations-updates"&gt;полные примечания к релизу&lt;/a&gt; для подробностей и загляните в &lt;a href="https://aspire.dev/integrations/gallery/"&gt;галерею интеграций&lt;/a&gt; для полного списка.&lt;/p&gt;</content:encoded></item><item><title>azd update — Одна команда для всех ваших пакетных менеджеров</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-update-universal-upgrade-command/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-update-universal-upgrade-command/</guid><description>Azure Developer CLI теперь имеет универсальную команду обновления, которая работает независимо от способа установки — winget, Homebrew, Chocolatey или скрипт установки.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальная версия доступна &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-update-universal-upgrade-command/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Знаете это сообщение «Доступна новая версия azd», которое появляется каждые несколько недель? То самое, которое вы закрываете, потому что не помните, устанавливали ли вы &lt;code&gt;azd&lt;/code&gt; через winget, Homebrew или тот curl-скрипт, который запустили полгода назад? Так вот, это наконец-то исправлено.&lt;/p&gt;
&lt;p&gt;Microsoft выпустила &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-update/"&gt;&lt;code&gt;azd update&lt;/code&gt;&lt;/a&gt; — единую команду, которая обновляет Azure Developer CLI до последней версии независимо от того, как вы её изначально установили. Windows, macOS, Linux — неважно. Одна команда.&lt;/p&gt;
&lt;h2 id="как-это-работает"&gt;Как это работает&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вот и всё. Если хотите ранний доступ к новым возможностям, можно переключиться на ежедневную Insiders-сборку:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd update --channel daily
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd update --channel stable
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Команда определяет текущий метод установки и использует подходящий механизм обновления под капотом. Больше никаких «подожди, я на этой машине winget или choco использовал?»&lt;/p&gt;
&lt;h2 id="небольшой-нюанс"&gt;Небольшой нюанс&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;azd update&lt;/code&gt; доступна начиная с версии 1.23.x. Если у вас более старая версия, придётся выполнить последнее ручное обновление через исходный метод установки. После этого &lt;code&gt;azd update&lt;/code&gt; берёт всё на себя.&lt;/p&gt;
&lt;p&gt;Проверьте текущую версию командой &lt;code&gt;azd version&lt;/code&gt;. Если нужна чистая установка, &lt;a href="https://learn.microsoft.com/azure/developer/azure-developer-cli/install-azd"&gt;документация по установке&lt;/a&gt; вам поможет.&lt;/p&gt;
&lt;h2 id="почему-это-важно"&gt;Почему это важно&lt;/h2&gt;
&lt;p&gt;Это небольшое улучшение качества жизни, но для тех из нас, кто ежедневно использует &lt;code&gt;azd&lt;/code&gt; для деплоя ИИ-агентов и Aspire-приложений в Azure, быть на последней версии означает меньше моментов «этот баг уже был исправлен в последнем релизе». На одну заботу меньше.&lt;/p&gt;
&lt;p&gt;Читайте &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-update/"&gt;полный анонс&lt;/a&gt; и &lt;a href="https://blog.jongallant.com/2026/04/azd-update"&gt;подробный разбор&lt;/a&gt; Джона Галланта для дополнительного контекста.&lt;/p&gt;</content:encoded></item><item><title>Azure DevOps Server Патч Апрель 2026 — Исправление Завершения PR и Обновления Безопасности</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-server-april-2026-patch/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-server-april-2026-patch/</guid><description>Azure DevOps Server получает Патч 3 с исправлением сбоев завершения PR, улучшенной валидацией при выходе из системы и восстановлением PAT-подключений к GitHub Enterprise Server.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальная версия доступна &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-server-april-2026-patch/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Быстрое уведомление для команд, использующих самостоятельно размещённый Azure DevOps Server: Microsoft выпустила &lt;a href="https://devblogs.microsoft.com/devops/april-patches-for-azure-devops-server/"&gt;Патч 3 за апрель 2026&lt;/a&gt; с тремя целевыми исправлениями.&lt;/p&gt;
&lt;h2 id="что-исправлено"&gt;Что исправлено&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Сбои завершения pull request&lt;/strong&gt; — исключение нулевой ссылки при автоматическом завершении рабочих элементов могло приводить к сбою слияния PR. Если вы сталкивались с случайными ошибками завершения PR, вероятно, это была причина&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Валидация перенаправления при выходе&lt;/strong&gt; — улучшена валидация при выходе из системы для предотвращения потенциально вредоносных перенаправлений. Это исправление безопасности, которое стоит применить как можно скорее&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PAT-подключения к GitHub Enterprise Server&lt;/strong&gt; — создание подключений с помощью Personal Access Token к GitHub Enterprise Server было сломано, теперь восстановлено&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="как-обновить"&gt;Как обновить&lt;/h2&gt;
&lt;p&gt;Скачайте &lt;a href="https://aka.ms/devopsserverpatch3"&gt;Патч 3&lt;/a&gt; и запустите установщик. Чтобы проверить, что патч применён:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;patch-installer&amp;gt;.exe CheckInstall
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Если вы используете Azure DevOps Server на собственных серверах, Microsoft настоятельно рекомендует поддерживать актуальную версию патчей как для безопасности, так и для надёжности. Ознакомьтесь с &lt;a href="https://learn.microsoft.com/azure/devops/server/release-notes/azuredevopsserver?view=azure-devops#azure-devops-server-patch-3-release-date-april-14-2026"&gt;примечаниями к выпуску&lt;/a&gt; для получения полной информации.&lt;/p&gt;</content:encoded></item><item><title>Azure Smart Tier вышел в GA — Автоматическая оптимизация стоимости Blob Storage без правил жизненного цикла</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-smart-tier-blob-storage-ga/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-smart-tier-blob-storage-ga/</guid><description>Smart tier для Azure Blob Storage теперь общедоступен — автоматическое перемещение объектов между уровнями hot, cool и cold на основе реальных паттернов доступа, без правил жизненного цикла.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальная версия доступна &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-smart-tier-blob-storage-ga/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы когда-нибудь тратили время на настройку политик жизненного цикла Azure Blob Storage, а потом наблюдали, как они разваливаются при изменении паттернов доступа, эта статья для вас. Microsoft только что объявил о &lt;a href="https://azure.microsoft.com/en-us/blog/optimize-object-storage-costs-automatically-with-smart-tier-now-generally-available/"&gt;общей доступности smart tier&lt;/a&gt; для Azure Blob и Data Lake Storage — полностью управляемой возможности тиеринга, которая автоматически перемещает объекты между уровнями hot, cool и cold на основе реального использования.&lt;/p&gt;
&lt;h2 id="что-на-самом-деле-делает-smart-tier"&gt;Что на самом деле делает smart tier&lt;/h2&gt;
&lt;p&gt;Концепция проста: smart tier непрерывно оценивает время последнего доступа к каждому объекту в вашем аккаунте хранения. Часто используемые данные остаются в hot, неактивные данные перемещаются в cool через 30 дней, а затем в cold ещё через 60 дней. Когда к данным снова обращаются, они немедленно возвращаются в hot. Цикл начинается заново.&lt;/p&gt;
&lt;p&gt;Никаких правил жизненного цикла для настройки. Никаких прогнозов паттернов доступа. Никакой ручной настройки.&lt;/p&gt;
&lt;p&gt;Во время превью Microsoft сообщил, что &lt;strong&gt;более 50% ёмкости, управляемой smart tier, автоматически переместилось на более холодные уровни&lt;/strong&gt; на основе реальных паттернов доступа. Это существенная экономия для крупных аккаунтов хранения.&lt;/p&gt;
&lt;h2 id="почему-это-важно-для-net-разработчиков"&gt;Почему это важно для .NET-разработчиков&lt;/h2&gt;
&lt;p&gt;Если вы создаёте приложения, генерирующие логи, телеметрию, аналитические данные или любой растущий массив данных — а давайте будем честны, кто этого не делает? — затраты на хранение быстро накапливаются. Традиционный подход заключался в написании политик управления жизненным циклом, их тестировании, а затем перенастройке при изменении паттернов доступа вашего приложения. Smart tier полностью устраняет этот рабочий процесс.&lt;/p&gt;
&lt;p&gt;Несколько практических сценариев, где это помогает:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Телеметрия и логи приложений&lt;/strong&gt; — hot при отладке, почти не используются через несколько недель&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Конвейеры данных и выходные данные ETL&lt;/strong&gt; — интенсивно используются во время обработки, затем в основном cold&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Контент, создаваемый пользователями&lt;/strong&gt; — недавние загрузки hot, старый контент постепенно остывает&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Данные резервного копирования и архивирования&lt;/strong&gt; — иногда используются для соответствия требованиям, в основном простаивают&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="настройка"&gt;Настройка&lt;/h2&gt;
&lt;p&gt;Включение smart tier — это однократная настройка:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Новые аккаунты&lt;/strong&gt;: Выберите smart tier как уровень доступа по умолчанию при создании аккаунта хранения (требуется зональная избыточность)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Существующие аккаунты&lt;/strong&gt;: Переключите уровень доступа blob с текущего значения по умолчанию на smart tier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Объекты размером менее 128 КиБ остаются в hot и не облагаются платой за мониторинг. Для всего остального вы платите стандартные тарифы hot/cool/cold без платы за переход между уровнями, без штрафов за раннее удаление и без стоимости извлечения данных. Ежемесячная плата за мониторинг на объект покрывает оркестрацию.&lt;/p&gt;
&lt;h2 id="компромисс-о-котором-стоит-знать"&gt;Компромисс, о котором стоит знать&lt;/h2&gt;
&lt;p&gt;Правила тиеринга smart tier фиксированы (30 дней → cool, 90 дней → cold). Если вам нужны пользовательские пороги — например, перемещение в cool через 7 дней для конкретной рабочей нагрузки — правила жизненного цикла по-прежнему подходят лучше. И не смешивайте оба подхода: избегайте использования правил жизненного цикла для объектов, управляемых smart tier, так как они могут конфликтовать.&lt;/p&gt;
&lt;h2 id="заключение"&gt;Заключение&lt;/h2&gt;
&lt;p&gt;Это не революция, но решает реальную операционную головную боль. Если вы управляете растущими аккаунтами blob storage и устали поддерживать политики жизненного цикла, &lt;a href="https://learn.microsoft.com/en-us/azure/storage/blobs/access-tiers-smart"&gt;включите smart tier&lt;/a&gt; и позвольте Azure заниматься этим. Доступно уже сегодня практически во всех зональных регионах публичного облака.&lt;/p&gt;</content:encoded></item><item><title>Где размещать AI-агентов в Azure? Практическое руководство по выбору</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-ai-agent-hosting-options-guide/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-ai-agent-hosting-options-guide/</guid><description>Azure предлагает шесть способов размещения AI-агентов — от контейнеров до полностью управляемых Foundry Hosted Agents. Вот как выбрать подходящий вариант для вашей .NET нагрузки.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальная версия доступна &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-ai-agent-hosting-options-guide/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы сейчас создаёте AI-агентов с .NET, вы наверняка заметили: способов разместить их в Azure &lt;em&gt;очень много&lt;/em&gt;. Container Apps, AKS, Functions, App Service, Foundry Agents, Foundry Hosted Agents — и все звучат разумно, пока вам не нужно действительно выбрать один. Microsoft только что опубликовала &lt;a href="https://devblogs.microsoft.com/all-things-azure/hostedagent/"&gt;полное руководство по размещению AI-агентов в Azure&lt;/a&gt;, и я хочу разобрать его с практической точки зрения .NET-разработчика.&lt;/p&gt;
&lt;h2 id="шесть-вариантов-с-первого-взгляда"&gt;Шесть вариантов с первого взгляда&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Вариант&lt;/th&gt;
&lt;th&gt;Лучше всего для&lt;/th&gt;
&lt;th&gt;Вы управляете&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container Apps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Полный контроль контейнеров без сложности K8s&lt;/td&gt;
&lt;td&gt;Наблюдаемость, состояние, жизненный цикл&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AKS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Корпоративный комплаенс, мультикластер, пользовательские сети&lt;/td&gt;
&lt;td&gt;Всем (в этом и суть)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Azure Functions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Событийные краткосрочные задачи агентов&lt;/td&gt;
&lt;td&gt;Почти ничем — настоящий serverless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App Service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Простые HTTP-агенты, предсказуемый трафик&lt;/td&gt;
&lt;td&gt;Развёртывание, настройка масштабирования&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Foundry Agents&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Агенты без кода через портал/SDK&lt;/td&gt;
&lt;td&gt;Почти ничем&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Foundry Hosted Agents&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Агенты с пользовательским фреймворком на управляемой инфраструктуре&lt;/td&gt;
&lt;td&gt;Только ваш код агента&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Первые четыре — это вычисления общего назначения: вы &lt;em&gt;можете&lt;/em&gt; запускать на них агентов, но они не были для этого спроектированы. Последние два — нативные для агентов: они понимают разговоры, вызовы инструментов и жизненные циклы агентов как первоклассные концепции.&lt;/p&gt;
&lt;h2 id="foundry-hosted-agents--оптимальный-выбор-для-net-разработчиков-агентов"&gt;Foundry Hosted Agents — оптимальный выбор для .NET-разработчиков агентов&lt;/h2&gt;
&lt;p&gt;Вот что привлекло моё внимание. Foundry Hosted Agents находятся точно посередине: вы получаете гибкость запуска собственного кода (Semantic Kernel, Agent Framework, LangGraph — что угодно), а платформа управляет инфраструктурой, наблюдаемостью и управлением разговорами.&lt;/p&gt;
&lt;p&gt;Ключевой элемент — &lt;strong&gt;Hosting Adapter&lt;/strong&gt; — тонкий слой абстракции, который соединяет ваш фреймворк агентов с платформой Foundry. Для Microsoft Agent Framework это выглядит так:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.agentserver.agentframework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;from_agent_framework&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ChatAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chat_client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;AzureAIAgentClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;You are a helpful assistant.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;get_local_time&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;from_agent_framework&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Это вся ваша история хостинга. Адаптер обрабатывает трансляцию протоколов, стриминг через server-sent events, историю разговоров и трассировку OpenTelemetry — всё автоматически. Никакого пользовательского middleware, никакой ручной прокладки.&lt;/p&gt;
&lt;h2 id="развёртывание-действительно-простое"&gt;Развёртывание действительно простое&lt;/h2&gt;
&lt;p&gt;Я раньше развёртывал агентов в Container Apps, и это работает, но в итоге вы пишете много связующего кода для управления состоянием и наблюдаемости. С Hosted Agents и &lt;code&gt;azd&lt;/code&gt; развёртывание — это:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Установить расширение AI-агента&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd ext install azure.ai.agents
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Инициализировать из шаблона&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd ai agent init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Собрать, отправить, развернуть — готово&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Эта единственная команда &lt;code&gt;azd up&lt;/code&gt; собирает ваш контейнер, отправляет его в ACR, создаёт проект Foundry, развёртывает endpoints моделей и запускает вашего агента. Пять шагов сжаты в одну команду.&lt;/p&gt;
&lt;h2 id="встроенное-управление-разговорами"&gt;Встроенное управление разговорами&lt;/h2&gt;
&lt;p&gt;Это та часть, которая экономит больше всего времени в продакшене. Вместо создания собственного хранилища состояния разговоров, Hosted Agents обрабатывают это нативно:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Создать постоянный разговор&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;conversation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conversations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Первый ход&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;response1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;extra_body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;agent_reference&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;MyAgent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;agent_reference&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Remember: my favorite number is 42.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Второй ход — контекст сохранён&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;response2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;extra_body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;agent_reference&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;MyAgent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;agent_reference&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Multiply my favorite number by 10.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Никакого Redis. Никакого хранилища сессий Cosmos DB. Никакого middleware для сериализации сообщений. Платформа просто справляется.&lt;/p&gt;
&lt;h2 id="мой-фреймворк-принятия-решений"&gt;Мой фреймворк принятия решений&lt;/h2&gt;
&lt;p&gt;Пройдя все шесть вариантов, вот моя быстрая ментальная модель:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Нужен нулевой уровень инфраструктуры?&lt;/strong&gt; → Foundry Agents (портал/SDK, без контейнеров)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Есть пользовательский код агента, но нужен управляемый хостинг?&lt;/strong&gt; → Foundry Hosted Agents&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Нужны событийные краткосрочные задачи агентов?&lt;/strong&gt; → Azure Functions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Нужен максимальный контроль контейнеров без K8s?&lt;/strong&gt; → Container Apps&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Нужен строгий комплаенс и мультикластер?&lt;/strong&gt; → AKS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Простой HTTP-агент с предсказуемым трафиком?&lt;/strong&gt; → App Service&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Для большинства .NET-разработчиков, работающих с Semantic Kernel или Microsoft Agent Framework, Hosted Agents — вероятно правильная отправная точка. Вы получаете scale-to-zero, встроенный OpenTelemetry, управление разговорами и гибкость фреймворка — без управления Kubernetes или создания собственного стека наблюдаемости.&lt;/p&gt;
&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;Ландшафт хостинга агентов в Azure быстро зреет. Если вы начинаете новый проект AI-агента сегодня, я бы серьёзно рассмотрел Foundry Hosted Agents, прежде чем по привычке тянуться к Container Apps или AKS. Управляемая инфраструктура экономит реальное время, а паттерн hosting adapter позволяет сохранить ваш выбор фреймворка.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/all-things-azure/hostedagent/"&gt;полным руководством Microsoft&lt;/a&gt; и &lt;a href="https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents"&gt;репозиторием Foundry Samples&lt;/a&gt; для рабочих примеров.&lt;/p&gt;</content:encoded></item><item><title>Agent Skills в .NET стали по-настоящему гибкими</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agent-skills-dotnet-three-authoring-patterns/</link><pubDate>Tue, 14 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agent-skills-dotnet-three-authoring-patterns/</guid><description>Microsoft Agent Framework теперь поддерживает три способа создания навыков — файлы, классы и инлайн-код — все компонуются через единый provider. Рассказываю почему это важно и как использовать каждый из них.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Эта статья была переведена автоматически. Оригинал доступен &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agent-skills-dotnet-three-authoring-patterns/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы строили агентов с Microsoft Agent Framework, вам знаком процесс: определяете навыки, подключаете их к provider и позволяете агенту решать, какой вызвать. Новое — это &lt;em&gt;как&lt;/em&gt; вы создаёте эти навыки, и скачок в гибкости значительный.&lt;/p&gt;
&lt;p&gt;Последнее обновление вводит три паттерна создания agent skills: &lt;strong&gt;файловые&lt;/strong&gt;, &lt;strong&gt;классовые&lt;/strong&gt; и &lt;strong&gt;определённые инлайн-кодом&lt;/strong&gt;. Все три подключаются к единому &lt;code&gt;AgentSkillsProviderBuilder&lt;/code&gt;, что означает свободное комбинирование без логики маршрутизации или специального связующего кода. Расскажу о каждом и когда его использовать.&lt;/p&gt;
&lt;h2 id="файловые-навыки-отправная-точка"&gt;Файловые навыки: отправная точка&lt;/h2&gt;
&lt;p&gt;Файловые навыки — это именно то, что звучит: директория на диске с файлом &lt;code&gt;SKILL.md&lt;/code&gt;, опциональными скриптами и справочными документами. Самый прямой способ дать агенту новые возможности:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;skills/
└── onboarding-guide/
├── SKILL.md
├── scripts/
│ └── check-provisioning.py
└── references/
└── onboarding-checklist.md
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Фронтматтер &lt;code&gt;SKILL.md&lt;/code&gt; объявляет имя и описание навыка, а секция инструкций говорит агенту, как использовать скрипты и ссылки:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;name: onboarding-guide
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;description: &amp;gt;-
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Walk new hires through their first-week setup checklist.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## Instructions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;1.&lt;/span&gt; Ask for the employee&amp;#39;s name and start date.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;2.&lt;/span&gt; Run &lt;span class="sb"&gt;`scripts/check-provisioning.py`&lt;/span&gt; to verify accounts.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;3.&lt;/span&gt; Walk through &lt;span class="sb"&gt;`references/onboarding-checklist.md`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;4.&lt;/span&gt; Follow up on incomplete items.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Затем подключаете &lt;code&gt;SubprocessScriptRunner.RunAsync&lt;/code&gt; для выполнения скриптов:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;skillsProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AgentSkillsProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;skills&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SubprocessScriptRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AzureOpenAIClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetResponsesClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ChatClientAgentOptions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;HRAgent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ChatOptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Instructions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;You are a helpful HR assistant.&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AIContextProviders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;skillsProvider&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;deploymentName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Агент автоматически обнаруживает навык и вызывает скрипт провизионирования, когда нужно проверить статус аккаунтов. Чисто и просто.&lt;/p&gt;
&lt;h2 id="классовые-навыки-распространяем-через-nuget"&gt;Классовые навыки: распространяем через NuGet&lt;/h2&gt;
&lt;p&gt;Здесь для команд становится интересно. Классовые навыки наследуют от &lt;code&gt;AgentClassSkill&amp;lt;T&amp;gt;&lt;/code&gt; и используют атрибуты &lt;code&gt;[AgentSkillResource]&lt;/code&gt; и &lt;code&gt;[AgentSkillScript]&lt;/code&gt;, чтобы фреймворк обнаружил всё через рефлексию:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BenefitsEnrollmentSkill&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentClassSkill&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BenefitsEnrollmentSkill&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;override&lt;/span&gt; &lt;span class="n"&gt;AgentSkillFrontmatter&lt;/span&gt; &lt;span class="n"&gt;Frontmatter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;benefits-enrollment&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;Enroll an employee in health, dental, or vision plans.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Instructions&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Read&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;plans&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Confirm&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt; &lt;span class="n"&gt;wants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;enroll&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;complete&lt;/span&gt; &lt;span class="n"&gt;enrollment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [AgentSkillResource(&amp;#34;available-plans&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Description(&amp;#34;Plan options with monthly pricing.&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;AvailablePlans&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;##&lt;/span&gt; &lt;span class="n"&gt;Available&lt;/span&gt; &lt;span class="n"&gt;Plans&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Health&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Basic&lt;/span&gt; &lt;span class="n"&gt;HMO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Premium&lt;/span&gt; &lt;span class="n"&gt;PPO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Dental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Standard&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Enhanced&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Vision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Basic&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [AgentSkillScript(&amp;#34;enroll&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [Description(&amp;#34;Enrolls employee in the specified benefit plan.&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Enroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;planCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HrClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnrollInPlan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;planCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;planCode&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Красота в том, что команда может упаковать это как NuGet-пакет. Добавляете в проект, помещаете в builder, и оно работает рядом с файловыми навыками без координации:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;skillsProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AgentSkillsProviderBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseFileSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;skills&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;BenefitsEnrollmentSkill&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseFileScriptRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SubprocessScriptRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Оба навыка появляются в системном промпте агента. Агент решает, какой использовать, на основе разговора — никакого кода маршрутизации.&lt;/p&gt;
&lt;h2 id="инлайн-навыки-быстрый-мост"&gt;Инлайн-навыки: быстрый мост&lt;/h2&gt;
&lt;p&gt;Знаете тот момент, когда другая команда строит именно тот навык, который вам нужен, но он будет готов только к следующему спринту? &lt;code&gt;AgentInlineSkill&lt;/code&gt; — ваш мост:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;timeOffSkill&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AgentInlineSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;time-off-balance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Calculate remaining vacation and sick days.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Ask&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;employee&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;provided&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="m"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Present&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt; &lt;span class="n"&gt;clearly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;&amp;#34;&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;calculate-balance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;leaveType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;totalDays&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HrDatabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetAnnualAllowance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;leaveType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;daysUsed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HrDatabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetDaysUsed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;leaveType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;totalDays&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;daysUsed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;leaveType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;totalDays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;daysUsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Добавьте в builder так же, как и остальные:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;skillsProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AgentSkillsProviderBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseFileSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;skills&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;BenefitsEnrollmentSkill&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeOffSkill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseFileScriptRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SubprocessScriptRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Когда NuGet-пакет наконец выйдет, замените инлайн-навык на классовую версию. Агент не заметит разницы.&lt;/p&gt;
&lt;p&gt;Но инлайн-навыки не только для мостов. Они также правильный выбор, когда нужно генерировать навыки динамически в рантайме — представьте навык для каждого бизнес-подразделения, загруженный из конфигурации — или когда скрипту нужно захватить локальное состояние, которое не принадлежит DI-контейнеру.&lt;/p&gt;
&lt;h2 id="одобрение-скриптов-человек-в-цикле"&gt;Одобрение скриптов: человек в цикле&lt;/h2&gt;
&lt;p&gt;Для нас, .NET-разработчиков, строящих продакшен-агентов, это та часть, которая по-настоящему разблокирует разговоры о деплое. Некоторые скрипты имеют реальные последствия — записать кого-то на бенефиты, запросить продакшен-инфраструктуру. Включите &lt;code&gt;UseScriptApproval&lt;/code&gt;, и агент делает паузу перед выполнением любого скрипта:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;skillsProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AgentSkillsProviderBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseFileSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;skills&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;BenefitsEnrollmentSkill&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeOffSkill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseFileScriptRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SubprocessScriptRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseScriptApproval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Когда агент хочет выполнить скрипт, он возвращает запрос на одобрение. Ваше приложение собирает решение — одобрить или отклонить — и агент продолжает соответственно. В регулируемых средах это разница между «мы можем это задеплоить» и «юристы сказали нет».&lt;/p&gt;
&lt;h2 id="почему-эта-комбинация-важна"&gt;Почему эта комбинация важна&lt;/h2&gt;
&lt;p&gt;Настоящая сила не в каком-то отдельном паттерне — а в композиции. Вы можете:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Начать с малого&lt;/strong&gt; с файловым навыком, итерировать инструкции и опубликовать без написания C#&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Распространять переиспользуемые навыки&lt;/strong&gt; как NuGet-пакеты, которые другие команды добавляют одной строкой&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Закрывать пробелы&lt;/strong&gt; инлайн-навыками, когда что-то нужно &lt;em&gt;прямо сейчас&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Фильтровать общие директории&lt;/strong&gt; предикатами, чтобы агент загружал только то, что нужно&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Добавить человеческий контроль&lt;/strong&gt; для скриптов, затрагивающих продакшен-системы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Всё это компонуется через &lt;code&gt;AgentSkillsProviderBuilder&lt;/code&gt;. Никакой специальной маршрутизации, никакой условной логики, никаких проверок типа навыка.&lt;/p&gt;
&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;Agent skills в .NET теперь имеют по-настоящему гибкую модель создания. Будь вы соло-разработчик, прототипирующий с файловыми навыками, или корпоративная команда, распространяющая упакованные возможности через NuGet — паттерны подходят. А механизм одобрения скриптов делает решение готовым к продакшену в средах, где нужен человеческий чекпоинт.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/agent-framework/agent-skills-in-net-three-ways-to-author-one-provider-to-run-them/"&gt;оригинальным объявлением&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/agent-framework/agents/skills"&gt;документацией Agent Skills&lt;/a&gt; на Microsoft Learn и &lt;a href="https://github.com/microsoft/agent-framework/tree/main/dotnet/samples/02-agents/AgentSkills"&gt;примерами .NET на GitHub&lt;/a&gt;, чтобы начать.&lt;/p&gt;</content:encoded></item><item><title>Azure MCP Server 2.0 выпущен — Self-Hosted Agentic Cloud Automation здесь</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-server-2-self-hosted-agentic-cloud/</link><pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-server-2-self-hosted-agentic-cloud/</guid><description>Azure MCP Server 2.0 достиг стабильности с self-hosted удалёнными развёртываниями, 276 инструментами в 57 сервисах Azure и enterprise-grade безопасностью — вот что важно для .NET разработчиков, создающих agentic workflows.</description><content:encoded>&lt;p&gt;&lt;em&gt;Эта статья была переведена автоматически. Оригинал доступен &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-mcp-server-2-self-hosted-agentic-cloud/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Если вы в последнее время создавали что-то с MCP и Azure, вы наверняка уже знаете, что локальный опыт работает хорошо. Подключите MCP сервер, позвольте вашему AI агенту общаться с ресурсами Azure, и двигайтесь дальше. Но в момент, когда нужно поделиться этой настройкой с командой? Вот тогда всё становится сложным.&lt;/p&gt;
&lt;p&gt;Больше не нужно. Azure MCP Server &lt;a href="https://devblogs.microsoft.com/azure-sdk/announcing-azure-mcp-server-2-0-stable-release/"&gt;только что достиг стабильности версии 2.0&lt;/a&gt;, и главная фишка — это ровно то, о чём просили enterprise команды: &lt;strong&gt;поддержка self-hosted удалённых MCP серверов&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="что-такое-azure-mcp-server"&gt;Что такое Azure MCP Server?&lt;/h2&gt;
&lt;p&gt;Быстрое напоминание. Azure MCP Server реализует спецификацию &lt;a href="https://modelcontextprotocol.io/docs/getting-started/intro"&gt;Model Context Protocol&lt;/a&gt; и раскрывает возможности Azure в виде структурированных, обнаруживаемых инструментов, которые AI агенты могут вызывать. Думайте об этом как о стандартизированном мосте между вашим агентом и Azure — provisioning, развёртывание, мониторинг, диагностика, всё через один консистентный интерфейс.&lt;/p&gt;
&lt;p&gt;Цифры говорят сами за себя: &lt;strong&gt;276 MCP инструментов в 57 сервисах Azure&lt;/strong&gt;. Это серьёзное покрытие.&lt;/p&gt;
&lt;h2 id="главное-self-hosted-удалённые-развёртывания"&gt;Главное: self-hosted удалённые развёртывания&lt;/h2&gt;
&lt;p&gt;Вот в чём дело. Запуск MCP локально на вашей машине — это нормально для разработки и экспериментов. Но в реальном сценарии с командой вам нужно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Общий доступ для разработчиков и внутренних систем агентов&lt;/li&gt;
&lt;li&gt;Централизованная конфигурация (контекст тенанта, умолчания подписки, телеметрия)&lt;/li&gt;
&lt;li&gt;Enterprise границы сети и политики&lt;/li&gt;
&lt;li&gt;Интеграция в CI/CD pipelines&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Azure MCP Server 2.0 решает все эти проблемы. Вы можете развернуть его как централизованно управляемый внутренний сервис с HTTP-транспортом, правильной аутентификацией и консистентным управлением.&lt;/p&gt;
&lt;p&gt;Для аутентификации у вас есть два хороших варианта:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Managed Identity&lt;/strong&gt; — при работе рядом с &lt;a href="https://aka.ms/azmcp/self-host/foundry"&gt;Microsoft Foundry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;On-Behalf-Of (OBO) flow&lt;/strong&gt; — OpenID Connect делегирование, которое вызывает Azure API, используя контекст вошедшего пользователя&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Этот OBO flow особенно интересен для нас, .NET разработчиков. Это означает, что ваши agentic workflows могут работать с реальными разрешениями пользователя, а не с какой-то чрезмерно привилегированной сервисной учётной записью. Принцип наименьших привилегий, встроенный прямо туда.&lt;/p&gt;
&lt;h2 id="усиление-безопасности"&gt;Усиление безопасности&lt;/h2&gt;
&lt;p&gt;Это не просто выпуск фич — это ещё и выпуск безопасности. Релиз 2.0 добавляет:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Более сильную валидацию endpoints&lt;/li&gt;
&lt;li&gt;Защиту от injection паттернов в инструментах, ориентированных на запросы&lt;/li&gt;
&lt;li&gt;Более жёсткие элементы управления изоляцией для окружений разработки&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если вы собираетесь раскрывать MCP как общий сервис, эти меры защиты имеют большое значение. Большое.&lt;/p&gt;
&lt;h2 id="где-вы-можете-его-использовать"&gt;Где вы можете его использовать?&lt;/h2&gt;
&lt;p&gt;История совместимости клиентов широкая. Azure MCP Server 2.0 работает с:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IDEs&lt;/strong&gt;: VS Code, Visual Studio, IntelliJ, Eclipse, Cursor&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLI agents&lt;/strong&gt;: GitHub Copilot CLI, Claude Code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standalone&lt;/strong&gt;: локальный сервер для простых настроек&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-hosted remote&lt;/strong&gt;: новая звезда версии 2.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Плюс есть поддержка sovereign cloud для Azure US Government и Azure, управляемого 21Vianet, что критично для регулируемых развёртываний.&lt;/p&gt;
&lt;h2 id="почему-это-важно-для-net-разработчиков"&gt;Почему это важно для .NET разработчиков&lt;/h2&gt;
&lt;p&gt;Если вы создаёте agentic приложения с .NET — будь то Semantic Kernel, Microsoft Agent Framework или ваша собственная оркестровка — Azure MCP Server 2.0 даёт вам production-ready способ дать вашим агентам взаимодействовать с инфраструктурой Azure. Нет пользовательских REST обёрток. Нет сервис-специфичных паттернов интеграции. Просто MCP.&lt;/p&gt;
&lt;p&gt;Вместе с &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;fluent API для MCP Apps&lt;/a&gt;, который вышел несколько дней назад, экосистема .NET MCP быстро растёт.&lt;/p&gt;
&lt;h2 id="начало-работы"&gt;Начало работы&lt;/h2&gt;
&lt;p&gt;Выберите свой путь:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aka.ms/azmcp"&gt;GitHub Repo&lt;/a&gt;&lt;/strong&gt; — исходный код, документация, всё&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aka.ms/azmcp/download/docker"&gt;Docker Image&lt;/a&gt;&lt;/strong&gt; — контейнеризованное развёртывание&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aka.ms/azmcp/download/vscode"&gt;VS Code Extension&lt;/a&gt;&lt;/strong&gt; — интеграция IDE&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aka.ms/azmcp/self-host"&gt;Self-hosting guide&lt;/a&gt;&lt;/strong&gt; — главная фишка версии 2.0&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="в-итоге"&gt;В итоге&lt;/h2&gt;
&lt;p&gt;Azure MCP Server 2.0 — это ровно тот вид upgrade инфраструктуры, который не выглядит ослепительно на демо, но всё изменяет на практике. Self-hosted удалённый MCP с правильной аутентификацией, усилением безопасности и поддержкой sovereign cloud означает, что MCP готов для реальных команд, создающих реальные agentic workflows на Azure. Если вы ждали сигнала &amp;ldquo;enterprise-ready&amp;rdquo; — вот он.&lt;/p&gt;</content:encoded></item><item><title>.NET Aspire 13.2 хочет стать лучшим другом вашего ИИ-агента</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-agentic-development-build-run-observe/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-agentic-development-build-run-observe/</guid><description>Aspire 13.2 делает ставку на агентную разработку — структурированный вывод CLI, изолированные запуски, самовосстанавливающиеся среды и полные данные OpenTelemetry, чтобы ваши ИИ-агенты могли по-настоящему строить, запускать и наблюдать за вашими приложениями.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-agentic-development-build-run-observe/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Знаете тот момент, когда ваш ИИ-агент пишет отличный код, вы воодушевляетесь, а потом всё разваливается, когда он пытается это &lt;em&gt;запустить&lt;/em&gt;? Конфликты портов, процессы-призраки, неправильные переменные окружения — внезапно ваш агент сжигает токены на устранение проблем при запуске вместо создания функциональности.&lt;/p&gt;
&lt;p&gt;Команда Aspire только что опубликовала &lt;a href="https://devblogs.microsoft.com/aspire/agentic-dev-aspirations/"&gt;очень продуманный пост&lt;/a&gt; именно об этой проблеме, и их ответ убедителен: Aspire 13.2 спроектирован не только для людей, но и для ИИ-агентов.&lt;/p&gt;
&lt;h2 id="проблема-реальна"&gt;Проблема реальна&lt;/h2&gt;
&lt;p&gt;ИИ-агенты невероятны в написании кода. Но доставка работающего full-stack приложения включает куда больше, чем генерация файлов. Нужно запустить сервисы в правильном порядке, управлять портами, установить переменные окружения, подключить базы данных и получить обратную связь, когда что-то ломается. Сейчас большинство агентов справляется со всем этим методом проб и ошибок — выполняя команды, читая вывод ошибок, пробуя снова.&lt;/p&gt;
&lt;p&gt;Мы нагружаем их Markdown-инструкциями, кастомными навыками и промптами, чтобы направить, но они непредсказуемы, не компилируются и стоят токенов даже для парсинга. Команда Aspire попала в точку с ключевым инсайтом: агентам нужны &lt;strong&gt;компиляторы и структурированные API&lt;/strong&gt;, а не больше Markdown.&lt;/p&gt;
&lt;h2 id="aspire-как-инфраструктура-для-агентов"&gt;Aspire как инфраструктура для агентов&lt;/h2&gt;
&lt;p&gt;Вот что Aspire 13.2 приносит для агентной разработки:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Весь ваш стек в типизированном коде.&lt;/strong&gt; AppHost определяет полную топологию — API, фронтенд, базу данных, кэш — в компилируемом TypeScript или C#:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createBuilder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;./.modules/aspire.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postgres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addPostgres&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;catalog&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addRedis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cache&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addNodeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;src/index.ts&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withHttpEndpoint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PORT&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addViteApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;frontend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./frontend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Агент может прочитать это, чтобы понять топологию приложения, добавить ресурсы, настроить связи и &lt;em&gt;скомпилировать для проверки&lt;/em&gt;. Компилятор сразу скажет, если что-то не так. Никаких догадок, никаких проб и ошибок с конфигами.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Одна команда, чтобы править ими всеми.&lt;/strong&gt; Вместо того чтобы агенты жонглировали &lt;code&gt;docker compose up&lt;/code&gt;, &lt;code&gt;npm run dev&lt;/code&gt; и скриптами запуска баз данных, всё сводится к &lt;code&gt;aspire start&lt;/code&gt;. Все ресурсы запускаются в правильном порядке, на правильных портах, с правильной конфигурацией. Долгоживущие процессы тоже не вешают агента — Aspire управляет ими.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Изолированный режим для параллельных агентов.&lt;/strong&gt; С &lt;code&gt;--isolated&lt;/code&gt; каждый запуск Aspire получает собственные случайные порты и отдельные пользовательские секреты. Несколько агентов работают в git worktrees? Они не столкнутся. Это огромное преимущество для инструментов вроде фоновых агентов VS Code, которые создают параллельные среды.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Глаза агента через телеметрию.&lt;/strong&gt; Вот где становится действительно мощно. Aspire CLI предоставляет полные данные OpenTelemetry во время разработки — трейсы, метрики, структурированные логи. Ваш агент не просто читает вывод консоли и надеется на лучшее. Он может отследить неудавшийся запрос через сервисы, профилировать медленные эндпоинты и точно определить, где что ломается. Это наблюдаемость продакшен-уровня в цикле разработки.&lt;/p&gt;
&lt;h2 id="аналогия-с-бамперами-на-боулинге"&gt;Аналогия с бамперами на боулинге&lt;/h2&gt;
&lt;p&gt;Команда Aspire использует отличную аналогию: думайте об Aspire как о бамперах на дорожке боулинга для ИИ-агентов. Если агент несовершенен (а он таким и будет), бамперы не дают ему закатывать шар в жёлоб. Определение стека предотвращает неправильную конфигурацию, компилятор ловит ошибки, CLI управляет процессами, а телеметрия обеспечивает обратную связь.&lt;/p&gt;
&lt;p&gt;Комбинируйте это с чем-то вроде Playwright CLI, и ваш агент может реально &lt;em&gt;использовать&lt;/em&gt; ваше приложение — кликать по флоу, проверять DOM, видеть поломки в телеметрии, исправлять код, перезапускать и тестировать снова. Построить, запустить, наблюдать, исправить. Это тот автономный цикл разработки, к которому мы стремились.&lt;/p&gt;
&lt;h2 id="начало-работы"&gt;Начало работы&lt;/h2&gt;
&lt;p&gt;Новичок в Aspire? Установите CLI с &lt;a href="https://get.aspire.dev"&gt;get.aspire.dev&lt;/a&gt; и следуйте &lt;a href="https://aspire.dev/get-started/first-app"&gt;руководству по началу работы&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Уже используете Aspire? Выполните &lt;code&gt;aspire update --self&lt;/code&gt; для получения 13.2, затем наведите ваш любимый кодирующий агент на репозиторий. Вы можете удивиться, насколько дальше он продвинется с ограничителями Aspire.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Aspire 13.2 — это уже не просто фреймворк для распределённых приложений — он становится необходимой инфраструктурой для агентов. Структурированные определения стека, запуск одной командой, изолированные параллельные запуски и телеметрия в реальном времени дают ИИ-агентам именно то, что нужно для перехода от написания кода к поставке приложений.&lt;/p&gt;
&lt;p&gt;Читайте &lt;a href="https://devblogs.microsoft.com/aspire/agentic-dev-aspirations/"&gt;полный пост&lt;/a&gt; от команды Aspire со всеми деталями и демо-видео.&lt;/p&gt;</content:encoded></item><item><title>MCP Apps получили Fluent API — Создавайте богатые UI для AI-инструментов на .NET за три шага</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/</guid><description>Новый Fluent API конфигурации для MCP Apps на Azure Functions позволяет превратить любой .NET MCP-инструмент в полноценное приложение с представлениями, разрешениями и CSP-политиками всего в несколько строк кода.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;MCP-инструменты отлично подходят для наделения AI-агентов возможностями. Но что, если вашему инструменту нужно показать что-то пользователю — дашборд, форму, интерактивную визуализацию? Именно для этого и существуют MCP Apps, и теперь их стало намного проще создавать.&lt;/p&gt;
&lt;p&gt;Лилиан Касем из команды Azure SDK &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;представила новый Fluent API конфигурации&lt;/a&gt; для MCP Apps на .NET Azure Functions — это такое улучшение опыта разработчика, что невольно задаёшься вопросом, почему так просто не было всегда.&lt;/p&gt;
&lt;h2 id="что-такое-mcp-apps"&gt;Что такое MCP Apps?&lt;/h2&gt;
&lt;p&gt;MCP Apps расширяют Model Context Protocol, позволяя инструментам нести собственные UI-представления, статические ресурсы и средства управления безопасностью. Вместо простого возврата текста ваш MCP-инструмент может отрисовывать полноценные HTML-интерфейсы — интерактивные дашборды, визуализации данных, формы конфигурации — всё это вызывается AI-агентами и отображается пользователям через MCP-клиенты.&lt;/p&gt;
&lt;p&gt;Проблема была в том, что ручная настройка всего этого требовала глубокого знания спецификации MCP: URI &lt;code&gt;ui://&lt;/code&gt;, специальные MIME-типы, координация метаданных между инструментами и ресурсами. Не сложно, но утомительно.&lt;/p&gt;
&lt;h2 id="fluent-api-за-три-шага"&gt;Fluent API за три шага&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Шаг 1: Определите свою функцию.&lt;/strong&gt; Стандартный MCP-инструмент Azure Functions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;[Function(nameof(HelloApp))]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;HelloApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [McpToolTrigger(&amp;#34;HelloApp&amp;#34;, &amp;#34;A simple MCP App that says hello.&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ToolInvocationContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Hello from app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Шаг 2: Преобразуйте его в MCP App.&lt;/strong&gt; В стартапе вашей программы:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigureMcpTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;HelloApp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsMcpApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;assets/hello-app.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello App&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpAppPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClipboardWrite&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;McpAppPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClipboardRead&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCsp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;csp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowBaseUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.microsoft.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.microsoft.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Шаг 3: Добавьте HTML-представление.&lt;/strong&gt; Создайте &lt;code&gt;assets/hello-app.html&lt;/code&gt; с нужным вам интерфейсом.&lt;/p&gt;
&lt;p&gt;Вот и всё. Fluent API берёт на себя всю сантехнику MCP-протокола — генерирует синтетическую ресурсную функцию, устанавливает правильный MIME-тип и внедряет метаданные, связывающие ваш инструмент с его представлением.&lt;/p&gt;
&lt;h2 id="api-спроектирован-отлично"&gt;API спроектирован отлично&lt;/h2&gt;
&lt;p&gt;Несколько вещей, которые мне особенно нравятся:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Источники представлений гибкие.&lt;/strong&gt; Можно отдавать HTML из файлов на диске или встраивать ресурсы прямо в сборку для автономных развёртываний:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpViewSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;assets/my-view.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpViewSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromEmbeddedResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;MyApp.Resources.view.html&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;CSP компонуемый.&lt;/strong&gt; Вы явно разрешаете источники, необходимые вашему приложению, следуя принципу наименьших привилегий. Вызывайте &lt;code&gt;WithCsp&lt;/code&gt; несколько раз — источники накапливаются:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCsp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;csp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://api.example.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadResourcesFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://cdn.example.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://youtube.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Управление видимостью.&lt;/strong&gt; Можно сделать инструмент видимым только для LLM, только для UI хоста или для обоих. Хотите инструмент, который только отрисовывает UI и не должен вызываться моделью? Легко:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithVisibility&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpVisibility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// UI-only, hidden from the model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="начало-работы"&gt;Начало работы&lt;/h2&gt;
&lt;p&gt;Добавьте превью-пакет:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Mcp --version 1.5.0-preview.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Если вы уже создаёте MCP-инструменты с Azure Functions, это просто обновление пакета. &lt;a href="https://learn.microsoft.com/azure/azure-functions/scenario-mcp-apps?tabs=bash%2Clinux&amp;amp;pivots=programming-language-csharp"&gt;Быстрый старт MCP Apps&lt;/a&gt; — лучшее место для начала, если вы новичок в этой концепции.&lt;/p&gt;
&lt;h2 id="подводя-итоги"&gt;Подводя итоги&lt;/h2&gt;
&lt;p&gt;MCP Apps — одно из самых захватывающих нововведений в пространстве AI-инструментов: инструменты, которые не просто &lt;em&gt;делают что-то&lt;/em&gt;, но могут &lt;em&gt;показывать что-то&lt;/em&gt; пользователям. Fluent API убирает сложность протокола и позволяет сосредоточиться на главном: логике вашего инструмента и его интерфейсе.&lt;/p&gt;
&lt;p&gt;Прочитайте &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;полный пост&lt;/a&gt; для полного справочника по API и примеров.&lt;/p&gt;</content:encoded></item><item><title>Microsoft Foundry Март 2026 — GPT-5.4, Agent Service GA и Обновление SDK, Которое Меняет Всё</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/microsoft-foundry-march-2026-whats-new/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/microsoft-foundry-march-2026-whats-new/</guid><description>Мартовское обновление Microsoft Foundry 2026 года масштабно: Agent Service выходит в GA, GPT-5.4 обеспечивает надёжное рассуждение, SDK azure-ai-projects стабилизируется на всех языках, а Fireworks AI приносит открытые модели в Azure.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/microsoft-foundry-march-2026-whats-new/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ежемесячные посты «Что нового в Microsoft Foundry» обычно представляют собой сочетание инкрементальных улучшений и редких ключевых функций. &lt;a href="https://devblogs.microsoft.com/foundry/whats-new-in-microsoft-foundry-mar-2026/"&gt;Мартовский выпуск 2026 года&lt;/a&gt;? Практически сплошные ключевые функции. Foundry Agent Service выходит в GA, GPT-5.4 выпускается для продакшена, SDK получает крупный стабильный релиз, а Fireworks AI приносит инференс открытых моделей в Azure. Давайте разберём, что важно для .NET-разработчиков.&lt;/p&gt;
&lt;h2 id="foundry-agent-service-готов-к-продакшену"&gt;Foundry Agent Service готов к продакшену&lt;/h2&gt;
&lt;p&gt;Это главная новость. Среда выполнения агентов нового поколения вышла в общую доступность — построена на OpenAI Responses API, совместима на уровне протокола с агентами OpenAI и открыта для моделей от различных поставщиков. Если вы сегодня строите на Responses API, миграция на Foundry добавит корпоративную безопасность, приватную сеть, Entra RBAC, полную трассировку и оценку поверх вашей существующей агентной логики.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.projects&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.projects.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PromptAgentDefinition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;project_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_PROJECT_ENDPOINT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;agent_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-enterprise-agent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;definition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PromptAgentDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_MODEL_DEPLOYMENT_NAME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;You are a helpful assistant.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ключевые дополнения: сквозная приватная сеть, расширение MCP-аутентификации (включая OAuth passthrough), предварительный просмотр Voice Live для голосовых агентов и размещённые агенты в 6 новых регионах.&lt;/p&gt;
&lt;h2 id="gpt-54--надёжность-важнее-чистого-интеллекта"&gt;GPT-5.4 — надёжность важнее чистого интеллекта&lt;/h2&gt;
&lt;p&gt;GPT-5.4 — это не про то, чтобы стать умнее. Это про надёжность. Более сильное рассуждение в длинных взаимодействиях, лучшее следование инструкциям, меньше сбоев в середине рабочего процесса и встроенные возможности использования компьютера. Для продакшен-агентов эта надёжность значит гораздо больше, чем результаты бенчмарков.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Модель&lt;/th&gt;
&lt;th&gt;Цена (за М токенов)&lt;/th&gt;
&lt;th&gt;Лучше всего для&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.4 (≤272K)&lt;/td&gt;
&lt;td&gt;$2.50 / $15 вывод&lt;/td&gt;
&lt;td&gt;Продакшен-агенты, кодирование, документооборот&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.4 Pro&lt;/td&gt;
&lt;td&gt;$30 / $180 вывод&lt;/td&gt;
&lt;td&gt;Глубокий анализ, научное рассуждение&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.4 Mini&lt;/td&gt;
&lt;td&gt;Экономичный&lt;/td&gt;
&lt;td&gt;Классификация, извлечение, лёгкие вызовы инструментов&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Умная стратегия — маршрутизация: GPT-5.4 Mini обрабатывает высоконагруженную работу с низкой задержкой, а GPT-5.4 берёт на себя запросы с интенсивным рассуждением.&lt;/p&gt;
&lt;h2 id="sdk-наконец-стабилен"&gt;SDK наконец стабилен&lt;/h2&gt;
&lt;p&gt;SDK &lt;code&gt;azure-ai-projects&lt;/code&gt; выпустил стабильные релизы на всех языках — Python 2.0.0, JS/TS 2.0.0, Java 2.0.0 и .NET 2.0.0 (1 апреля). Зависимость от &lt;code&gt;azure-ai-agents&lt;/code&gt; исчезла — всё живёт под &lt;code&gt;AIProjectClient&lt;/code&gt;. Установите через &lt;code&gt;pip install azure-ai-projects&lt;/code&gt;, пакет включает &lt;code&gt;openai&lt;/code&gt; и &lt;code&gt;azure-identity&lt;/code&gt; как прямые зависимости.&lt;/p&gt;
&lt;p&gt;Для .NET-разработчиков это означает единый NuGet-пакет для всей поверхности Foundry. Больше никакого жонглирования отдельными SDK для агентов.&lt;/p&gt;
&lt;h2 id="fireworks-ai-приносит-открытые-модели-в-azure"&gt;Fireworks AI приносит открытые модели в Azure&lt;/h2&gt;
&lt;p&gt;Пожалуй, самое архитектурно интересное дополнение: Fireworks AI обрабатывает более 13 триллионов токенов в день при ~180K запросов/секунду, теперь доступен через Foundry. DeepSeek V3.2, gpt-oss-120b, Kimi K2.5 и MiniMax M2.5 при запуске.&lt;/p&gt;
&lt;p&gt;Настоящая история — это &lt;strong&gt;bring-your-own-weights&lt;/strong&gt; — загружайте квантованные или дообученные веса откуда угодно без смены стека обслуживания. Развёртывание через бессерверную модель с оплатой за токен или выделенную пропускную способность.&lt;/p&gt;
&lt;h2 id="другие-важные-моменты"&gt;Другие важные моменты&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Phi-4 Reasoning Vision 15B&lt;/strong&gt; — мультимодальное рассуждение для графиков, диаграмм и макетов документов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evaluations GA&lt;/strong&gt; — готовые оценщики с непрерывным мониторингом продакшена через Azure Monitor&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Priority Processing&lt;/strong&gt; (Preview) — выделенная вычислительная линия для нагрузок, чувствительных к задержке&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Voice Live&lt;/strong&gt; — среда выполнения «голос-к-голосу», подключаемая напрямую к агентам Foundry&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tracing GA&lt;/strong&gt; — сквозная инспекция трассировок агентов с сортировкой и фильтрацией&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Устаревание PromptFlow&lt;/strong&gt; — миграция на Microsoft Framework Workflows к январю 2027&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="заключение"&gt;Заключение&lt;/h2&gt;
&lt;p&gt;Март 2026 — это поворотный момент для Foundry. Agent Service GA, стабильные SDK на всех языках, GPT-5.4 для надёжных продакшен-агентов и инференс открытых моделей через Fireworks AI — платформа готова к серьёзным нагрузкам.&lt;/p&gt;
&lt;p&gt;Прочитайте &lt;a href="https://devblogs.microsoft.com/foundry/whats-new-in-microsoft-foundry-mar-2026/"&gt;полный обзор&lt;/a&gt; и &lt;a href="https://learn.microsoft.com/azure/foundry/quickstarts/get-started-code"&gt;создайте своего первого агента&lt;/a&gt;, чтобы начать.&lt;/p&gt;</content:encoded></item><item><title>SQL MCP Server — Правильный способ дать AI-агентам доступ к базе данных</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/sql-mcp-server-data-api-builder/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/sql-mcp-server-data-api-builder/</guid><description>SQL MCP Server от Data API builder даёт AI-агентам безопасный, детерминированный доступ к базам данных без раскрытия схем и без NL2SQL. RBAC, кеширование, поддержка нескольких баз — всё встроено.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/sql-mcp-server-data-api-builder/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Давайте будем честны: большинство доступных сегодня MCP-серверов для баз данных устрашают. Они берут запрос на естественном языке, генерируют SQL на лету и выполняют его против ваших продакшн-данных. Что может пойти не так? (Всё. Абсолютно всё.)&lt;/p&gt;
&lt;p&gt;Команда Azure SQL только что &lt;a href="https://devblogs.microsoft.com/azure-sql/introducing-sql-mcp-server/"&gt;представила SQL MCP Server&lt;/a&gt;, и он использует принципиально другой подход. Построенный как функция Data API builder (DAB) 2.0, он даёт AI-агентам структурированный, детерминированный доступ к операциям с базой данных — без NL2SQL, без раскрытия вашей схемы и с полным RBAC на каждом шагу.&lt;/p&gt;
&lt;h2 id="почему-не-nl2sql"&gt;Почему не NL2SQL?&lt;/h2&gt;
&lt;p&gt;Это самое интересное проектное решение. Модели недетерминированы, а сложные запросы наиболее склонны порождать тонкие ошибки. Именно те запросы, которые пользователи надеются, что AI сможет сгенерировать, также требуют наибольшей проверки, когда генерируются недетерминированно.&lt;/p&gt;
&lt;p&gt;Вместо этого SQL MCP Server использует подход &lt;strong&gt;NL2DAB&lt;/strong&gt;. Агент работает со слоем абстракции сущностей Data API builder и встроенным конструктором запросов для детерминированной генерации точного, хорошо сформированного T-SQL. Тот же результат для пользователя, но без риска галлюцинированных JOIN или случайного раскрытия данных.&lt;/p&gt;
&lt;h2 id="семь-инструментов-а-не-семьсот"&gt;Семь инструментов, а не семьсот&lt;/h2&gt;
&lt;p&gt;SQL MCP Server предоставляет ровно семь DML-инструментов, независимо от размера базы данных:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;describe_entities&lt;/code&gt; — обнаружение доступных сущностей и операций&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create_record&lt;/code&gt; — вставка строк&lt;/li&gt;
&lt;li&gt;&lt;code&gt;read_records&lt;/code&gt; — запрос таблиц и представлений&lt;/li&gt;
&lt;li&gt;&lt;code&gt;update_record&lt;/code&gt; — изменение строк&lt;/li&gt;
&lt;li&gt;&lt;code&gt;delete_record&lt;/code&gt; — удаление строк&lt;/li&gt;
&lt;li&gt;&lt;code&gt;execute_entity&lt;/code&gt; — выполнение хранимых процедур&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aggregate_records&lt;/code&gt; — запросы агрегации&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это умно, потому что контекстные окна — это пространство для мышления агента. Наводнение их сотнями определений инструментов оставляет меньше места для рассуждений. Семь фиксированных инструментов держат агента сфокусированным на &lt;em&gt;мышлении&lt;/em&gt;, а не на &lt;em&gt;навигации&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Каждый инструмент можно включить или выключить отдельно:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;runtime&amp;#34;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/mcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;dml-tools&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;describe-entities&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;create-record&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;read-records&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;update-record&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;delete-record&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;execute-entity&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;aggregate-records&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="начало-за-три-команды"&gt;Начало за три команды&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dab init &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --database-type mssql &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --connection-string &lt;span class="s2"&gt;&amp;#34;@env(&amp;#39;sql_connection_string&amp;#39;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dab add Customers &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --source dbo.Customers &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --permissions &lt;span class="s2"&gt;&amp;#34;anonymous:*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dab start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Это работающий SQL MCP Server, предоставляющий доступ к вашей таблице Customers. Слой абстракции сущностей позволяет задавать псевдонимы для имён и столбцов, ограничивать поля по ролям и точно контролировать, что видят агенты — не раскрывая внутренних деталей схемы.&lt;/p&gt;
&lt;h2 id="история-безопасности-убедительна"&gt;История безопасности убедительна&lt;/h2&gt;
&lt;p&gt;Здесь зрелость Data API builder окупается:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RBAC на каждом уровне&lt;/strong&gt; — каждая сущность определяет, какие роли могут читать, создавать, обновлять или удалять, и какие поля видны&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Интеграция с Azure Key Vault&lt;/strong&gt; — строки подключения и секреты управляются безопасно&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Microsoft Entra + пользовательский OAuth&lt;/strong&gt; — аутентификация продакшн-уровня&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Content Security Policy&lt;/strong&gt; — агенты взаимодействуют через контролируемый контракт, а не сырой SQL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Абстракция схемы особенно важна. Внутренние имена таблиц и столбцов никогда не раскрываются агенту. Вы определяете сущности, псевдонимы и описания, имеющие смысл для AI-взаимодействия — а не вашу ER-диаграмму.&lt;/p&gt;
&lt;h2 id="мульти-база-и-мульти-протокол"&gt;Мульти-база и мульти-протокол&lt;/h2&gt;
&lt;p&gt;SQL MCP Server поддерживает Microsoft SQL, PostgreSQL, Azure Cosmos DB и MySQL. А поскольку это функция DAB, вы получаете REST, GraphQL и MCP эндпоинты одновременно из одной конфигурации. Те же определения сущностей, те же правила RBAC, та же безопасность — по всем трём протоколам.&lt;/p&gt;
&lt;p&gt;Автоконфигурация в DAB 2.0 может даже проинспектировать вашу базу данных и динамически построить конфигурацию, если вам подходит меньше абстракции для быстрого прототипирования.&lt;/p&gt;
&lt;h2 id="моё-мнение"&gt;Моё мнение&lt;/h2&gt;
&lt;p&gt;Вот как должен работать корпоративный доступ к базам данных для AI-агентов. Не «эй, LLM, напиши мне SQL и YOLO его по продакшну». Вместо этого: чётко определённый слой сущностей, детерминированная генерация запросов, RBAC на каждом шагу, кеширование, мониторинг и телеметрия. Скучно в самом лучшем смысле.&lt;/p&gt;
&lt;p&gt;Для .NET-разработчиков история интеграции чистая — DAB является .NET-инструментом, MCP Server работает как контейнер и интегрируется с Azure SQL, который большинство из нас уже использует. Если вы строите AI-агентов, которым нужен доступ к данным, начните здесь.&lt;/p&gt;
&lt;h2 id="подводя-итоги"&gt;Подводя итоги&lt;/h2&gt;
&lt;p&gt;SQL MCP Server бесплатен, с открытым исходным кодом и работает где угодно. Это предписывающий подход Microsoft к предоставлению AI-агентам безопасного доступа к базам данных. Ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/azure-sql/introducing-sql-mcp-server/"&gt;полным постом&lt;/a&gt; и &lt;a href="https://aka.ms/sql/mcp"&gt;документацией&lt;/a&gt; для начала работы.&lt;/p&gt;</content:encoded></item><item><title>VS Code 1.116 — Приложение Agents Получает Навигацию с Клавиатуры и Автодополнение Контекста Файлов</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-116-agents-app-updates/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-116-agents-app-updates/</guid><description>VS Code 1.116 сосредоточен на доработке приложения Agents — выделенные горячие клавиши, улучшения доступности, автодополнение контекста файлов и разрешение ссылок CSS @import.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-116-agents-app-updates/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;VS Code 1.116 — это апрельский релиз 2026 года, и хотя он легче некоторых недавних обновлений, изменения целенаправленны и значимы — особенно если вы ежедневно используете приложение Agents.&lt;/p&gt;
&lt;p&gt;Вот что появилось, на основе &lt;a href="https://code.visualstudio.com/updates/v1_116"&gt;официальных заметок о релизе&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="улучшения-приложения-agents"&gt;Улучшения приложения Agents&lt;/h2&gt;
&lt;p&gt;Приложение Agents продолжает развиваться с доработками юзабилити, которые реально влияют на повседневные рабочие процессы:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Выделенные горячие клавиши&lt;/strong&gt; — теперь можно переключать фокус на представление Changes, дерево файлов внутри Changes и представление настроек чата с помощью выделенных команд и горячих клавиш. Если вы раньше кликали по приложению Agents для навигации, теперь доступен полностью клавиатурный рабочий процесс.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Диалог помощи по доступности&lt;/strong&gt; — нажатие &lt;code&gt;Alt+F1&lt;/code&gt; в поле ввода чата теперь открывает диалог помощи по доступности, показывающий доступные команды и горячие клавиши. Пользователи экранных читалок также могут контролировать подробность объявлений. Хорошая доступность полезна для всех.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Автодополнение контекста файлов&lt;/strong&gt; — введите &lt;code&gt;#&lt;/code&gt; в чате приложения Agents, чтобы вызвать автодополнение контекста файлов в рамках текущего рабочего пространства. Это одно из тех маленьких улучшений качества жизни, которые ускоряют каждое взаимодействие — больше не нужно вводить полные пути к файлам при обращении к коду.&lt;/p&gt;
&lt;h2 id="разрешение-ссылок-css-import"&gt;Разрешение ссылок CSS &lt;code&gt;@import&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Приятно для фронтенд-разработчиков: VS Code теперь разрешает CSS &lt;code&gt;@import&lt;/code&gt;-ссылки, использующие пути node_modules. Вы можете переходить через &lt;code&gt;Ctrl+клик&lt;/code&gt; по импортам вроде &lt;code&gt;@import &amp;quot;some-module/style.css&amp;quot;&lt;/code&gt; при использовании бандлеров. Мелочь, но убирает точку трения в CSS-рабочих процессах.&lt;/p&gt;
&lt;h2 id="заключение"&gt;Заключение&lt;/h2&gt;
&lt;p&gt;VS Code 1.116 — это про совершенствование: сделать приложение Agents более удобным для навигации, более доступным и более дружелюбным к клавиатуре. Если вы проводите значительное время в приложении Agents (а я подозреваю, что многие из нас так и делают), эти изменения накапливаются.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://code.visualstudio.com/updates/v1_116"&gt;полными заметками о релизе&lt;/a&gt; для полного списка.&lt;/p&gt;</content:encoded></item><item><title>Агентная платформенная инженерия становится реальностью — Git-APE показывает как</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agentic-platform-engineering-git-ape/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agentic-platform-engineering-git-ape/</guid><description>Проект Git-APE от Microsoft воплощает агентную платформенную инженерию на практике — используя агенты GitHub Copilot и Azure MCP для превращения запросов на естественном языке в валидированную облачную инфраструктуру.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agentic-platform-engineering-git-ape/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Платформенная инженерия была одним из тех терминов, которые звучат отлично на конференциях, но обычно означают «мы построили внутренний портал и обёртку для Terraform.» Настоящее обещание — самообслуживающаяся инфраструктура, которая действительно безопасна, управляема и быстра — всегда была в нескольких шагах.&lt;/p&gt;
&lt;p&gt;Команда Azure только что опубликовала &lt;a href="https://devblogs.microsoft.com/all-things-azure/putting-agentic-platform-engineering-to-the-test/"&gt;Часть 2 серии об агентной платформенной инженерии&lt;/a&gt;, и эта часть целиком о практической реализации. Они называют это &lt;strong&gt;Git-APE&lt;/strong&gt; (да, акроним намеренный), и это open-source проект, который использует агенты GitHub Copilot плюс серверы Azure MCP для превращения запросов на естественном языке в валидированную и развёрнутую инфраструктуру.&lt;/p&gt;
&lt;h2 id="что-git-ape-делает-на-самом-деле"&gt;Что Git-APE делает на самом деле&lt;/h2&gt;
&lt;p&gt;Основная идея: вместо того чтобы разработчики изучали модули Terraform, навигировали по UI порталов или создавали тикеты для платформенной команды, они разговаривают с агентом Copilot. Агент интерпретирует намерение, генерирует Infrastructure-as-Code, валидирует его по политикам и разворачивает — всё внутри VS Code.&lt;/p&gt;
&lt;p&gt;Вот настройка:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/Azure/git-ape
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; git-ape
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Откройте workspace в VS Code, и файлы конфигурации агента автоматически обнаруживаются GitHub Copilot. Вы взаимодействуете с агентом напрямую:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;@git-ape deploy a function app with storage in West Europe
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Агент использует Azure MCP Server под капотом для взаимодействия с сервисами Azure. Конфигурация MCP в настройках VS Code активирует конкретные возможности:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;azureMcp.serverMode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;azureMcp.enabledServices&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;deploy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;bestpractices&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;group&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;subscription&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;functionapp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;storage&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;sql&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;monitor&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;azureMcp.readOnly&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="почему-это-важно"&gt;Почему это важно&lt;/h2&gt;
&lt;p&gt;Для тех из нас, кто строит на Azure, это смещает разговор о платформенной инженерии с «как построить портал» на «как описать наши ограничения как API.» Когда интерфейс вашей платформы — это ИИ-агент, качество ваших ограничений и политик становится продуктом.&lt;/p&gt;
&lt;p&gt;Блог Части 1 изложил теорию: хорошо описанные API, схемы контроля и явные ограничения делают платформы agent-ready. Часть 2 доказывает, что это работает, поставляя реальные инструменты. Агент не генерирует ресурсы вслепую — он валидирует по лучшим практикам, соблюдает соглашения об именовании и применяет политики вашей организации.&lt;/p&gt;
&lt;p&gt;Очистка так же проста:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;@git-ape destroy my-resource-group
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="моё-мнение"&gt;Моё мнение&lt;/h2&gt;
&lt;p&gt;Буду честен — здесь больше о паттерне, чем о конкретном инструменте. Git-APE сам по себе — это демо/референсная архитектура. Но лежащая в основе идея — агенты как интерфейс к вашей платформе, MCP как протокол, GitHub Copilot как хост — вот куда движется experience корпоративного разработчика.&lt;/p&gt;
&lt;p&gt;Если вы — платформенная команда, которая ищет, как сделать внутренние инструменты agent-friendly, лучшего стартового пункта не найти. А если вы .NET-разработчик и думаете, как это связано с вашим миром: Azure MCP Server и агенты GitHub Copilot работают с любыми нагрузками Azure. Ваш ASP.NET Core API, ваш стек .NET Aspire, ваши контейнеризированные микросервисы — всё это может быть целью агентного потока деплоя.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Git-APE — это ранний, но конкретный взгляд на агентную платформенную инженерию на практике. Клонируйте &lt;a href="https://github.com/Azure/git-ape"&gt;репозиторий&lt;/a&gt;, попробуйте демо и начните думать о том, как API и политики вашей платформы должны выглядеть, чтобы агент мог безопасно их использовать.&lt;/p&gt;
&lt;p&gt;Читайте &lt;a href="https://devblogs.microsoft.com/all-things-azure/putting-agentic-platform-engineering-to-the-test/"&gt;полный пост&lt;/a&gt; для walkthrough и видео-демонстраций.&lt;/p&gt;</content:encoded></item><item><title>Изолированный режим Aspire устраняет кошмар конфликтов портов при параллельной разработке</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-isolated-mode-parallel-instances/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-isolated-mode-parallel-instances/</guid><description>Aspire 13.2 вводит режим --isolated: случайные порты, отдельные секреты и ноль коллизий при запуске нескольких экземпляров одного AppHost. Идеально для ИИ-агентов, worktrees и параллельных рабочих процессов.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-isolated-mode-parallel-instances/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы когда-нибудь пытались запустить два экземпляра одного проекта одновременно, вы знаете эту боль. Порт 8080 уже используется. Порт 17370 занят. Убить что-то, перезапустить, жонглировать переменными окружения — настоящий убийца продуктивности.&lt;/p&gt;
&lt;p&gt;Эта проблема не улучшается, а ухудшается. ИИ-агенты создают git worktrees для независимой работы. Фоновые агенты поднимают отдельные среды. Разработчики дважды клонируют один репозиторий для feature-веток. Каждый из этих сценариев упирается в одну и ту же стену: два экземпляра одного приложения борются за одни и те же порты.&lt;/p&gt;
&lt;p&gt;Aspire 13.2 решает это одним флагом. James Newton-King из команды Aspire &lt;a href="https://devblogs.microsoft.com/aspire/aspire-isolated-mode-parallel-development/"&gt;описал все детали&lt;/a&gt;, и это одна из тех фич «почему у нас этого не было раньше».&lt;/p&gt;
&lt;h2 id="решение---isolated"&gt;Решение: &lt;code&gt;--isolated&lt;/code&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire run --isolated
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вот и всё. Каждый запуск получает:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Случайные порты&lt;/strong&gt; — больше никаких коллизий между экземплярами&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Изолированные пользовательские секреты&lt;/strong&gt; — строки подключения и API-ключи остаются раздельными для каждого экземпляра&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Никакого ручного переназначения портов. Никакого жонглирования переменными окружения. Каждый запуск автоматически получает чистую среду без коллизий.&lt;/p&gt;
&lt;h2 id="реальные-сценарии-где-это-сияет"&gt;Реальные сценарии, где это сияет&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Множественные checkout.&lt;/strong&gt; У вас feature-ветка в одной директории и bugfix в другой:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Terminal 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projects/my-app-feature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire run --isolated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Terminal 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projects/my-app-bugfix
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire run --isolated
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Оба работают без конфликтов. Дашборд показывает, что где запущено.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Фоновые агенты в VS Code.&lt;/strong&gt; Когда фоновый агент Copilot Chat создаёт git worktree для независимой работы с вашим кодом, ему может понадобиться запустить ваш Aspire AppHost. Без &lt;code&gt;--isolated&lt;/code&gt; это конфликт портов с основным worktree. С ним оба экземпляра просто работают.&lt;/p&gt;
&lt;p&gt;Навык Aspire, поставляемый с &lt;code&gt;aspire agent init&lt;/code&gt;, автоматически инструктирует агентов использовать &lt;code&gt;--isolated&lt;/code&gt; при работе в worktrees. Так что фоновый агент Copilot должен справляться с этим из коробки.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Интеграционные тесты параллельно с разработкой.&lt;/strong&gt; Нужно запускать тесты против работающего AppHost, продолжая разрабатывать фичи? Изолированный режим даёт каждому контексту собственные порты и конфигурацию.&lt;/p&gt;
&lt;h2 id="как-это-работает-под-капотом"&gt;Как это работает под капотом&lt;/h2&gt;
&lt;p&gt;Когда вы передаёте &lt;code&gt;--isolated&lt;/code&gt;, CLI генерирует уникальный ID экземпляра для запуска. Это управляет двумя поведениями:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Рандомизация портов&lt;/strong&gt; — вместо привязки к предсказуемым портам, определённым в конфигурации AppHost, изолированный режим выбирает случайные доступные порты для всего — дашборда, эндпоинтов сервисов, всего. Service discovery автоматически подстраивается, чтобы сервисы находили друг друга независимо от назначенных портов.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Изоляция секретов&lt;/strong&gt; — каждый изолированный запуск получает собственное хранилище пользовательских секретов, привязанное к ID экземпляра. Строки подключения и API-ключи одного запуска не утекают в другой.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ваш код не нуждается в изменениях. Service discovery Aspire разрешает эндпоинты во время выполнения, так что всё подключается правильно независимо от назначения портов.&lt;/p&gt;
&lt;h2 id="когда-использовать"&gt;Когда использовать&lt;/h2&gt;
&lt;p&gt;Используйте &lt;code&gt;--isolated&lt;/code&gt; при запуске нескольких экземпляров одного AppHost одновременно — будь то параллельная разработка, автоматизированные тесты, ИИ-агенты или git worktrees. Для разработки с единственным экземпляром, где вы предпочитаете предсказуемые порты, обычный &lt;code&gt;aspire run&lt;/code&gt; по-прежнему отлично работает.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Изолированный режим — это маленькая фича, которая решает реальную и всё более распространённую проблему. По мере того как разработка с ИИ подталкивает нас к большему количеству параллельных рабочих процессов — множество агентов, множество worktrees, множество контекстов — возможность просто поднять ещё один экземпляр без борьбы за порты становится необходимой.&lt;/p&gt;
&lt;p&gt;Прочитайте &lt;a href="https://devblogs.microsoft.com/aspire/aspire-isolated-mode-parallel-development/"&gt;полный пост&lt;/a&gt; для всех технических деталей и попробуйте с &lt;code&gt;aspire update --self&lt;/code&gt; для получения 13.2.&lt;/p&gt;</content:encoded></item><item><title>Оценка модернизации GitHub Copilot — лучший инструмент миграции, который вы ещё не используете</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-modernization-assessment-github-copilot/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-modernization-assessment-github-copilot/</guid><description>Расширение модернизации GitHub Copilot не просто предлагает изменения кода — оно создаёт полноценную оценку миграции с действенными проблемами, сравнением целей Azure и коллаборативным рабочим процессом. Вот почему документ оценки — ключ ко всему.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/dotnet-modernization-assessment-github-copilot/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Миграция устаревшего приложения .NET Framework на современный .NET — одна из тех задач, о которых все знают, что их нужно сделать, но никто не хочет начинать. Это никогда не просто «сменить целевой фреймворк». Это API, которые исчезли, пакеты, которых больше нет, модели хостинга, которые работают совершенно по-другому, и миллион мелких решений о том, что контейнеризировать, что переписать и что оставить как есть.&lt;/p&gt;
&lt;p&gt;Джеффри Фриц только что опубликовал &lt;a href="https://devblogs.microsoft.com/dotnet/your-migrations-source-of-truth-the-modernization-assessment/"&gt;глубокий разбор оценки модернизации GitHub Copilot&lt;/a&gt;, и честно? Это лучший инструмент миграции для .NET, который я видел. Не из-за генерации кода — это уже стандарт. Из-за документа оценки, который он создаёт.&lt;/p&gt;
&lt;h2 id="это-не-просто-движок-предложений-кода"&gt;Это не просто движок предложений кода&lt;/h2&gt;
&lt;p&gt;Расширение VS Code следует модели &lt;strong&gt;Оценить → Спланировать → Выполнить&lt;/strong&gt;. Фаза оценки анализирует всю кодовую базу и создаёт структурированный документ, фиксирующий всё: что нужно изменить, какие ресурсы Azure предоставить, какую модель развёртывания использовать. Всё последующее — инфраструктура как код, контейнеризация, манифесты развёртывания — вытекает из результатов оценки.&lt;/p&gt;
&lt;p&gt;Оценка хранится в &lt;code&gt;.github/modernize/assessment/&lt;/code&gt; вашего проекта. Каждый запуск создаёт независимый отчёт, поэтому вы накапливаете историю и можете отслеживать, как меняется ваша позиция по миграции по мере исправления проблем.&lt;/p&gt;
&lt;h2 id="два-способа-начать"&gt;Два способа начать&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Рекомендованная оценка&lt;/strong&gt; — быстрый путь. Выберите из курируемых доменов (Обновление Java/.NET, облачная готовность, безопасность) и получите значимые результаты без настройки конфигурации. Идеально для первого взгляда на состояние вашего приложения.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пользовательская оценка&lt;/strong&gt; — прицельный путь. Настройте точно, что анализировать: целевой compute (App Service, AKS, Container Apps), целевую ОС, анализ контейнеризации. Выберите несколько целей Azure для сравнения подходов к миграции бок о бок.&lt;/p&gt;
&lt;p&gt;Это представление сравнения действительно полезно. Приложение с 3 обязательными проблемами для App Service может иметь 7 для AKS. Видеть оба варианта помогает принять решение по хостингу до того, как вы привяжетесь к пути миграции.&lt;/p&gt;
&lt;h2 id="разбивка-проблем-действенна"&gt;Разбивка проблем действенна&lt;/h2&gt;
&lt;p&gt;Каждая проблема сопровождается уровнем критичности:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Обязательная&lt;/strong&gt; — необходимо исправить, иначе миграция провалится&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Потенциальная&lt;/strong&gt; — может повлиять на миграцию, требует человеческого суждения&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Необязательная&lt;/strong&gt; — рекомендуемые улучшения, не блокируют миграцию&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И каждая проблема ссылается на затронутые файлы и номера строк, предоставляет подробное описание того, что не так и почему это важно для вашей целевой платформы, даёт конкретные шаги по устранению (не просто «исправьте это») и включает ссылки на официальную документацию.&lt;/p&gt;
&lt;p&gt;Вы можете передать отдельные проблемы разработчикам, и у них есть всё необходимое для действий. В этом разница между инструментом, который говорит «есть проблема» и инструментом, который говорит, как её решить.&lt;/p&gt;
&lt;h2 id="охваченные-пути-обновления"&gt;Охваченные пути обновления&lt;/h2&gt;
&lt;p&gt;Для .NET конкретно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.NET Framework → .NET 10&lt;/li&gt;
&lt;li&gt;ASP.NET → ASP.NET Core&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Каждый путь обновления имеет правила обнаружения, которые знают, какие API были удалены, какие паттерны не имеют прямого эквивалента и какие проблемы безопасности требуют внимания.&lt;/p&gt;
&lt;p&gt;Для команд, управляющих несколькими приложениями, есть также CLI, поддерживающий пакетные оценки нескольких репозиториев — клонируйте все репо, оцените их все, получите отчёты по каждому приложению плюс агрегированное представление портфолио.&lt;/p&gt;
&lt;h2 id="моё-мнение"&gt;Моё мнение&lt;/h2&gt;
&lt;p&gt;Если вы сидите на устаревших приложениях .NET Framework (а давайте будем честны, большинство корпоративных команд именно так и делает), это &lt;em&gt;тот самый&lt;/em&gt; инструмент, с которого стоит начать. Только документ оценки стоит потраченного времени — он превращает расплывчатое «нам бы модернизировать» в конкретный, приоритизированный список рабочих элементов с чёткими путями вперёд.&lt;/p&gt;
&lt;p&gt;Коллаборативный рабочий процесс тоже продуман: экспортируйте оценки, поделитесь с командой, импортируйте без повторного запуска. Архитектурные ревью, где решения принимают не те, кто запускает инструменты? Учтено.&lt;/p&gt;
&lt;h2 id="подводя-итоги"&gt;Подводя итоги&lt;/h2&gt;
&lt;p&gt;Оценка модернизации GitHub Copilot превращает миграцию .NET из пугающего, неопределённого проекта в структурированный, отслеживаемый процесс. Начните с рекомендованной оценки, чтобы увидеть текущее состояние, затем используйте пользовательские оценки для сравнения целей Azure и построения плана миграции.&lt;/p&gt;
&lt;p&gt;Прочитайте &lt;a href="https://devblogs.microsoft.com/dotnet/your-migrations-source-of-truth-the-modernization-assessment/"&gt;полное руководство&lt;/a&gt; и установите &lt;a href="https://aka.ms/ghcp-appmod/vscode-ext"&gt;расширение VS Code&lt;/a&gt;, чтобы попробовать на своей кодовой базе.&lt;/p&gt;</content:encoded></item><item><title>Подключите ваши MCP-серверы на Azure Functions к агентам Foundry — Вот как</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/</guid><description>Создайте MCP-сервер один раз, разверните на Azure Functions и подключите к агентам Microsoft Foundry с правильной аутентификацией. Ваши инструменты работают везде — VS Code, Cursor, а теперь и корпоративные AI-агенты.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот что мне нравится в экосистеме MCP: вы создаёте сервер один раз, и он работает везде. VS Code, Visual Studio, Cursor, ChatGPT — каждый MCP-клиент может обнаруживать и использовать ваши инструменты. Теперь Microsoft добавляет ещё одного потребителя в этот список: агенты Foundry.&lt;/p&gt;
&lt;p&gt;Лили Ма из команды Azure SDK &lt;a href="https://devblogs.microsoft.com/azure-sdk/give-your-foundry-agent-custom-tools-with-mcp-servers-on-azure-functions/"&gt;опубликовала практическое руководство&lt;/a&gt; по подключению MCP-серверов на Azure Functions к агентам Microsoft Foundry. Если у вас уже есть MCP-сервер, это чистая добавленная ценность — никакой перестройки не требуется.&lt;/p&gt;
&lt;h2 id="почему-эта-комбинация-имеет-смысл"&gt;Почему эта комбинация имеет смысл&lt;/h2&gt;
&lt;p&gt;Azure Functions даёт вам масштабируемую инфраструктуру, встроенную аутентификацию и бессерверную тарификацию для хостинга MCP-серверов. Microsoft Foundry даёт вам AI-агентов, которые могут рассуждать, планировать и выполнять действия. Соединение этих двух означает, что ваши пользовательские инструменты — запросы к базе данных, вызовы бизнес-API, выполнение логики валидации — становятся возможностями, которые корпоративные AI-агенты могут автономно обнаруживать и использовать.&lt;/p&gt;
&lt;p&gt;Ключевой момент: ваш MCP-сервер остаётся прежним. Вы просто добавляете Foundry как ещё одного потребителя. Те же инструменты, которые работают в вашей конфигурации VS Code, теперь обеспечивают работу AI-агента, с которым взаимодействуют ваша команда или клиенты.&lt;/p&gt;
&lt;h2 id="варианты-аутентификации"&gt;Варианты аутентификации&lt;/h2&gt;
&lt;p&gt;Здесь статья действительно приносит пользу. Четыре метода аутентификации в зависимости от вашего сценария:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Метод&lt;/th&gt;
&lt;th&gt;Сценарий&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;На основе ключей&lt;/strong&gt; (по умолчанию)&lt;/td&gt;
&lt;td&gt;Разработка или серверы без аутентификации Entra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft Entra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Продакшн с управляемыми удостоверениями&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Проброс OAuth-удостоверений&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Продакшн, где каждый пользователь аутентифицируется отдельно&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Без аутентификации&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Разработка/тестирование или только публичные данные&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Для продакшна рекомендуется Microsoft Entra с идентификацией агента. Проброс OAuth-удостоверений — для случаев, когда важен контекст пользователя: агент предлагает пользователям войти, и каждый запрос несёт собственный токен пользователя.&lt;/p&gt;
&lt;h2 id="настройка"&gt;Настройка&lt;/h2&gt;
&lt;p&gt;Общий поток:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Разверните MCP-сервер на Azure Functions&lt;/strong&gt; — доступны примеры для &lt;a href="https://github.com/Azure-Samples/remote-mcp-functions-dotnet"&gt;.NET&lt;/a&gt;, Python, TypeScript и Java&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Включите встроенную MCP-аутентификацию&lt;/strong&gt; на вашем function app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Получите URL эндпоинта&lt;/strong&gt; — &lt;code&gt;https://&amp;lt;FUNCTION_APP_NAME&amp;gt;.azurewebsites.net/runtime/webhooks/mcp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Добавьте MCP-сервер как инструмент в Foundry&lt;/strong&gt; — перейдите к агенту в портале, добавьте новый MCP-инструмент, укажите эндпоинт и учётные данные&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Затем протестируйте в песочнице Agent Builder, отправив запрос, который активирует один из ваших инструментов.&lt;/p&gt;
&lt;h2 id="моё-мнение"&gt;Моё мнение&lt;/h2&gt;
&lt;p&gt;История компонуемости здесь становится по-настоящему сильной. Создайте MCP-сервер один раз на .NET (или Python, TypeScript, Java), разверните на Azure Functions, и каждый MCP-совместимый клиент может его использовать — инструменты для кодирования, чат-приложения, а теперь и корпоративные AI-агенты. Это паттерн «напиши один раз, используй везде», который действительно работает.&lt;/p&gt;
&lt;p&gt;Для .NET-разработчиков конкретно, &lt;a href="https://github.com/Azure-Samples/remote-mcp-functions-dotnet"&gt;расширение MCP для Azure Functions&lt;/a&gt; делает это простым. Вы определяете инструменты как Azure Functions, развёртываете — и у вас есть MCP-сервер продакшн-уровня со всей безопасностью и масштабированием, которые предоставляет Azure Functions.&lt;/p&gt;
&lt;h2 id="подводя-итоги"&gt;Подводя итоги&lt;/h2&gt;
&lt;p&gt;Если у вас есть MCP-инструменты на Azure Functions, подключение к агентам Foundry — быстрый выигрыш: ваши пользовательские инструменты становятся корпоративными AI-возможностями с правильной аутентификацией и без изменений кода на сервере.&lt;/p&gt;
&lt;p&gt;Прочитайте &lt;a href="https://devblogs.microsoft.com/azure-sdk/give-your-foundry-agent-custom-tools-with-mcp-servers-on-azure-functions/"&gt;полное руководство&lt;/a&gt; для пошаговых инструкций по каждому методу аутентификации и ознакомьтесь с &lt;a href="https://learn.microsoft.com/azure/azure-functions/functions-mcp-foundry-tools?tabs=entra%2Cmcp-extension%2Cfoundry"&gt;подробной документацией&lt;/a&gt; для продакшн-настроек.&lt;/p&gt;</content:encoded></item><item><title>Создаём мультиагентные UI в реальном времени, которые не выглядят как чёрный ящик</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/ag-ui-real-time-multi-agent-ui-maf/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/ag-ui-real-time-multi-agent-ui-maf/</guid><description>AG-UI и Microsoft Agent Framework объединяются, чтобы дать мультиагентным рабочим процессам полноценный фронтенд — с потоковой передачей в реальном времени, человеческими одобрениями и полной видимостью действий агентов.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/ag-ui-real-time-multi-agent-ui-maf/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот в чём дело с мультиагентными системами: в демо они выглядят невероятно. Три агента передают друг другу работу, решают задачи, принимают решения. А потом ты пытаешься показать это реальным пользователям и&amp;hellip; тишина. Крутящийся индикатор. Непонятно, какой агент чем занимается и почему система встала на паузу. Это не продукт — это проблема доверия.&lt;/p&gt;
&lt;p&gt;Команда Microsoft Agent Framework только что опубликовала &lt;a href="https://devblogs.microsoft.com/agent-framework/ag-ui-multi-agent-workflow-demo/"&gt;отличный walkthrough&lt;/a&gt; о том, как связать рабочие процессы MAF с &lt;a href="https://github.com/ag-ui-protocol/ag-ui"&gt;AG-UI&lt;/a&gt; — открытым протоколом для потоковой передачи событий выполнения агентов на фронтенд через Server-Sent Events. И честно? Это именно тот мост, которого нам не хватало.&lt;/p&gt;
&lt;h2 id="почему-это-важно-для-net-разработчиков"&gt;Почему это важно для .NET-разработчиков&lt;/h2&gt;
&lt;p&gt;Если вы строите приложения с ИИ, наверняка уже упирались в эту стену. Ваша серверная оркестрация работает отлично — агенты передают задачи друг другу, инструменты запускаются, решения принимаются. Но фронтенд понятия не имеет, что происходит за кулисами. AG-UI решает это, определяя стандартный протокол для потоковой передачи событий агентов (&lt;code&gt;RUN_STARTED&lt;/code&gt;, &lt;code&gt;STEP_STARTED&lt;/code&gt;, &lt;code&gt;TOOL_CALL_*&lt;/code&gt;, &lt;code&gt;TEXT_MESSAGE_*&lt;/code&gt;) напрямую в ваш UI-слой через SSE.&lt;/p&gt;
&lt;p&gt;Демо — это рабочий процесс клиентской поддержки с тремя агентами: агент триажа маршрутизирует запросы, агент возвратов обрабатывает денежные вопросы, и агент заказов управляет заменами. У каждого агента свои инструменты, а топология передач определена явно — никакого «разберись из промпта».&lt;/p&gt;
&lt;h2 id="топология-передач--настоящая-звезда"&gt;Топология передач — настоящая звезда&lt;/h2&gt;
&lt;p&gt;Что зацепило мой взгляд — как &lt;code&gt;HandoffBuilder&lt;/code&gt; позволяет объявить направленный граф маршрутизации между агентами:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HandoffBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ag_ui_handoff_workflow_demo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;participants&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;triage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;termination_condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;termination_condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_handoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;triage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Refunds, damaged-item claims...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_handoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;triage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Replacement, exchange...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_handoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Replacement logistics needed after refund.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_handoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;triage&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;After replacement/shipping tasks complete.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Каждый &lt;code&gt;add_handoff&lt;/code&gt; создаёт направленное ребро с описанием на естественном языке. Фреймворк генерирует инструменты передачи для каждого агента на основе этой топологии. Решения о маршрутизации основываются на вашей структуре оркестрации, а не на том, что LLM решит сделать. Это огромное преимущество для надёжности в продакшене.&lt;/p&gt;
&lt;h2 id="human-in-the-loop-который-действительно-работает"&gt;Human-in-the-loop, который действительно работает&lt;/h2&gt;
&lt;p&gt;Демо показывает два паттерна прерываний, без которых не обойтись ни одному реальному агентному приложению:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Прерывания для одобрения инструментов&lt;/strong&gt; — когда агент вызывает инструмент с &lt;code&gt;approval_mode=&amp;quot;always_require&amp;quot;&lt;/code&gt;, рабочий процесс ставится на паузу и отправляет событие. Фронтенд рендерит модальное окно одобрения с названием инструмента и аргументами. Никаких циклов повторных попыток, сжигающих токены — просто чистый поток пауза-одобрение-возобновление.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Прерывания запроса информации&lt;/strong&gt; — когда агенту нужно больше контекста от пользователя (например, ID заказа), он ставит на паузу и спрашивает. Фронтенд показывает вопрос, пользователь отвечает, и выполнение возобновляется с того же места, где остановилось.&lt;/p&gt;
&lt;p&gt;Оба паттерна передаются как стандартные события AG-UI, поэтому вашему фронтенду не нужна специальная логика для каждого агента — он просто отображает любое событие, приходящее через SSE-соединение.&lt;/p&gt;
&lt;h2 id="подключение-удивительно-простое"&gt;Подключение удивительно простое&lt;/h2&gt;
&lt;p&gt;Интеграция между MAF и AG-UI — это один вызов функции:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;agent_framework.ag_ui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AgentFrameworkWorkflow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;add_agent_framework_fastapi_endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;demo_workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AgentFrameworkWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;workflow_factory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;_thread_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;create_handoff_workflow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ag_ui_handoff_workflow_demo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;add_agent_framework_fastapi_endpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;demo_workflow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/handoff_demo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;workflow_factory&lt;/code&gt; создаёт свежий рабочий процесс для каждого потока, так что каждый диалог получает изолированное состояние. Эндпоинт автоматически обрабатывает всю SSE-обвязку. Если вы уже используете FastAPI (или можете добавить его как лёгкий слой), это практически без трения.&lt;/p&gt;
&lt;h2 id="моё-мнение"&gt;Моё мнение&lt;/h2&gt;
&lt;p&gt;Для нас, .NET-разработчиков, немедленный вопрос: «Можно ли сделать это на C#?» Agent Framework доступен и для .NET, и для Python, а протокол AG-UI не зависит от языка (это просто SSE). Так что хотя конкретная демка использует Python и FastAPI, паттерн переносится напрямую. Вы можете настроить минимальный API ASP.NET Core с SSE-эндпоинтами, следуя той же схеме событий AG-UI.&lt;/p&gt;
&lt;p&gt;Более важный вывод — мультиагентные UI становятся полноценной задачей первого класса, а не чем-то придуманным постфактум. Если вы строите что-либо, где агенты взаимодействуют с людьми — клиентская поддержка, рабочие процессы утверждения, обработка документов — эта комбинация оркестрации MAF и прозрачности AG-UI является паттерном, которому стоит следовать.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;AG-UI + Microsoft Agent Framework даёт вам лучшее из обоих миров: надёжную мультиагентную оркестрацию на бэкенде и видимость в реальном времени на фронтенде. Больше никаких взаимодействий агентов как чёрный ящик.&lt;/p&gt;
&lt;p&gt;Посмотрите &lt;a href="https://devblogs.microsoft.com/agent-framework/ag-ui-multi-agent-workflow-demo/"&gt;полный walkthrough&lt;/a&gt; и &lt;a href="https://github.com/ag-ui-protocol/ag-ui"&gt;репозиторий протокола AG-UI&lt;/a&gt;, чтобы погрузиться глубже.&lt;/p&gt;</content:encoded></item><item><title>Та Самая Настройка Плавающих Окон в Visual Studio, О Которой Вы Не Знали (Но Должны)</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/visual-studio-floating-windows-powertoys/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/visual-studio-floating-windows-powertoys/</guid><description>Скрытая настройка Visual Studio даёт полный контроль над плавающими окнами — независимые записи в панели задач, правильное поведение на нескольких мониторах и идеальная интеграция с FancyZones. Один выпадающий список меняет всё.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинал можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/visual-studio-floating-windows-powertoys/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы используете несколько мониторов с Visual Studio (а честно говоря, кто сейчас не использует?), вы наверняка сталкивались с раздражающей проблемой: плавающие окна инструментов исчезают при сворачивании основной IDE, они всегда остаются поверх всего остального и не отображаются отдельными кнопками в панели задач. Это работает для некоторых рабочих процессов, но для мультимониторных конфигураций — это расстраивает.&lt;/p&gt;
&lt;p&gt;Мадс Кристенсен из команды Visual Studio &lt;a href="https://devblogs.microsoft.com/visualstudio/take-full-control-of-your-floating-windows-in-visual-studio/"&gt;поделился малоизвестной настройкой&lt;/a&gt;, которая полностью меняет поведение плавающих окон. Один выпадающий список. Вот и всё.&lt;/p&gt;
&lt;h2 id="настройка"&gt;Настройка&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Tools &amp;gt; Options &amp;gt; Environment &amp;gt; Windows &amp;gt; Floating Windows&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Выпадающий список &amp;ldquo;These floating windows are owned by the main window&amp;rdquo; имеет три варианта:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;None&lt;/strong&gt; — полная независимость. Каждое плавающее окно получает собственную запись в панели задач и ведёт себя как обычное окно Windows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool Windows&lt;/strong&gt; (по умолчанию) — документы свободно плавают, окна инструментов привязаны к IDE.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documents and Tool Windows&lt;/strong&gt; — классическое поведение Visual Studio, всё привязано к главному окну.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="почему-none--лучший-выбор-для-мультимониторных-настроек"&gt;Почему &amp;ldquo;None&amp;rdquo; — лучший выбор для мультимониторных настроек&lt;/h2&gt;
&lt;p&gt;Установите &lt;strong&gt;None&lt;/strong&gt;, и внезапно все ваши плавающие окна инструментов и документов начинают вести себя как настоящие приложения Windows. Они появляются в панели задач, остаются видимыми при сворачивании основного окна Visual Studio и перестают навязчиво выходить на передний план.&lt;/p&gt;
&lt;p&gt;Совместите это с &lt;strong&gt;PowerToys FancyZones&lt;/strong&gt; — и это полностью меняет игру. Создайте пользовательские макеты на своих мониторах, расположите Solution Explorer в одной зоне, отладчик в другой, а файлы кода где угодно. Всё остаётся на месте, всё доступно независимо, и ваше рабочее пространство ощущается организованным, а не хаотичным.&lt;/p&gt;
&lt;h2 id="быстрые-рекомендации"&gt;Быстрые рекомендации&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Продвинутые пользователи с несколькими мониторами&lt;/strong&gt;: Установите &lt;strong&gt;None&lt;/strong&gt;, используйте в паре с FancyZones&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Иногда используете плавающие окна&lt;/strong&gt;: &lt;strong&gt;Tool Windows&lt;/strong&gt; (по умолчанию) — хороший компромисс&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Традиционный рабочий процесс&lt;/strong&gt;: &lt;strong&gt;Documents and Tool Windows&lt;/strong&gt; сохраняет классическое поведение&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Совет профессионала: &lt;strong&gt;Ctrl + двойной клик&lt;/strong&gt; по заголовку любого окна инструментов, чтобы мгновенно сделать его плавающим или закрепить. Перезапуск после изменения настройки не нужен.&lt;/p&gt;
&lt;h2 id="заключение"&gt;Заключение&lt;/h2&gt;
&lt;p&gt;Это одна из тех настроек из серии «не могу поверить, что я этого не знал». Если плавающие окна в Visual Studio когда-либо вас раздражали, идите и измените эту настройку прямо сейчас.&lt;/p&gt;
&lt;p&gt;Прочитайте &lt;a href="https://devblogs.microsoft.com/visualstudio/take-full-control-of-your-floating-windows-in-visual-studio/"&gt;полный пост&lt;/a&gt; для подробностей и скриншотов.&lt;/p&gt;</content:encoded></item><item><title>VS Code 1.115 — Уведомления фонового терминала, режим SSH-агента и другое</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-115-agent-improvements/</link><pubDate>Mon, 06 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-115-agent-improvements/</guid><description>VS Code 1.115 приносит уведомления фонового терминала для агентов, удалённый хостинг агентов через SSH, вставку файлов в терминал и отслеживание изменений с учётом сессий. Вот что важно для .NET-разработчиков.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-115-agent-improvements/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;VS Code 1.115 только что &lt;a href="https://code.visualstudio.com/updates/v1_115"&gt;вышел&lt;/a&gt;, и хотя это более лёгкий релиз в плане основных функций, улучшения, связанные с агентами, действительно полезны, если вы ежедневно работаете с AI-ассистентами для написания кода.&lt;/p&gt;
&lt;p&gt;Давайте разберём, что действительно стоит знать.&lt;/p&gt;
&lt;h2 id="фоновые-терминалы-общаются-с-агентами"&gt;Фоновые терминалы общаются с агентами&lt;/h2&gt;
&lt;p&gt;Это главная функция выпуска. Фоновые терминалы теперь автоматически уведомляют агентов о завершении команд, включая код возврата и вывод терминала. Запросы ввода в фоновых терминалах также обнаруживаются и показываются пользователю.&lt;/p&gt;
&lt;p&gt;Почему это важно? Если вы использовали режим агента Copilot для запуска команд сборки или тестовых наборов в фоне, вы знаете боль от &amp;ldquo;оно уже закончилось?&amp;rdquo; — фоновые терминалы по сути работали по принципу &amp;ldquo;запустил и забыл&amp;rdquo;. Теперь агент получает уведомление, когда ваш &lt;code&gt;dotnet build&lt;/code&gt; или &lt;code&gt;dotnet test&lt;/code&gt; завершается, видит вывод и может соответственно реагировать. Небольшое изменение, которое делает рабочие процессы на основе агентов значительно надёжнее.&lt;/p&gt;
&lt;p&gt;Также появился новый инструмент &lt;code&gt;send_to_terminal&lt;/code&gt;, позволяющий агентам отправлять команды в фоновые терминалы с подтверждением пользователя, исправляя проблему, когда &lt;code&gt;run_in_terminal&lt;/code&gt; с таймаутом перемещал терминалы в фон и делал их доступными только для чтения.&lt;/p&gt;
&lt;h2 id="удалённый-хостинг-агентов-через-ssh"&gt;Удалённый хостинг агентов через SSH&lt;/h2&gt;
&lt;p&gt;VS Code теперь поддерживает подключение к удалённым машинам по SSH с автоматической установкой CLI и запуском в режиме хоста агентов. Это означает, что ваши сессии AI-агентов могут напрямую работать с удалёнными окружениями — полезно для .NET-разработчиков, которые собирают и тестируют на Linux-серверах или облачных виртуальных машинах.&lt;/p&gt;
&lt;h2 id="отслеживание-изменений-в-сессиях-агентов"&gt;Отслеживание изменений в сессиях агентов&lt;/h2&gt;
&lt;p&gt;Изменения файлов, сделанные во время сессий агентов, теперь отслеживаются и восстанавливаются, с поддержкой diff, отмены/повтора и восстановления состояния. Если агент вносит изменения в ваш код и что-то идёт не так, вы можете точно увидеть, что изменилось, и откатить это. Спокойствие при том, что агенты модифицируют вашу кодовую базу.&lt;/p&gt;
&lt;h2 id="распознавание-вкладок-браузера-и-другие-улучшения"&gt;Распознавание вкладок браузера и другие улучшения&lt;/h2&gt;
&lt;p&gt;Ещё несколько улучшений качества жизни:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Отслеживание вкладок браузера&lt;/strong&gt; — чат теперь может отслеживать и ссылаться на вкладки браузера, открытые во время сессии, чтобы агенты могли ссылаться на веб-страницы, которые вы просматриваете&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Вставка файлов в терминал&lt;/strong&gt; — вставляйте файлы (включая изображения) в терминал с помощью Ctrl+V, перетаскивания или правого клика&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Покрытие тестами в миникарте&lt;/strong&gt; — индикаторы покрытия тестами теперь отображаются в миникарте для быстрого визуального обзора&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Масштабирование щипком на Mac&lt;/strong&gt; — встроенный браузер поддерживает жесты масштабирования щипком&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Права Copilot в Сессиях&lt;/strong&gt; — строка состояния показывает информацию об использовании в представлении Сессий&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Фавиконы в Перейти к файлу&lt;/strong&gt; — открытые веб-страницы показывают фавиконы в списке быстрого выбора&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;VS Code 1.115 — это инкрементальный релиз, но улучшения агентов — уведомления фонового терминала, хостинг агентов через SSH и отслеживание изменений — в сумме дают заметно более гладкий опыт разработки с помощью ИИ. Если вы используете режим агента Copilot для .NET-проектов, это именно те улучшения качества жизни, которые уменьшают ежедневное трение.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://code.visualstudio.com/updates/v1_115"&gt;полными заметками о выпуске&lt;/a&gt; для всех деталей.&lt;/p&gt;</content:encoded></item><item><title>C# 15 получает типы-объединения — и это именно то, что мы просили</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/</link><pubDate>Sun, 05 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/</guid><description>C# 15 вводит ключевое слово union — размеченные объединения с исчерпывающим сопоставлением с образцом, контролируемым компилятором. Вот как они выглядят, почему это важно и как попробовать их уже сегодня.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Это та самая фича, которую я ждал. C# 15 вводит ключевое слово &lt;code&gt;union&lt;/code&gt; — настоящие размеченные объединения с исчерпывающим сопоставлением с образцом, контролируемым компилятором. Если вы когда-нибудь завидовали размеченным объединениям F# или enum в Rust, вы точно знаете, почему это важно.&lt;/p&gt;
&lt;p&gt;Билл Вагнер &lt;a href="https://devblogs.microsoft.com/dotnet/csharp-15-union-types/"&gt;опубликовал подробный разбор&lt;/a&gt; в блоге .NET, и честно? Дизайн чистый, практичный и очень в духе C#. Давайте я покажу, что тут на самом деле есть и почему это более значимо, чем может показаться на первый взгляд.&lt;/p&gt;
&lt;h2 id="проблема-которую-решают-объединения"&gt;Проблема, которую решают объединения&lt;/h2&gt;
&lt;p&gt;До C# 15 возврат «одного из нескольких возможных типов» из метода всегда был компромиссом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;object&lt;/code&gt;&lt;/strong&gt; — никаких ограничений, никакой помощи от компилятора, защитное приведение типов повсюду&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Маркерные интерфейсы&lt;/strong&gt; — лучше, но любой может их реализовать. Компилятор никогда не может считать набор полным&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Абстрактные базовые классы&lt;/strong&gt; — та же проблема, плюс типам нужен общий предок&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ничто из этого не даёт того, что действительно нужно: замкнутого набора типов, где компилятор гарантирует, что вы обработали каждый случай. Именно это делают типы-объединения.&lt;/p&gt;
&lt;h2 id="синтаксис-красиво-прост"&gt;Синтаксис красиво прост&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Одна строка. &lt;code&gt;Pet&lt;/code&gt; может содержать &lt;code&gt;Cat&lt;/code&gt;, &lt;code&gt;Dog&lt;/code&gt; или &lt;code&gt;Bird&lt;/code&gt;. Неявные преобразования генерируются автоматически:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Pet&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rex&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Dog { Name = Rex }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;А вот и магия — компилятор обеспечивает исчерпывающее сопоставление:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Dog&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Cat&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Bird&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Дискард &lt;code&gt;_&lt;/code&gt; не нужен. Компилятор знает, что этот switch покрывает все возможные случаи. Если позже вы добавите четвёртый тип в объединение, каждое выражение switch, которое его не обрабатывает, выдаст предупреждение. Пропущенные случаи обнаруживаются на этапе сборки, а не в рантайме.&lt;/p&gt;
&lt;h2 id="где-это-становится-практичным"&gt;Где это становится практичным&lt;/h2&gt;
&lt;p&gt;Пример с &lt;code&gt;Pet&lt;/code&gt; милый, но вот где объединения действительно сияют в реальном коде.&lt;/p&gt;
&lt;h3 id="api-ответы-возвращающие-разные-формы"&gt;API-ответы, возвращающие разные формы&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;ApiResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ValidationFailure&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Теперь каждый потребитель вынужден обрабатывать успех, ошибку и ошибку валидации. Больше никаких багов «забыл проверить случай ошибки».&lt;/p&gt;
&lt;h3 id="одно-значение-или-коллекция"&gt;Одно значение или коллекция&lt;/h3&gt;
&lt;p&gt;Паттерн &lt;code&gt;OneOrMore&amp;lt;T&amp;gt;&lt;/code&gt; показывает, как объединения могут иметь тело со вспомогательными методами:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AsEnumerable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;single&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вызывающий код передаёт удобную форму:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;dotnet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;moreTags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;csharp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;unions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;preview&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsEnumerable&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$&amp;#34;[{tag}] &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// [dotnet]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="композиция-несвязанных-типов"&gt;Композиция несвязанных типов&lt;/h3&gt;
&lt;p&gt;Это убойная фича по сравнению с традиционными иерархиями. Можно объединять типы, не имеющие ничего общего — &lt;code&gt;string&lt;/code&gt; и &lt;code&gt;Exception&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt; и &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;. Общий предок не нужен.&lt;/p&gt;
&lt;h2 id="пользовательские-объединения-для-существующих-библиотек"&gt;Пользовательские объединения для существующих библиотек&lt;/h2&gt;
&lt;p&gt;Вот умное решение в дизайне: любой класс или struct с атрибутом &lt;code&gt;[Union]&lt;/code&gt; распознаётся как тип-объединение, если он следует базовому паттерну (публичные конструкторы для типов-случаев и свойство &lt;code&gt;Value&lt;/code&gt;). Библиотеки вроде OneOf, которые уже предоставляют типы, похожие на объединения, могут подключить поддержку компилятора без переписывания внутренней реализации.&lt;/p&gt;
&lt;p&gt;Для чувствительных к производительности сценариев с типами-значениями библиотеки могут реализовать паттерн доступа без boxing через методы &lt;code&gt;HasValue&lt;/code&gt; и &lt;code&gt;TryGetValue&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="общая-картина"&gt;Общая картина&lt;/h2&gt;
&lt;p&gt;Типы-объединения — часть более широкой истории исчерпывающей проверки в C#:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Типы-объединения&lt;/strong&gt; — исчерпывающее сопоставление по замкнутому набору типов (доступно сейчас в preview)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Закрытые иерархии&lt;/strong&gt; — модификатор &lt;code&gt;closed&lt;/code&gt; предотвращает создание производных классов вне определяющей сборки (предложено)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Закрытые enum&lt;/strong&gt; — предотвращает создание значений, отличных от объявленных членов (предложено)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Вместе эти три фичи дадут C# одну из самых полных систем типобезопасного сопоставления с образцом среди всех мейнстримных языков.&lt;/p&gt;
&lt;h2 id="попробуйте-сегодня"&gt;Попробуйте сегодня&lt;/h2&gt;
&lt;p&gt;Типы-объединения доступны в .NET 11 Preview 2:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Установите &lt;a href="https://dotnet.microsoft.com/download/dotnet"&gt;.NET 11 Preview SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Укажите &lt;code&gt;net11.0&lt;/code&gt; в качестве целевой платформы проекта&lt;/li&gt;
&lt;li&gt;Установите &lt;code&gt;&amp;lt;LangVersion&amp;gt;preview&amp;lt;/LangVersion&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Одно замечание: в Preview 2 вам нужно объявить &lt;code&gt;UnionAttribute&lt;/code&gt; и &lt;code&gt;IUnion&lt;/code&gt; в проекте, так как их ещё нет в рантайме. Возьмите &lt;a href="https://github.com/dotnet/docs/blob/e68b5dd1e557b53c45ca43e61b013bc919619fb9/docs/csharp/language-reference/builtin-types/snippets/unions/RuntimePolyfill.cs"&gt;RuntimePolyfill.cs&lt;/a&gt; из репозитория документации, или добавьте это:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;System.Runtime.CompilerServices&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; AllowMultiple = false)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnionAttribute&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IUnion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;object?&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;Типы-объединения — одна из тех фич, которые заставляют задуматься, как мы обходились без них. Исчерпывающее сопоставление, контролируемое компилятором, чистый синтаксис, поддержка дженериков и интеграция с существующим pattern matching — это всё, что мы просили, реализованное в стиле C#.&lt;/p&gt;
&lt;p&gt;Попробуйте их в .NET 11 Preview 2, ломайте вещи и &lt;a href="https://github.com/dotnet/csharplang/discussions/9663"&gt;делитесь обратной связью на GitHub&lt;/a&gt;. Это preview, и команда C# активно слушает. Ваши граничные случаи и отзывы о дизайне повлияют на финальный релиз.&lt;/p&gt;
&lt;p&gt;Полную языковую справку смотрите в &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/union"&gt;документации по типам-объединениям&lt;/a&gt; и &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/proposals/unions"&gt;спецификации фичи&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Aspire 13.2 получает CLI для документации — и ваш ИИ-агент тоже может им пользоваться</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-docs-cli-ai-skills/</link><pubDate>Sat, 04 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-docs-cli-ai-skills/</guid><description>.NET Aspire 13.2 добавляет aspire docs — CLI для поиска, просмотра и чтения официальной документации, не покидая терминал. Он также работает как инструмент для ИИ-агентов. Вот почему это важно.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-docs-cli-ai-skills/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Знаете тот момент, когда вы погружены в Aspire AppHost, подключаете интеграции, и вам нужно проверить, какие именно параметры ожидает интеграция Redis? Вы переключаетесь Alt-Tab на браузер, ищете на aspire.dev, вглядываетесь в документацию API, возвращаетесь в редактор. Контекст потерян. Поток прерван.&lt;/p&gt;
&lt;p&gt;Aspire 13.2 только что &lt;a href="https://devblogs.microsoft.com/aspire/aspire-docs-in-your-terminal/"&gt;выпустил решение этой проблемы&lt;/a&gt;. CLI &lt;code&gt;aspire docs&lt;/code&gt; позволяет искать, просматривать и читать официальную документацию Aspire прямо из терминала. А поскольку за ним стоят переиспользуемые сервисы, ИИ-агенты и навыки могут использовать те же самые команды для поиска документации вместо того, чтобы галлюцинировать несуществующие API.&lt;/p&gt;
&lt;h2 id="проблема-которую-это-действительно-решает"&gt;Проблема, которую это действительно решает&lt;/h2&gt;
&lt;p&gt;David Pine точно подмечает в оригинальном посте: ИИ-агенты были &lt;em&gt;ужасны&lt;/em&gt; в помощи разработчикам при создании приложений на Aspire. Они рекомендовали &lt;code&gt;dotnet run&lt;/code&gt; вместо &lt;code&gt;aspire run&lt;/code&gt;, ссылались на learn.microsoft.com для документации, которая живёт на aspire.dev, предлагали устаревшие NuGet-пакеты, и — моё любимое — галлюцинировали API, которых не существует.&lt;/p&gt;
&lt;p&gt;Почему? Потому что Aspire был специфичен для .NET гораздо дольше, чем является полиглотом, а LLM работают на тренировочных данных, которые предшествуют последним возможностям. Когда вы даёте ИИ-агенту возможность реально искать актуальную документацию, он перестаёт угадывать и начинает быть полезным.&lt;/p&gt;
&lt;h2 id="три-команды-ноль-вкладок-браузера"&gt;Три команды, ноль вкладок браузера&lt;/h2&gt;
&lt;p&gt;CLI освежающе прост:&lt;/p&gt;
&lt;h3 id="показать-всю-документацию"&gt;Показать всю документацию&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Возвращает каждую страницу документации, доступную на aspire.dev. Нужен машиночитаемый вывод? Добавьте &lt;code&gt;--format Json&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="поиск-по-теме"&gt;Поиск по теме&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs search &lt;span class="s2"&gt;&amp;#34;redis&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ищет и по заголовкам, и по содержимому с взвешенной оценкой релевантности. Тот же поисковый движок, который используется внутренне в инструментах документации. Вы получаете ранжированные результаты с заголовками, слагами и оценками релевантности.&lt;/p&gt;
&lt;h3 id="чтение-полной-страницы-или-только-одного-раздела"&gt;Чтение полной страницы (или только одного раздела)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs get redis-integration
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Выводит полную страницу в формате markdown в ваш терминал. Нужен только один раздел?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs get redis-integration --section &lt;span class="s2"&gt;&amp;#34;Add Redis resource&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Хирургическая точность. Никакого прокручивания 500 строк. Только нужная часть.&lt;/p&gt;
&lt;h2 id="аспект-ии-агентов"&gt;Аспект ИИ-агентов&lt;/h2&gt;
&lt;p&gt;Вот где становится интересно для нас, разработчиков, работающих с ИИ-инструментами. Те же команды &lt;code&gt;aspire docs&lt;/code&gt; работают как инструменты для ИИ-агентов — через навыки, MCP-серверы или простые CLI-обёртки.&lt;/p&gt;
&lt;p&gt;Вместо того чтобы ваш ИИ-ассистент придумывал API Aspire на основе устаревших тренировочных данных, он может вызвать &lt;code&gt;aspire docs search &amp;quot;postgres&amp;quot;&lt;/code&gt;, найти официальную документацию по интеграции, прочитать нужную страницу и дать вам документированный подход. Актуальная документация в реальном времени — а не то, что модель запомнила шесть месяцев назад.&lt;/p&gt;
&lt;p&gt;Архитектура за этим — намеренная. Команда Aspire создала переиспользуемые сервисы (&lt;code&gt;IDocsIndexService&lt;/code&gt;, &lt;code&gt;IDocsSearchService&lt;/code&gt;, &lt;code&gt;IDocsFetcher&lt;/code&gt;, &lt;code&gt;IDocsCache&lt;/code&gt;) вместо одноразовой интеграции. Это значит, что один и тот же поисковый движок работает для людей в терминале, ИИ-агентов в редакторе и автоматизации в CI-пайплайне.&lt;/p&gt;
&lt;h2 id="реальные-сценарии"&gt;Реальные сценарии&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Быстрые справки в терминале:&lt;/strong&gt; Вы на три файла в глубину и вам нужны параметры конфигурации Redis. Две команды, девяносто секунд, обратно к работе:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs search &lt;span class="s2"&gt;&amp;#34;redis&amp;#34;&lt;/span&gt; --limit &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs get redis-integration --section &lt;span class="s2"&gt;&amp;#34;Configuration&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Разработка с помощью ИИ:&lt;/strong&gt; Ваш навык VS Code оборачивает команды CLI. Вы спрашиваете «Добавь базу данных PostgreSQL в мой AppHost», и агент сначала смотрит реальную документацию, а потом отвечает. Никаких галлюцинаций.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Валидация CI/CD:&lt;/strong&gt; Ваш пайплайн программно проверяет конфигурации AppHost по официальной документации. Вывод &lt;code&gt;--format Json&lt;/code&gt; чисто передаётся в &lt;code&gt;jq&lt;/code&gt; и другие инструменты.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пользовательские базы знаний:&lt;/strong&gt; Создаёте свои ИИ-инструменты? Направляйте структурированный JSON-вывод напрямую в свою базу знаний:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs search &lt;span class="s2"&gt;&amp;#34;monitoring&amp;#34;&lt;/span&gt; --format Json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;[.[] | {slug, title, summary}]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Никакого веб-скрейпинга. Никаких API-ключей. Те же структурированные данные, которые используются внутренне инструментами документации.&lt;/p&gt;
&lt;h2 id="документация-всегда-актуальна"&gt;Документация всегда актуальна&lt;/h2&gt;
&lt;p&gt;Это то, что я ценю больше всего. CLI не скачивает снимок — он обращается к aspire.dev с кэшированием на основе ETag. В момент обновления документации ваш CLI и любой навык, построенный на его основе, отражает это. Никаких устаревших копий, никаких моментов «но в вики было написано&amp;hellip;».&lt;/p&gt;
&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;aspire docs&lt;/code&gt; — это одна из тех маленьких функций, которая решает реальную проблему чисто и элегантно. Люди получают доступ к документации прямо в терминале. ИИ-агенты получают способ перестать угадывать и начать ссылаться на реальные документы. И всё это подкреплено одним и тем же источником истины.&lt;/p&gt;
&lt;p&gt;Если вы разрабатываете на .NET Aspire и ещё не попробовали CLI, запустите &lt;code&gt;aspire docs search &amp;quot;ваша-тема&amp;quot;&lt;/code&gt; и почувствуйте, как это работает. Затем подумайте о том, чтобы обернуть эти команды в свои ИИ-навыки или настройки автоматизации — ваши агенты скажут вам спасибо.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://davidpine.dev/posts/aspire-docs-mcp-tools/"&gt;глубоким разбором David Pine&lt;/a&gt; о том, как создавались инструменты документации, и с &lt;a href="https://aspire.dev/reference/cli/commands/aspire-docs/"&gt;официальной справкой CLI&lt;/a&gt; для всех деталей.&lt;/p&gt;</content:encoded></item><item><title>Microsoft Agent Framework Достиг 1.0 — Вот Что Действительно Важно для .NET-Разработчиков</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agent-framework-1-0-production-ready/</link><pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agent-framework-1-0-production-ready/</guid><description>Microsoft Agent Framework 1.0 готов к продакшену со стабильными API, мульти-агентной оркестрацией и коннекторами для всех основных AI-провайдеров. Вот что вам нужно знать как .NET-разработчику.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agent-framework-1-0-production-ready/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы следили за путешествием Agent Framework с ранних дней Semantic Kernel и AutoGen, это событие значительное. Microsoft Agent Framework только что &lt;a href="https://devblogs.microsoft.com/agent-framework/microsoft-agent-framework-version-1-0/"&gt;достиг версии 1.0&lt;/a&gt; — готов к продакшену, стабильные API, обязательство долгосрочной поддержки. Он доступен и для .NET, и для Python, и действительно готов к реальным нагрузкам.&lt;/p&gt;
&lt;p&gt;Давайте пробьёмся через шум анонса и сосредоточимся на том, что важно, если вы создаёте AI-приложения на .NET.&lt;/p&gt;
&lt;h2 id="коротко"&gt;Коротко&lt;/h2&gt;
&lt;p&gt;Agent Framework 1.0 объединяет то, что раньше было Semantic Kernel и AutoGen, в единый SDK с открытым исходным кодом. Одна абстракция агента. Один движок оркестрации. Множество AI-провайдеров. Если вы метались между Semantic Kernel для корпоративных паттернов и AutoGen для исследовательских мульти-агентных рабочих процессов, можете остановиться. Теперь это единственный SDK.&lt;/p&gt;
&lt;h2 id="начать-работу-почти-нечестно-просто"&gt;Начать работу почти нечестно просто&lt;/h2&gt;
&lt;p&gt;Вот работающий агент на .NET:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// dotnet add package Microsoft.Agents.AI.OpenAI --prerelease&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI.Foundry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.Identity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;https://your-project.services.ai.azure.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetResponsesClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;gpt-5.3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;HaikuBot&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;You are an upbeat assistant that writes beautifully.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Write a haiku about shipping 1.0.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вот и всё. Несколько строк — и у вас есть AI-агент, работающий через Azure Foundry. Эквивалент на Python столь же лаконичен. Добавляйте инструменты-функции, многоходовые диалоги и стриминг по мере необходимости — поверхность API масштабируется без странностей.&lt;/p&gt;
&lt;h2 id="мульти-агентная-оркестрация--это-серьёзно"&gt;Мульти-агентная оркестрация — это серьёзно&lt;/h2&gt;
&lt;p&gt;Одиночные агенты подходят для демо, но продакшен-сценарии обычно требуют координации. Agent Framework 1.0 поставляется с проверенными в бою паттернами оркестрации прямо из Microsoft Research и AutoGen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Последовательная&lt;/strong&gt; — агенты обрабатывают по очереди (писатель → рецензент → редактор)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Параллельная&lt;/strong&gt; — распределение по нескольким агентам параллельно, объединение результатов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handoff&lt;/strong&gt; — один агент делегирует другому на основе намерения&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Групповой чат&lt;/strong&gt; — несколько агентов обсуждают и сходятся к решению&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Magentic-One&lt;/strong&gt; — исследовательский мульти-агентный паттерн от MSR&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Все поддерживают стриминг, чекпоинты, одобрения с участием человека и паузу/возобновление. Часть с чекпоинтами критически важна — долго работающие процессы переживают перезапуски. Для нас, .NET-разработчиков, строивших устойчивые рабочие процессы с Azure Functions, это знакомое ощущение.&lt;/p&gt;
&lt;h2 id="самые-важные-возможности"&gt;Самые важные возможности&lt;/h2&gt;
&lt;p&gt;Вот мой список того, что стоит знать:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Middleware-хуки.&lt;/strong&gt; Знаете, как ASP.NET Core имеет middleware-конвейеры? Тот же концепт, но для выполнения агентов. Перехватывайте каждый этап — добавляйте безопасность контента, логирование, политики соответствия — не трогая промпты агента. Именно так вы делаете агентов готовыми для enterprise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Подключаемая память.&lt;/strong&gt; История разговоров, персистентное key-value состояние, векторный поиск. Выбирайте бэкенд: Foundry Agent Service, Mem0, Redis, Neo4j или создайте свой. Память — это то, что превращает stateless-вызов LLM в агента, который действительно помнит контекст.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Декларативные YAML-агенты.&lt;/strong&gt; Определяйте инструкции агента, инструменты, память и топологию оркестрации в версионируемых YAML-файлах. Загружайте и запускайте одним вызовом API. Это меняет правила игры для команд, которые хотят итерировать поведение агента без редеплоя кода.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Поддержка A2A и MCP.&lt;/strong&gt; MCP (Model Context Protocol) позволяет агентам динамически обнаруживать и вызывать внешние инструменты. A2A (протокол Agent-to-Agent) обеспечивает кросс-рантайм взаимодействие — ваши .NET-агенты могут координироваться с агентами в других фреймворках. Поддержка A2A 1.0 появится в ближайшее время.&lt;/p&gt;
&lt;h2 id="превью-возможности-за-которыми-стоит-следить"&gt;Превью-возможности, за которыми стоит следить&lt;/h2&gt;
&lt;p&gt;Некоторые возможности вышли в превью в 1.0 — функциональны, но API могут измениться:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DevUI&lt;/strong&gt; — локальный отладчик в браузере для визуализации выполнения агента, потоков сообщений и вызовов инструментов в реальном времени. Представьте Application Insights, но для рассуждений агента.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub Copilot SDK и Claude Code SDK&lt;/strong&gt; — используйте Copilot или Claude как агентную обвязку прямо из кода оркестрации. Составляйте агента с возможностями программирования рядом с другими агентами в одном рабочем процессе.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent Harness&lt;/strong&gt; — настраиваемый локальный рантайм, дающий агентам доступ к шеллу, файловой системе и циклам обмена сообщениями. Думайте о кодинг-агентах и паттернах автоматизации.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skills&lt;/strong&gt; — переиспользуемые пакеты доменных возможностей, дающие агентам структурированные способности из коробки.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="миграция-с-semantic-kernel-или-autogen"&gt;Миграция с Semantic Kernel или AutoGen&lt;/h2&gt;
&lt;p&gt;Если у вас есть существующий код на Semantic Kernel или AutoGen, есть специальные помощники миграции, которые анализируют ваш код и генерируют пошаговые планы миграции. &lt;a href="https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-semantic-kernel"&gt;Руководство по миграции с Semantic Kernel&lt;/a&gt; и &lt;a href="https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-autogen"&gt;руководство по миграции с AutoGen&lt;/a&gt; проведут вас через всё.&lt;/p&gt;
&lt;p&gt;Если вы были на RC-пакетах, обновление до 1.0 — это просто смена версии.&lt;/p&gt;
&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;Agent Framework 1.0 — это продакшен-веха, которую ждали корпоративные команды. Стабильные API, поддержка нескольких провайдеров, паттерны оркестрации, реально работающие в масштабе, и пути миграции как с Semantic Kernel, так и с AutoGen.&lt;/p&gt;
&lt;p&gt;Фреймворк &lt;a href="https://github.com/microsoft/agent-framework"&gt;полностью открыт на GitHub&lt;/a&gt;, и вы можете начать прямо сейчас с &lt;code&gt;dotnet add package Microsoft.Agents.AI&lt;/code&gt;. Посмотрите &lt;a href="https://learn.microsoft.com/en-us/agent-framework/get-started/"&gt;руководство по быстрому старту&lt;/a&gt; и &lt;a href="https://github.com/microsoft/agent-framework"&gt;примеры&lt;/a&gt;, чтобы попробовать на практике.&lt;/p&gt;
&lt;p&gt;Если вы ждали сигнала «безопасно использовать в продакшене» — вот он.&lt;/p&gt;</content:encoded></item><item><title>azd теперь позволяет запускать и отлаживать ИИ-агенты локально — Что изменилось в марте 2026</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-march-2026-local-ai-agent-debugging/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-march-2026-local-ai-agent-debugging/</guid><description>Azure Developer CLI выпустил семь версий в марте 2026. Главное: локальный цикл запуска и отладки для ИИ-агентов, интеграция GitHub Copilot в настройке проектов и поддержка Container App Jobs.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azd-march-2026-local-ai-agent-debugging/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Семь релизов за месяц. Именно столько выпустила команда Azure Developer CLI (&lt;code&gt;azd&lt;/code&gt;) в марте 2026, и главная фича — та, которую я ждал: &lt;strong&gt;локальный цикл запуска и отладки для ИИ-агентов&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;PC Chan &lt;a href="https://devblogs.microsoft.com/azure-sdk/azure-developer-cli-azd-march-2026/"&gt;опубликовала полный обзор&lt;/a&gt;, и хотя там много всего, позвольте мне отфильтровать то, что действительно важно для .NET-разработчиков, создающих приложения с ИИ.&lt;/p&gt;
&lt;h2 id="запуск-и-отладка-ии-агентов-без-деплоя"&gt;Запуск и отладка ИИ-агентов без деплоя&lt;/h2&gt;
&lt;p&gt;Это главное. Новое расширение &lt;code&gt;azure.ai.agents&lt;/code&gt; добавляет команды для полноценного inner-loop для ИИ-агентов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;azd ai agent run&lt;/code&gt; — запускает агент локально&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azd ai agent invoke&lt;/code&gt; — отправляет сообщения (локально или в продакшн)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azd ai agent show&lt;/code&gt; — показывает статус контейнера и здоровье&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azd ai agent monitor&lt;/code&gt; — стримит логи контейнера в реальном времени&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Раньше тестирование ИИ-агента означало деплой в Microsoft Foundry при каждом изменении. Теперь можно итерировать локально, тестировать поведение агента и деплоить только когда готов.&lt;/p&gt;
&lt;h2 id="github-copilot-настраивает-ваш-azd-проект"&gt;GitHub Copilot настраивает ваш azd-проект&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;azd init&lt;/code&gt; теперь предлагает опцию &amp;ldquo;Set up with GitHub Copilot (Preview)&amp;rdquo;. Вместо ручного ответа на промпты, Copilot-агент генерирует конфигурацию за вас. Когда команда падает, &lt;code&gt;azd&lt;/code&gt; предлагает ИИ-ассистированное устранение неполадок — всё не выходя из терминала.&lt;/p&gt;
&lt;h2 id="container-app-jobs-и-улучшения-деплоя"&gt;Container App Jobs и улучшения деплоя&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Container App Jobs&lt;/strong&gt;: &lt;code&gt;azd&lt;/code&gt; теперь деплоит &lt;code&gt;Microsoft.App/jobs&lt;/code&gt; через существующую конфигурацию &lt;code&gt;host: containerapp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Настраиваемые таймауты деплоя&lt;/strong&gt;: Новый флаг &lt;code&gt;--timeout&lt;/code&gt; в &lt;code&gt;azd deploy&lt;/code&gt; и поле &lt;code&gt;deployTimeout&lt;/code&gt; в &lt;code&gt;azure.yaml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Фолбэк удалённой сборки&lt;/strong&gt;: При неудаче ACR-сборки &lt;code&gt;azd&lt;/code&gt; автоматически переключается на локальный Docker/Podman.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Локальная preflight-валидация&lt;/strong&gt;: Bicep-параметры проверяются локально перед деплоем.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="улучшения-dx"&gt;Улучшения DX&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Автоматическое определение pnpm/yarn&lt;/strong&gt; для JS/TS-проектов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Поддержка pyproject.toml&lt;/strong&gt; для Python&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Локальные каталоги шаблонов&lt;/strong&gt; — &lt;code&gt;azd init --template&lt;/code&gt; принимает пути файловой системы&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Улучшенные сообщения об ошибках&lt;/strong&gt; в режиме &lt;code&gt;--no-prompt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Переменные окружения сборки&lt;/strong&gt; — инжектируются во все подпроцессы сборки (.NET, Node.js, Java, Python)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Локальный цикл отладки ИИ-агентов — звезда этого релиза, но совокупность улучшений деплоя и DX делает &lt;code&gt;azd&lt;/code&gt; более зрелым, чем когда-либо. Если вы деплоите .NET-приложения в Azure — особенно ИИ-агенты — это обновление стоит внимания.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/azure-sdk/azure-developer-cli-azd-march-2026/"&gt;полными заметками о выпуске&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Azure DevOps наконец-то исправил Markdown-редактор, на который все жаловались</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-markdown-editor-work-items/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-markdown-editor-work-items/</guid><description>Markdown-редактор Azure DevOps для рабочих элементов получает более чёткое разделение между режимами просмотра и редактирования. Маленькое изменение, которое решает действительно раздражающую проблему.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-markdown-editor-work-items/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы используете Azure Boards, вы наверняка сталкивались с этим: читаете описание рабочего элемента, может проверяете критерии приёмки, и случайно делаете двойной клик. Бум — вы в режиме редактирования. Вы ничего не хотели редактировать. Просто читали.&lt;/p&gt;
&lt;p&gt;Dan Hellem &lt;a href="https://devblogs.microsoft.com/devops/improving-the-markdown-editor-for-work-items/"&gt;объявил об исправлении&lt;/a&gt;, и это одно из тех изменений, которые звучат мелко, но реально убирают трение из повседневного рабочего процесса.&lt;/p&gt;
&lt;h2 id="что-изменилось"&gt;Что изменилось&lt;/h2&gt;
&lt;p&gt;Markdown-редактор для текстовых полей рабочих элементов теперь открывается в &lt;strong&gt;режиме просмотра по умолчанию&lt;/strong&gt;. Можно читать контент и взаимодействовать с ним — переходить по ссылкам, проверять форматирование — не беспокоясь о случайном входе в режим редактирования.&lt;/p&gt;
&lt;p&gt;Когда действительно хотите редактировать, нажмите на иконку редактирования вверху поля. Закончили — явно вернитесь в режим просмотра. Просто, намеренно, предсказуемо.&lt;/p&gt;
&lt;h2 id="почему-это-важнее-чем-кажется"&gt;Почему это важнее, чем кажется&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://developercommunity.visualstudio.com/t/Markdown-editor-for-work-item-multi-line/10935496"&gt;Тред обратной связи от сообщества&lt;/a&gt; был длинным. Поведение двойного клика для редактирования было введено с Markdown-редактором в июле 2025, и жалобы начались почти сразу.&lt;/p&gt;
&lt;p&gt;Для команд, которые делают планирование спринтов, уточнение бэклога или код-ревью в Azure Boards, такое микро-трение накапливается.&lt;/p&gt;
&lt;h2 id="статус-развёртывания"&gt;Статус развёртывания&lt;/h2&gt;
&lt;p&gt;Уже раскатывается для части пользователей и расширится на всех в ближайшие две-три недели.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Не каждое улучшение должно быть заголовочной фичей. Иногда лучшее обновление — просто убрать что-то раздражающее. Это именно такой случай — маленький UX-фикс, который делает Azure Boards менее враждебным для людей, которые просто хотят спокойно прочитать свои рабочие элементы.&lt;/p&gt;</content:encoded></item><item><title>Bookmark Studio добавляет слотовую навигацию и обмен закладками в Visual Studio</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/bookmark-studio-visual-studio-extension/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/bookmark-studio-visual-studio-extension/</guid><description>Новое расширение Bookmark Studio от Mads Kristensen добавляет навигацию по слотам с клавиатуры, менеджер закладок, цвета, метки и возможности экспорта к закладкам Visual Studio.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/bookmark-studio-visual-studio-extension/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Закладки в Visual Studio всегда были&amp;hellip; нормальными. Ставишь одну, переходишь к следующей, забываешь какая есть какая. Работают, но никогда не были чем-то, что назвали бы мощным.&lt;/p&gt;
&lt;p&gt;Mads Kristensen только что &lt;a href="https://devblogs.microsoft.com/visualstudio/bookmark-studio-evolving-bookmarks-in-visual-studio/"&gt;выпустил Bookmark Studio&lt;/a&gt; — экспериментальное расширение, которое заполняет именно те пробелы, с которыми вы, вероятно, сталкивались.&lt;/p&gt;
&lt;h2 id="слотовая-навигация"&gt;Слотовая навигация&lt;/h2&gt;
&lt;p&gt;Закладки можно назначить на слоты 1–9 и перейти к ним напрямую через &lt;code&gt;Alt+Shift+1&lt;/code&gt; по &lt;code&gt;Alt+Shift+9&lt;/code&gt;. Новые закладки автоматически получают следующий свободный слот.&lt;/p&gt;
&lt;h2 id="менеджер-закладок"&gt;Менеджер закладок&lt;/h2&gt;
&lt;p&gt;Новое окно инструментов показывает все закладки с фильтрацией по имени, файлу, расположению, цвету или слоту.&lt;/p&gt;
&lt;h2 id="организация-с-метками-цветами-и-папками"&gt;Организация с метками, цветами и папками&lt;/h2&gt;
&lt;p&gt;Закладки могут иметь метки, цвета и группироваться в папки. Метаданные сохраняются по solution.&lt;/p&gt;
&lt;h2 id="экспорт-и-обмен"&gt;Экспорт и обмен&lt;/h2&gt;
&lt;p&gt;Bookmark Studio позволяет экспортировать закладки как текст, Markdown или CSV.&lt;/p&gt;
&lt;h2 id="закладки-следующие-за-кодом"&gt;Закладки, следующие за кодом&lt;/h2&gt;
&lt;p&gt;Bookmark Studio отслеживает закладки относительно привязанного текста, поэтому они не сдвигаются на неправильные строки при редактировании.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Bookmark Studio ничего не переизобретает. Берёт функцию, которая годами была «достаточной», и делает её действительно полезной. Скачайте из &lt;a href="https://marketplace.visualstudio.com/items?itemName=MadsKristensen.BookmarkStudio"&gt;Visual Studio Marketplace&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Дашборд Aspire 13.2 теперь с API телеметрии — и это меняет всё</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-dashboard-export-telemetry/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-dashboard-export-telemetry/</guid><description>.NET Aspire 13.2 приносит умный экспорт телеметрии, программируемый API для трейсов и логов, а также улучшения визуализации GenAI. Вот почему это важно для вашего рабочего процесса отладки.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/aspire-132-dashboard-export-telemetry/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Если вы создавали распределённые приложения на .NET Aspire, вы уже знаете, что дашборд — лучшая часть всего опыта. Все ваши трейсы, логи и метрики в одном месте — без внешнего Jaeger, без настройки Seq, без моментов «дай проверю другой терминал».&lt;/p&gt;
&lt;p&gt;Aspire 13.2 значительно всё улучшил. James Newton-King &lt;a href="https://devblogs.microsoft.com/aspire/aspire-dashboard-improvements-export-and-telemetry/"&gt;объявил об обновлении&lt;/a&gt;, и честно? Функции экспорта телеметрии и API сами по себе стоят обновления.&lt;/p&gt;
&lt;h2 id="экспорт-телеметрии-по-человечески"&gt;Экспорт телеметрии по-человечески&lt;/h2&gt;
&lt;p&gt;Вот сценарий, который мы все пережили: вы отлаживаете распределённую проблему, наконец воспроизводите её после двадцати минут настройки, и теперь нужно показать команде, что произошло. Раньше? Скриншоты. Копирование ID трейсов. Обычный хаос.&lt;/p&gt;
&lt;p&gt;Aspire 13.2 добавляет диалог &lt;strong&gt;Управление логами и телеметрией&lt;/strong&gt;, где можно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Очистить всю телеметрию (полезно перед попыткой воспроизведения)&lt;/li&gt;
&lt;li&gt;Экспортировать выбранную телеметрию в ZIP-файл в стандартном формате OTLP/JSON&lt;/li&gt;
&lt;li&gt;Повторно импортировать этот ZIP в любой дашборд Aspire позже&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Последний пункт — это убийственная фича. Вы воспроизводите баг, экспортируете телеметрию, прикрепляете к рабочему элементу, и ваш коллега может импортировать её в свой дашборд, чтобы увидеть именно то, что видели вы. Больше никаких «можешь воспроизвести у себя?»&lt;/p&gt;
&lt;p&gt;Отдельные трейсы, спаны и логи также получили опцию «Export JSON» в контекстных меню. Нужно поделиться конкретным трейсом? Правый клик, копируете JSON, вставляете в описание PR. Готово.&lt;/p&gt;
&lt;h2 id="api-телеметрии--настоящий-прорыв"&gt;API телеметрии — настоящий прорыв&lt;/h2&gt;
&lt;p&gt;Вот чему я больше всего рад. Дашборд теперь предоставляет HTTP API по пути &lt;code&gt;/api/telemetry&lt;/code&gt; для программного запроса данных телеметрии. Доступные эндпоинты:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/resources&lt;/code&gt; — список ресурсов с телеметрией&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/spans&lt;/code&gt; — запрос спанов с фильтрами&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/logs&lt;/code&gt; — запрос логов с фильтрами&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/traces&lt;/code&gt; — список трейсов&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/traces/{traceId}&lt;/code&gt; — все спаны конкретного трейса&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Всё возвращается в формате OTLP JSON. Это питает новые CLI-команды &lt;code&gt;aspire agent mcp&lt;/code&gt; и &lt;code&gt;aspire otel&lt;/code&gt;, но реальное значение больше: теперь можно создавать инструменты, скрипты и интеграции с ИИ-агентами, которые напрямую запрашивают телеметрию вашего приложения.&lt;/p&gt;
&lt;p&gt;Представьте ИИ-агента для кодинга, который может видеть ваши реальные распределённые трейсы во время отладки. Это уже не гипотетически — именно это делает возможным этот API.&lt;/p&gt;
&lt;h2 id="телеметрия-genai-становится-практичной"&gt;Телеметрия GenAI становится практичной&lt;/h2&gt;
&lt;p&gt;Если вы создаёте приложения с ИИ на Semantic Kernel или Microsoft.Extensions.AI, вам понравится улучшенный визуализатор телеметрии GenAI. Aspire 13.2 добавляет:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Описания ИИ-инструментов отображаются как Markdown&lt;/li&gt;
&lt;li&gt;Специальная кнопка GenAI на странице трейсов для быстрого доступа&lt;/li&gt;
&lt;li&gt;Улучшенная обработка ошибок для обрезанного или нестандартного JSON GenAI&lt;/li&gt;
&lt;li&gt;Навигация с подсветкой по клику между определениями инструментов&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Пост упоминает, что VS Code Copilot chat, Copilot CLI и OpenCode поддерживают настройку &lt;code&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;/code&gt;. Направьте их на дашборд Aspire, и вы буквально сможете наблюдать, как ваши ИИ-агенты думают в реальном времени через телеметрию. Такой опыт отладки вы больше нигде не найдёте.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Aspire 13.2 превращает дашборд из «приятного UI для отладки» в «программируемую платформу наблюдаемости». Рабочий процесс экспорта/импорта сам по себе экономит реальное время при распределённой отладке, а API телеметрии открывает дверь к диагностике с помощью ИИ.&lt;/p&gt;
&lt;p&gt;Если вы уже на Aspire — обновляйтесь. Если нет — это хороший повод попробовать &lt;a href="https://aspire.dev"&gt;aspire.dev&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Мартовское обновление Visual Studio позволяет создавать собственные агенты Copilot — и find_symbol меняет правила игры</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/visual-studio-march-2026-custom-copilot-agents/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/visual-studio-march-2026-custom-copilot-agents/</guid><description>Мартовское обновление Visual Studio 2026 приносит пользовательские агенты Copilot, переиспользуемые навыки, инструмент find_symbol с поддержкой языков и профилирование с Copilot из Test Explorer.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/visual-studio-march-2026-custom-copilot-agents/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Visual Studio только что получила самое значительное обновление Copilot. Mark Downie &lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-march-update-build-your-own-custom-agents/"&gt;объявил о мартовском релизе&lt;/a&gt;, и заголовок — пользовательские агенты, но честно говоря, инструмент &lt;code&gt;find_symbol&lt;/code&gt; может оказаться функцией, которая больше всего изменит ваш рабочий процесс.&lt;/p&gt;
&lt;h2 id="пользовательские-агенты-copilot-в-вашем-репозитории"&gt;Пользовательские агенты Copilot в вашем репозитории&lt;/h2&gt;
&lt;p&gt;Хотите, чтобы Copilot следовал стандартам кодирования вашей команды? Пользовательские агенты определяются как файлы &lt;code&gt;.agent.md&lt;/code&gt; в &lt;code&gt;.github/agents/&lt;/code&gt;. Каждый агент имеет полный доступ к workspace, пониманию кода, инструментам, вашей предпочтительной модели и MCP-соединениям.&lt;/p&gt;
&lt;h2 id="навыки-агента-переиспользуемые-наборы-инструкций"&gt;Навыки агента: переиспользуемые наборы инструкций&lt;/h2&gt;
&lt;p&gt;Навыки автоматически подхватываются из &lt;code&gt;.github/skills/&lt;/code&gt; в вашем репозитории или &lt;code&gt;~/.copilot/skills/&lt;/code&gt; в профиле.&lt;/p&gt;
&lt;h2 id="find_symbol-навигация-с-поддержкой-языка"&gt;find_symbol: навигация с поддержкой языка&lt;/h2&gt;
&lt;p&gt;Новый инструмент &lt;code&gt;find_symbol&lt;/code&gt; даёт агентному режиму Copilot навигацию по символам на основе языковых сервисов. Вместо текстового поиска агент может находить все ссылки на символ и получать доступ к информации о типах и области видимости.&lt;/p&gt;
&lt;p&gt;Для .NET-разработчиков это огромное улучшение — кодовые базы на C# с глубокими иерархиями типов получают огромную пользу.&lt;/p&gt;
&lt;h2 id="профилирование-тестов-с-copilot"&gt;Профилирование тестов с Copilot&lt;/h2&gt;
&lt;p&gt;В контекстном меню Test Explorer появился &lt;strong&gt;Profile with Copilot&lt;/strong&gt;. Profiling Agent запускает тест и автоматически анализирует производительность.&lt;/p&gt;
&lt;h2 id="perf-tips-во-время-отладки"&gt;Perf Tips во время отладки&lt;/h2&gt;
&lt;p&gt;Оптимизация производительности теперь происходит прямо во время отладки. Visual Studio показывает время выполнения inline. Увидели медленную строку? Кликните Perf Tip и попросите Copilot предложить оптимизации.&lt;/p&gt;
&lt;h2 id="исправление-уязвимостей-nuget-из-solution-explorer"&gt;Исправление уязвимостей NuGet из Solution Explorer&lt;/h2&gt;
&lt;p&gt;При обнаружении уязвимости NuGet-пакета в Solution Explorer появляется ссылка &lt;strong&gt;Fix with GitHub Copilot&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="подведём-итоги"&gt;Подведём итоги&lt;/h2&gt;
&lt;p&gt;Пользовательские агенты и навыки — заголовок, но &lt;code&gt;find_symbol&lt;/code&gt; — скрытая жемчужина, которая фундаментально меняет точность Copilot при рефакторинге .NET-кода. Скачайте &lt;a href="https://visualstudio.microsoft.com/downloads/"&gt;Visual Studio 2026 Insiders&lt;/a&gt;, чтобы всё попробовать.&lt;/p&gt;</content:encoded></item><item><title>KubeCon Europe 2026: Что на самом деле важно для .NET-разработчиков</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/kubecon-2026-aks-updates-dotnet-developers/</link><pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/kubecon-2026-aks-updates-dotnet-developers/</guid><description>Microsoft выпустила массу анонсов Kubernetes на KubeCon Europe 2026. Вот отфильтрованная версия — только обновления AKS и cloud-native, которые важны, если вы поставляете .NET-приложения.</description><content:encoded>&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно прочитать &lt;a href="https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/kubecon-2026-aks-updates-dotnet-developers/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Знаете это чувство, когда выходит огромный пост с анонсами и вы листаете его, думая «круто, но что это на самом деле меняет для меня»? Это я каждый сезон KubeCon.&lt;/p&gt;
&lt;p&gt;Microsoft только что опубликовала свой &lt;a href="https://opensource.microsoft.com/blog/2026/03/24/whats-new-with-microsoft-in-open-source-and-kubernetes-at-kubecon-cloudnativecon-europe-2026/"&gt;полный обзор KubeCon Europe 2026&lt;/a&gt; — написанный лично Бренданом Бёрнсом — и честно? Здесь настоящая суть. Не просто чеклисты фич, а операционные улучшения, которые меняют подход к управлению в продакшене.&lt;/p&gt;
&lt;p&gt;Давайте разберём, что действительно важно для нас, .NET-разработчиков.&lt;/p&gt;
&lt;h2 id="mtls-без-налога-service-mesh"&gt;mTLS без налога service mesh&lt;/h2&gt;
&lt;p&gt;Вот в чём дело с service mesh: все хотят гарантий безопасности, никто не хочет операционной нагрузки. AKS наконец закрывает этот разрыв.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://aka.ms/aks/application-network"&gt;Azure Kubernetes Application Network&lt;/a&gt; даёт вам mutual TLS, авторизацию с учётом приложения и телеметрию трафика — без развёртывания полного mesh с тяжёлыми sidecar. В сочетании с &lt;a href="https://aka.ms/acns/cilium-mtls"&gt;Cilium mTLS в Advanced Container Networking Services&lt;/a&gt; вы получаете зашифрованную связь между подами с использованием сертификатов X.509 и SPIRE для управления идентификацией.&lt;/p&gt;
&lt;p&gt;Что это значит на практике: ваши ASP.NET Core API общаются с фоновыми воркерами, ваши gRPC-сервисы вызывают друг друга — всё зашифровано и верифицировано на сетевом уровне, без единого изменения в коде приложения. Это серьёзно.&lt;/p&gt;
&lt;p&gt;Для команд, мигрирующих с &lt;code&gt;ingress-nginx&lt;/code&gt;, есть также &lt;a href="https://aka.ms/aks/app-routing/gateway-api"&gt;Application Routing с Meshless Istio&lt;/a&gt; с полной поддержкой Kubernetes Gateway API. Без sidecar. На основе стандартов. Плюс инструменты &lt;code&gt;ingress2gateway&lt;/code&gt; для постепенной миграции.&lt;/p&gt;
&lt;h2 id="наблюдаемость-gpu--не-как-запоздалая-мысль"&gt;Наблюдаемость GPU — не как запоздалая мысль&lt;/h2&gt;
&lt;p&gt;Если вы запускаете AI-инференс рядом с .NET-сервисами (а давайте честно, кто сейчас не начинает?), вы наверняка столкнулись со слепым пятном мониторинга GPU. У вас были отличные дашборды CPU/памяти, а потом&amp;hellip; ничего для GPU без ручной настройки экспортёров.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://aka.ms/aks/managed-gpu-metrics"&gt;AKS теперь показывает метрики GPU нативно&lt;/a&gt; в управляемых Prometheus и Grafana. Тот же стек, те же дашборды, тот же пайплайн алертов. Без кастомных экспортёров, без сторонних агентов.&lt;/p&gt;
&lt;p&gt;На сетевой стороне добавлена видимость по потокам для HTTP, gRPC и Kafka-трафика с &lt;a href="https://learn.microsoft.com/en-us/azure/aks/container-network-observability-logs"&gt;Azure Monitor в один клик&lt;/a&gt;. IP, порты, ворклоуды, направление потока, решения по политикам — всё во встроенных дашбордах.&lt;/p&gt;
&lt;p&gt;А вот то, от чего я посмотрел дважды: &lt;a href="https://learn.microsoft.com/en-us/azure/aks/advanced-container-networking-services-overview"&gt;agentic container networking&lt;/a&gt; добавляет веб-интерфейс, где можно задавать вопросы на естественном языке о состоянии сети кластера. «Почему под X не достигает сервис Y?» → диагностика только для чтения из live-телеметрии. Реально полезно в 2 часа ночи.&lt;/p&gt;
&lt;h2 id="кросс-кластерная-сеть-без-учёной-степени"&gt;Кросс-кластерная сеть без учёной степени&lt;/h2&gt;
&lt;p&gt;Мульти-кластерный Kubernetes исторически был опытом «принеси свой сетевой клей». Azure Kubernetes Fleet Manager теперь обеспечивает &lt;a href="https://aka.ms/kubernetes-fleet/networking/cross-cluster"&gt;кросс-кластерную сеть&lt;/a&gt; через управляемый Cilium cluster mesh:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Единая связность между кластерами AKS&lt;/li&gt;
&lt;li&gt;Глобальный реестр сервисов для кросс-кластерного обнаружения&lt;/li&gt;
&lt;li&gt;Конфигурация управляется централизованно, а не повторяется для каждого кластера&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если вы запускаете .NET-микросервисы в нескольких регионах для отказоустойчивости или соответствия требованиям, это заменяет много хрупкого кастомного клея. Сервис A в West Europe может обнаружить и вызвать Сервис B в East US через mesh, с согласованными политиками маршрутизации и безопасности.&lt;/p&gt;
&lt;h2 id="обновления-не-требующие-смелости"&gt;Обновления, не требующие смелости&lt;/h2&gt;
&lt;p&gt;Давайте честно — обновления Kubernetes в продакшене — это стресс. «Обновить и надеяться» было стратегией по умолчанию для слишком многих команд и главной причиной, по которой кластеры отстают по версиям.&lt;/p&gt;
&lt;p&gt;Две новые возможности меняют это:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blue-green обновления пулов агентов&lt;/strong&gt; создают параллельный пул нод с новой конфигурацией. Валидируйте поведение, постепенно переключайте трафик и сохраняйте чистый путь отката. Больше никаких мутаций на месте на продакшн-нодах.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Откат пула агентов&lt;/strong&gt; позволяет вернуть пул нод на предыдущую версию Kubernetes и образ ноды после неудачного обновления — без пересборки кластера.&lt;/p&gt;
&lt;p&gt;Вместе они наконец дают операторам реальный контроль над жизненным циклом обновлений. Для .NET-команд это важно, потому что скорость платформы напрямую определяет, как быстро вы можете принять новые рантаймы, патчи безопасности и сетевые возможности.&lt;/p&gt;
&lt;h2 id="ai-рабочие-нагрузки-становятся-полноценными-гражданами-kubernetes"&gt;AI-рабочие нагрузки становятся полноценными гражданами Kubernetes&lt;/h2&gt;
&lt;p&gt;Upstream-работа в open source не менее важна. Dynamic Resource Allocation (DRA) только что стала GA в Kubernetes 1.36, сделав планирование GPU настоящей первоклассной функцией вместо обходного пути.&lt;/p&gt;
&lt;p&gt;Проекты, за которыми стоит следить:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Проект&lt;/th&gt;
&lt;th&gt;Что делает&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/kaito-project/kubeairunway"&gt;AI Runway&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Общий Kubernetes API для инференса — деплой моделей без знания K8s, с обнаружением HuggingFace и оценкой стоимости&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.cncf.io/blog/2026/01/07/holmesgpt-agentic-troubleshooting-built-for-the-cloud-native-era/"&gt;HolmesGPT&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Агентный troubleshooting для cloud-native — теперь проект CNCF Sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/project-dalec/dalec"&gt;Dalec&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Декларативная сборка образов контейнеров с генерацией SBOM — меньше CVE на этапе сборки&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Направление ясно: ваш .NET API, слой оркестрации на Semantic Kernel и ваши рабочие нагрузки инференса должны работать на одной согласованной платформенной модели. Мы приближаемся.&lt;/p&gt;
&lt;h2 id="с-чего-бы-я-начал-на-этой-неделе"&gt;С чего бы я начал на этой неделе&lt;/h2&gt;
&lt;p&gt;Если вы оцениваете эти изменения для своей команды, вот мой честный список приоритетов:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Наблюдаемость в первую очередь&lt;/strong&gt; — включите метрики GPU и логи сетевых потоков в непродакшен-кластере. Посмотрите, что вы упускали.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Попробуйте blue-green обновления&lt;/strong&gt; — протестируйте workflow отката перед следующим обновлением продакшен-кластера. Постройте доверие к процессу.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Пилотируйте сеть с учётом идентичности&lt;/strong&gt; — выберите один внутренний путь сервиса и включите mTLS с Cilium. Измерьте оверхед (спойлер: минимальный).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Оцените Fleet Manager&lt;/strong&gt; — если у вас больше двух кластеров, кросс-кластерная сеть окупается за счёт сокращения кастомного клея.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Маленькие эксперименты, быстрая обратная связь. Это всегда правильный ход.&lt;/p&gt;
&lt;h2 id="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;Анонсы KubeCon могут быть ошеломляющими, но эта порция реально двигает стрелку для .NET-команд на AKS. Лучшая сетевая безопасность без оверхеда mesh, настоящая наблюдаемость GPU, более безопасные обновления и более прочные основы AI-инфраструктуры.&lt;/p&gt;
&lt;p&gt;Если вы уже на AKS, сейчас отличный момент укрепить ваш операционный baseline. А если планируете перенести .NET-рабочие нагрузки на Kubernetes — платформа только что стала значительно более готовой к продакшену.&lt;/p&gt;</content:encoded></item><item><title>SQL MCP Server, Copilot в SSMS и Database Hub с ИИ-агентами: что действительно важно с SQLCon 2026</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agentic-ai-microsoft-databases-what-matters/</link><pubDate>Sat, 28 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/agentic-ai-microsoft-databases-what-matters/</guid><description>Microsoft представила целый ряд анонсов по базам данных на SQLCon 2026. Вот что действительно важно, если вы создаёте приложения с ИИ на Azure SQL.</description><content:encoded>&lt;p&gt;Microsoft только что открыла &lt;a href="https://www.microsoft.com/en-us/sql-server/blog/2026/03/18/advancing-agentic-ai-with-microsoft-databases-across-a-unified-data-estate/"&gt;SQLCon 2026 вместе с FabCon в Атланте&lt;/a&gt;, и тут есть что разбирать. Оригинальный анонс охватывает всё — от планов экономии до корпоративных функций соответствия требованиям. Я пропущу слайды с корпоративными ценами и сосредоточусь на том, что важно, если вы разработчик, создающий решения с Azure SQL и ИИ.&lt;/p&gt;
&lt;h2 id="sql-mcp-server-в-публичном-превью"&gt;SQL MCP Server в публичном превью&lt;/h2&gt;
&lt;p&gt;Это главная новость для меня. Azure SQL Database Hyperscale теперь имеет &lt;strong&gt;SQL MCP Server&lt;/strong&gt; в публичном превью, который позволяет безопасно подключать ваши данные SQL к ИИ-агентам и Copilot через &lt;a href="https://modelcontextprotocol.io/"&gt;Model Context Protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Если вы следили за волной MCP — а честно говоря, сейчас это трудно пропустить — это большое дело. Вместо создания пользовательских конвейеров данных для передачи контекста из базы данных вашим ИИ-агентам, вы получаете стандартизированный протокол для прямого предоставления SQL-данных. Ваши агенты могут запрашивать, анализировать и действовать на основе актуальной информации из базы данных.&lt;/p&gt;
&lt;p&gt;Для тех из нас, кто создаёт ИИ-агентов с Semantic Kernel или Microsoft Agent Framework, это открывает чистый путь интеграции. Вашему агенту нужно проверить наличие товара? Найти запись клиента? Валидировать заказ? MCP даёт ему структурированный способ сделать это без написания индивидуального кода получения данных для каждого сценария.&lt;/p&gt;
&lt;h2 id="github-copilot-в-ssms-22-вышел-в-ga"&gt;GitHub Copilot в SSMS 22 вышел в GA&lt;/h2&gt;
&lt;p&gt;Если вы проводите время в SQL Server Management Studio — и будем честны, большинство из нас до сих пор это делает — GitHub Copilot теперь общедоступен в SSMS 22. Тот же опыт Copilot, который вы уже используете в VS Code и Visual Studio, но для T-SQL.&lt;/p&gt;
&lt;p&gt;Практическая ценность понятна: чат-ассистент для написания запросов, рефакторинга хранимых процедур, устранения проблем производительности и выполнения административных задач. Ничего революционного в концепции, но наличие этого прямо в SSMS означает, что вам не нужно переключаться на другой редактор, чтобы получить помощь ИИ при работе с базой данных.&lt;/p&gt;
&lt;h2 id="векторные-индексы-получили-серьёзное-обновление"&gt;Векторные индексы получили серьёзное обновление&lt;/h2&gt;
&lt;p&gt;Azure SQL Database теперь имеет более быстрые и функциональные векторные индексы с полной поддержкой вставки, обновления и удаления. Это означает, что ваши векторные данные остаются актуальными в реальном времени — без необходимости пакетного переиндексирования.&lt;/p&gt;
&lt;p&gt;Что нового:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Квантование&lt;/strong&gt; для уменьшения размера индекса без значительной потери точности&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Итеративная фильтрация&lt;/strong&gt; для более точных результатов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Тесная интеграция с оптимизатором запросов&lt;/strong&gt; для предсказуемой производительности&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если вы используете retrieval-augmented generation (RAG) с Azure SQL в качестве векторного хранилища, эти улучшения напрямую полезны. Вы можете хранить векторы рядом с реляционными данными в одной базе данных, что значительно упрощает архитектуру по сравнению с запуском отдельной векторной базы данных.&lt;/p&gt;
&lt;p&gt;Те же улучшения для векторов доступны и в SQL database в Fabric, поскольку обе системы работают на одном движке SQL.&lt;/p&gt;
&lt;h2 id="database-hub-в-fabric-агентное-управление"&gt;Database Hub в Fabric: агентное управление&lt;/h2&gt;
&lt;p&gt;Этот анонс больше ориентирован на будущее, но он интересен. Microsoft анонсировала &lt;strong&gt;Database Hub в Microsoft Fabric&lt;/strong&gt; (ранний доступ), который даёт единую панель управления для Azure SQL, Cosmos DB, PostgreSQL, MySQL и SQL Server через Arc.&lt;/p&gt;
&lt;p&gt;Интересный момент не только в едином представлении — а в агентном подходе к управлению. ИИ-агенты непрерывно мониторят вашу инфраструктуру баз данных, выявляют изменения, объясняют, почему они важны, и предлагают, что делать дальше. Это модель с участием человека, где агент выполняет рутинную работу, а вы принимаете решения.&lt;/p&gt;
&lt;p&gt;Для команд, управляющих более чем несколькими базами данных, это может реально снизить операционный шум. Вместо переключения между порталами и ручной проверки метрик агент приносит вам значимый сигнал.&lt;/p&gt;
&lt;h2 id="что-это-значит-для-net-разработчиков"&gt;Что это значит для .NET-разработчиков&lt;/h2&gt;
&lt;p&gt;Нить, соединяющая все эти анонсы, очевидна: Microsoft встраивает ИИ-агентов на каждом уровне стека баз данных. Не как маркетинговый трюк, а как практический инструментальный слой.&lt;/p&gt;
&lt;p&gt;Если вы создаёте приложения на .NET с Azure SQL, вот что я бы реально сделал:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Попробуйте SQL MCP Server&lt;/strong&gt;, если вы создаёте ИИ-агентов. Это самый чистый способ дать вашим агентам доступ к базе данных без пользовательской обвязки.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Включите Copilot в SSMS&lt;/strong&gt;, если ещё не сделали — бесплатный прирост производительности для ежедневной работы с SQL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Посмотрите на векторные индексы&lt;/strong&gt;, если вы используете RAG и сейчас запускаете отдельное векторное хранилище. Консолидация на Azure SQL — это на один сервис меньше для управления.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Полный анонс содержит больше — планы экономии, помощники миграции, функции соответствия — но история для разработчиков сводится к MCP Server, улучшениям векторов и агентному слою управления. Это те элементы, которые меняют подход к разработке, а не только к бюджетированию.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://www.microsoft.com/en-us/sql-server/blog/2026/03/18/advancing-agentic-ai-with-microsoft-databases-across-a-unified-data-estate/"&gt;полным анонсом от Shireesh Thota&lt;/a&gt; для полной картины и &lt;a href="https://aka.ms/database-hub"&gt;зарегистрируйтесь для раннего доступа к Database Hub&lt;/a&gt;, если хотите попробовать новый опыт управления.&lt;/p&gt;</content:encoded></item><item><title>Azure DevOps MCP Server появился в Microsoft Foundry: что это значит для ваших ИИ-агентов</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-mcp-server-microsoft-foundry/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/azure-devops-mcp-server-microsoft-foundry/</guid><description>Azure DevOps MCP Server теперь доступен в Microsoft Foundry. Подключайте своих ИИ-агентов напрямую к рабочим процессам DevOps — work items, репозитории, пайплайны — в несколько кликов.</description><content:encoded>&lt;p&gt;MCP (Model Context Protocol) переживает свой момент. Если вы следите за экосистемой ИИ-агентов, вы наверняка заметили, что MCP-серверы появляются повсюду — давая агентам возможность взаимодействовать с внешними инструментами и сервисами через стандартизированный протокол.&lt;/p&gt;
&lt;p&gt;Теперь &lt;a href="https://devblogs.microsoft.com/devops/remote-mcp-server-preview-in-microsoft-foundry/"&gt;Azure DevOps MCP Server доступен в Microsoft Foundry&lt;/a&gt;, и это одна из тех интеграций, которая заставляет задуматься о практических возможностях.&lt;/p&gt;
&lt;h2 id="что-здесь-на-самом-деле-происходит"&gt;Что здесь на самом деле происходит&lt;/h2&gt;
&lt;p&gt;Microsoft уже выпустила Azure DevOps MCP Server в &lt;a href="https://devblogs.microsoft.com/devops/azure-devops-remote-mcp-server-public-preview"&gt;публичном превью&lt;/a&gt; — это сам MCP-сервер. Новое — это интеграция с Foundry. Теперь вы можете добавить Azure DevOps MCP Server к своим агентам в Foundry прямо из каталога инструментов.&lt;/p&gt;
&lt;p&gt;Для тех, кто ещё не знаком с Foundry: это унифицированная платформа Microsoft для создания и управления ИИ-приложениями и агентами в масштабе. Доступ к моделям, оркестрация, оценка, развёртывание — всё в одном месте.&lt;/p&gt;
&lt;h2 id="настройка"&gt;Настройка&lt;/h2&gt;
&lt;p&gt;Настройка удивительно проста:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;В вашем агенте Foundry перейдите в &lt;strong&gt;Add Tools&lt;/strong&gt; &amp;gt; &lt;strong&gt;Catalog&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Найдите &amp;ldquo;Azure DevOps&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Выберите Azure DevOps MCP Server (preview) и нажмите &lt;strong&gt;Create&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Введите имя вашей организации и подключитесь&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Вот и всё. Ваш агент теперь имеет доступ к инструментам Azure DevOps.&lt;/p&gt;
&lt;h2 id="контроль-доступа-агента"&gt;Контроль доступа агента&lt;/h2&gt;
&lt;p&gt;Вот что мне нравится: вы не ограничены подходом «всё или ничего». Вы можете указать, какие инструменты доступны вашему агенту. Если вы хотите, чтобы он только читал work items, но не трогал пайплайны, это можно настроить. Принцип наименьших привилегий, применённый к вашим ИИ-агентам.&lt;/p&gt;
&lt;p&gt;Это важно для корпоративных сценариев, где вы не хотите, чтобы агент случайно запустил пайплайн развёртывания, потому что кто-то попросил его «помочь с релизом».&lt;/p&gt;
&lt;h2 id="почему-это-интересно-для-net-команд"&gt;Почему это интересно для .NET-команд&lt;/h2&gt;
&lt;p&gt;Подумайте о том, что это позволяет на практике:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Помощники планирования спринтов&lt;/strong&gt; — агенты, которые могут извлекать work items, анализировать данные о скорости работы и предлагать ёмкость спринта&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Боты для код-ревью&lt;/strong&gt; — агенты, которые понимают контекст вашего PR, потому что могут реально читать ваши репозитории и связанные work items&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Реагирование на инциденты&lt;/strong&gt; — агенты, которые могут создавать work items, запрашивать последние развёртывания и сопоставлять баги с недавними изменениями&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Онбординг разработчиков&lt;/strong&gt; — &amp;ldquo;Над чем мне работать?&amp;rdquo; получает реальный ответ, основанный на фактических данных проекта&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для .NET-команд, уже использующих Azure DevOps для CI/CD-пайплайнов и управления проектами, наличие ИИ-агента, который может напрямую взаимодействовать с этими системами, — это значительный шаг к полезной автоматизации (а не просто чат-бот как сервис).&lt;/p&gt;
&lt;h2 id="более-широкая-картина-mcp"&gt;Более широкая картина MCP&lt;/h2&gt;
&lt;p&gt;Это часть более крупного тренда: MCP-серверы становятся стандартным способом взаимодействия ИИ-агентов с внешним миром. Мы видим их для GitHub, Azure DevOps, баз данных, SaaS API — и Foundry становится хабом, где все эти соединения объединяются.&lt;/p&gt;
&lt;p&gt;Если вы создаёте агентов в экосистеме .NET, на MCP стоит обратить внимание. Протокол стандартизирован, инструментарий развивается, а интеграция с Foundry делает его доступным без необходимости вручную настраивать серверные подключения.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Azure DevOps MCP Server в Foundry находится в превью, так что ожидайте его развития. Но основной рабочий процесс надёжен: подключите, настройте доступ к инструментам и позвольте вашим агентам работать с данными DevOps. Если вы уже в экосистеме Foundry, это в нескольких кликах. Попробуйте и посмотрите, какие рабочие процессы вы сможете построить.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/devops/remote-mcp-server-preview-in-microsoft-foundry/"&gt;полным анонсом&lt;/a&gt; для пошаговых инструкций по настройке и дополнительных деталей.&lt;/p&gt;</content:encoded></item><item><title>Foundry Agent Service вышел в GA: что действительно важно для .NET-разработчиков агентов</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-agent-service-ga-what-matters/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/foundry-agent-service-ga-what-matters/</guid><description>Foundry Agent Service от Microsoft вышел в GA с приватной сетью, Voice Live, продакшен-оценками и открытым мультимодельным рантаймом. Вот что нужно знать.</description><content:encoded>&lt;p&gt;Будем честны — создать прототип ИИ-агента — это простая часть. Сложная часть — всё, что идёт после: вывести его в продакшен с правильной сетевой изоляцией, запустить оценки, которые действительно что-то значат, обеспечить соответствие требованиям и не сломать ничего в 2 часа ночи.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/foundry/foundry-agent-service-ga/"&gt;Foundry Agent Service только что вышел в GA&lt;/a&gt;, и этот релиз сфокусирован именно на этом разрыве «всё, что после».&lt;/p&gt;
&lt;h2 id="построен-на-responses-api"&gt;Построен на Responses API&lt;/h2&gt;
&lt;p&gt;Вот главная новость: Foundry Agent Service нового поколения построен на OpenAI Responses API. Если вы уже работаете с этим wire-протоколом, миграция на Foundry — это минимальные изменения кода. Что вы получаете: корпоративную безопасность, приватную сеть, Entra RBAC, полную трассировку и оценку — поверх вашей существующей логики агента.&lt;/p&gt;
&lt;p&gt;Архитектура намеренно открыта. Вы не привязаны к одному провайдеру моделей или одному фреймворку оркестрации. Используйте DeepSeek для планирования, OpenAI для генерации, LangGraph для оркестрации — рантайм обеспечивает слой согласованности.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.projects&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.projects.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PromptAgentDefinition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_PROJECT_ENDPOINT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;project_client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;project_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_openai_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;agent_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-enterprise-agent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;definition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PromptAgentDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_MODEL_DEPLOYMENT_NAME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;You are a helpful assistant.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conversation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conversations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;What are best practices for building AI agents?&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;extra_body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;agent_reference&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;agent_reference&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Если вы переходите с пакета &lt;code&gt;azure-ai-agents&lt;/code&gt;, агенты теперь являются операциями первого класса на &lt;code&gt;AIProjectClient&lt;/code&gt; в &lt;code&gt;azure-ai-projects&lt;/code&gt;. Удалите отдельную зависимость и используйте &lt;code&gt;get_openai_client()&lt;/code&gt; для работы с ответами.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="приватная-сеть-корпоративный-блокер-устранён"&gt;Приватная сеть: корпоративный блокер устранён&lt;/h2&gt;
&lt;p&gt;Это функция, которая разблокирует корпоративное внедрение. Foundry теперь поддерживает полную сквозную приватную сеть с BYO VNet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Нет публичного исходящего трафика&lt;/strong&gt; — трафик агента никогда не проходит через публичный интернет&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Внедрение контейнеров/подсетей&lt;/strong&gt; в вашу сеть для локальной коммуникации&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Подключение инструментов включено&lt;/strong&gt; — MCP-серверы, Azure AI Search, агенты данных Fabric — всё работает через приватные пути&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Последний пункт критичен. Приватными остаются не только вызовы для вывода — каждый вызов инструмента и поисковый запрос тоже остаётся внутри границы вашей сети. Для команд, работающих под политиками классификации данных, запрещающими внешнюю маршрутизацию, это то, чего не хватало.&lt;/p&gt;
&lt;h2 id="аутентификация-mcp-сделана-правильно"&gt;Аутентификация MCP сделана правильно&lt;/h2&gt;
&lt;p&gt;Подключения к MCP-серверам теперь поддерживают полный спектр паттернов аутентификации:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Метод аутентификации&lt;/th&gt;
&lt;th&gt;Когда использовать&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;На основе ключей&lt;/td&gt;
&lt;td&gt;Простой общий доступ для внутренних инструментов организации&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra Agent Identity&lt;/td&gt;
&lt;td&gt;Сервис-к-сервису; агент аутентифицируется от своего имени&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra Managed Identity&lt;/td&gt;
&lt;td&gt;Изоляция на уровне проекта; без управления учётными данными&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OAuth Identity Passthrough&lt;/td&gt;
&lt;td&gt;Делегированный доступ пользователя; агент действует от имени пользователей&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;OAuth Identity Passthrough — самый интересный. Когда пользователям нужно предоставить агенту доступ к своим личным данным — их OneDrive, их организации Salesforce, SaaS API с пользовательской областью — агент действует от их имени через стандартные OAuth-потоки. Никакой общей системной идентификации, притворяющейся всеми.&lt;/p&gt;
&lt;h2 id="voice-live-речь-в-речь-без-сантехнических-работ"&gt;Voice Live: речь-в-речь без сантехнических работ&lt;/h2&gt;
&lt;p&gt;Добавление голоса к агенту раньше означало объединение STT, LLM и TTS — три сервиса, три задержки, три поверхности биллинга, всё синхронизировано вручную. &lt;strong&gt;Voice Live&lt;/strong&gt; сворачивает это в единый управляемый API с:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Семантическое определение голосовой активности и конца реплики (понимает смысл, а не просто тишину)&lt;/li&gt;
&lt;li&gt;Серверное подавление шума и эхо-компенсация&lt;/li&gt;
&lt;li&gt;Поддержка прерывания (пользователи могут прервать ответ)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Голосовые взаимодействия проходят через тот же рантайм агента, что и текстовые. Те же оценщики, те же трассировки, та же прозрачность затрат. Для поддержки клиентов, полевого обслуживания или сценариев доступности это заменяет то, что раньше требовало пользовательского аудио-пайплайна.&lt;/p&gt;
&lt;h2 id="оценки-от-галочки-к-непрерывному-мониторингу"&gt;Оценки: от галочки к непрерывному мониторингу&lt;/h2&gt;
&lt;p&gt;Здесь Foundry серьёзно подходит к качеству продакшена. Система оценки теперь имеет три уровня:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Готовые оценщики&lt;/strong&gt; — связность, релевантность, обоснованность, качество поиска, безопасность. Подключите к датасету или живому трафику и получите оценки обратно.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Пользовательские оценщики&lt;/strong&gt; — закодируйте свою бизнес-логику, стандарты тона и специфичные для домена правила соответствия.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Непрерывная оценка&lt;/strong&gt; — Foundry сэмплирует живой продакшен-трафик, запускает набор оценщиков и отображает результаты через дашборды. Настройте алерты Azure Monitor на случай падения обоснованности или нарушения порогов безопасности.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Всё публикуется в Azure Monitor Application Insights. Качество агента, здоровье инфраструктуры, затраты и телеметрия приложения — всё в одном месте.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;eval_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Agent Quality Evaluation&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;data_source_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DataSourceConfigCustom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;custom&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;item_schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;object&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;required&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;include_sample_schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;testing_criteria&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;azure_ai_evaluator&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fluency&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;evaluator_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;builtin.fluency&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;initialization_parameters&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;deployment_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_MODEL_DEPLOYMENT_NAME&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;data_mapping&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{{item.query}}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;response&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{{sample.output_text}}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="шесть-новых-регионов-для-размещённых-агентов"&gt;Шесть новых регионов для размещённых агентов&lt;/h2&gt;
&lt;p&gt;Размещённые агенты теперь доступны в East US, North Central US, Sweden Central, Southeast Asia, Japan East и других регионах. Это важно для требований к размещению данных и для снижения задержки, когда ваш агент работает рядом с источниками данных.&lt;/p&gt;
&lt;h2 id="почему-это-важно-для-net-разработчиков"&gt;Почему это важно для .NET-разработчиков&lt;/h2&gt;
&lt;p&gt;Хотя примеры кода в анонсе GA написаны на Python, базовая инфраструктура не зависит от языка — и .NET SDK для &lt;code&gt;azure-ai-projects&lt;/code&gt; следует тем же паттернам. Responses API, фреймворк оценки, приватная сеть, аутентификация MCP — всё это доступно из .NET.&lt;/p&gt;
&lt;p&gt;Если вы ждали, пока ИИ-агенты перейдут от «классной демо» к «я реально могу отправить это на работе», этот GA-релиз — тот самый сигнал. Приватная сеть, правильная аутентификация, непрерывная оценка и продакшен-мониторинг — это были недостающие элементы.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Foundry Agent Service доступен сейчас. Установите SDK, откройте &lt;a href="https://ai.azure.com"&gt;портал&lt;/a&gt; и начинайте строить. &lt;a href="https://learn.microsoft.com/azure/foundry/quickstarts/get-started-code"&gt;Руководство по быстрому старту&lt;/a&gt; проведёт вас от нуля до работающего агента за минуты.&lt;/p&gt;
&lt;p&gt;Для полного технического погружения со всеми примерами кода ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/foundry/foundry-agent-service-ga/"&gt;анонсом GA&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>VS Code 1.112: что действительно важно для .NET-разработчиков</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-112-dotnet-developers/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/vscode-1-112-dotnet-developers/</guid><description>VS Code 1.112 только что вышел и наполнен обновлениями агентов, встроенным отладчиком браузера, песочницей MCP и поддержкой монорепозиториев. Вот что действительно важно для .NET-разработчиков.</description><content:encoded>&lt;p&gt;VS Code 1.112 только что приземлился, и честно? Этот релиз ощущается иначе, если вы проводите дни в мире .NET. В &lt;a href="https://code.visualstudio.com/updates/v1_112"&gt;официальных заметках о релизе&lt;/a&gt; много всего, но позвольте мне сэкономить вам время и сосредоточиться на том, что действительно важно для нас.&lt;/p&gt;
&lt;h2 id="copilot-cli-стал-намного-полезнее"&gt;Copilot CLI стал намного полезнее&lt;/h2&gt;
&lt;p&gt;Главная тема этого релиза — &lt;strong&gt;автономность агентов&lt;/strong&gt; — предоставление Copilot больше пространства для работы без того, чтобы вы контролировали каждый шаг.&lt;/p&gt;
&lt;h3 id="управление-сообщениями-и-очередь"&gt;Управление сообщениями и очередь&lt;/h3&gt;
&lt;p&gt;Знаете тот момент, когда Copilot CLI на полпути через задачу, и вы понимаете, что забыли что-то упомянуть? Раньше приходилось ждать. Теперь вы можете просто отправлять сообщения, пока запрос ещё обрабатывается — либо для корректировки текущего ответа, либо для постановки в очередь последующих инструкций.&lt;/p&gt;
&lt;p&gt;Это огромное улучшение для длинных задач генерации &lt;code&gt;dotnet&lt;/code&gt;, когда вы наблюдаете, как Copilot настраивает проект и думаете «ой, мне ещё нужен MassTransit туда».&lt;/p&gt;
&lt;h3 id="уровни-разрешений"&gt;Уровни разрешений&lt;/h3&gt;
&lt;p&gt;Вот что меня больше всего радует. Сессии Copilot CLI теперь поддерживают три уровня разрешений:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Стандартные разрешения&lt;/strong&gt; — обычный поток, где инструменты запрашивают подтверждение перед выполнением&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Пропуск подтверждений&lt;/strong&gt; — автоматически одобряет всё и повторяет при ошибках&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Автопилот&lt;/strong&gt; — полностью автономный режим: одобряет инструменты, сам отвечает на свои вопросы и продолжает до завершения задачи&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если вы делаете что-то вроде создания нового ASP.NET Core API с Entity Framework, миграциями и Docker-настройкой — режим Автопилот означает, что вы описываете, что хотите, и идёте за кофе. Он разберётся.&lt;/p&gt;
&lt;p&gt;Включить Автопилот можно через настройку &lt;code&gt;chat.autopilot.enabled&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="предварительный-просмотр-изменений-перед-делегированием"&gt;Предварительный просмотр изменений перед делегированием&lt;/h3&gt;
&lt;p&gt;Когда вы делегируете задачу Copilot CLI, он создаёт worktree. Раньше, если у вас были незакоммиченные изменения, приходилось проверять Source Control, чтобы увидеть, что будет затронуто. Теперь представление Chat показывает ожидающие изменения прямо перед тем, как вы решите, копировать, переместить или проигнорировать их.&lt;/p&gt;
&lt;p&gt;Мелочь, но это спасает от того момента «подождите, что у меня было в staged?».&lt;/p&gt;
&lt;h2 id="отладка-веб-приложений-без-выхода-из-vs-code"&gt;Отладка веб-приложений без выхода из VS Code&lt;/h2&gt;
&lt;p&gt;Встроенный браузер теперь поддерживает &lt;strong&gt;полную отладку&lt;/strong&gt;. Вы можете ставить точки останова, пошагово проходить код и проверять переменные — всё внутри VS Code. Больше не нужно переключаться на Edge DevTools.&lt;/p&gt;
&lt;p&gt;Появился новый тип отладки &lt;code&gt;editor-browser&lt;/code&gt;, и если у вас уже есть конфигурации запуска для &lt;code&gt;msedge&lt;/code&gt; или &lt;code&gt;chrome&lt;/code&gt;, миграция так же проста, как изменение поля &lt;code&gt;type&lt;/code&gt; в вашем &lt;code&gt;launch.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;editor-browser&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;request&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;launch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Debug Blazor App&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://localhost:5001&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Для Blazor-разработчиков это переломный момент. Вы уже запускаете &lt;code&gt;dotnet watch&lt;/code&gt; в терминале — теперь и отладка остаётся в том же окне.&lt;/p&gt;
&lt;p&gt;Браузер также получил независимые уровни масштабирования (наконец-то), правильные контекстные меню по правому клику, и масштаб сохраняется для каждого сайта.&lt;/p&gt;
&lt;h2 id="песочница-для-mcp-серверов"&gt;Песочница для MCP-серверов&lt;/h2&gt;
&lt;p&gt;Это важнее, чем может показаться. Если вы используете MCP-серверы — может быть, настроили пользовательский для ваших Azure-ресурсов или запросов к базе данных — они работали с теми же правами, что и ваш процесс VS Code. То есть полный доступ к файловой системе, сети, всему.&lt;/p&gt;
&lt;p&gt;Теперь их можно изолировать в песочнице. В вашем &lt;code&gt;mcp.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;servers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;my-azure-tools&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;node&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./mcp-server.js&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sandboxEnabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Когда изолированному серверу нужен доступ к чему-то, чего у него нет, VS Code запрашивает разрешение. Гораздо лучше подхода «надеемся, никто не сделает ничего странного».&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Примечание:&lt;/strong&gt; Песочница доступна на macOS и Linux на данный момент. Поддержка Windows на подходе — но удалённые сценарии вроде WSL уже работают.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="обнаружение-кастомизаций-в-монорепозиториях"&gt;Обнаружение кастомизаций в монорепозиториях&lt;/h2&gt;
&lt;p&gt;Если вы работаете в монорепозитории (и будем честны, многие корпоративные .NET-решения в итоге становятся таковыми), это решает реальную проблему.&lt;/p&gt;
&lt;p&gt;Раньше, если вы открывали подпапку вашего репозитория, VS Code не находил ваш &lt;code&gt;copilot-instructions.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt; или пользовательские скиллы, находящиеся в корне репозитория. Теперь с настройкой &lt;code&gt;chat.useCustomizationsInParentRepositories&lt;/code&gt; он поднимается до корня &lt;code&gt;.git&lt;/code&gt; и обнаруживает всё.&lt;/p&gt;
&lt;p&gt;Это означает, что ваша команда может делиться инструкциями для агентов, файлами промптов и пользовательскими инструментами между всеми проектами в монорепозитории, не требуя от каждого открывать корневую папку.&lt;/p&gt;
&lt;h2 id="troubleshoot-для-отладки-агентов"&gt;/troubleshoot для отладки агентов&lt;/h2&gt;
&lt;p&gt;Когда-нибудь настраивали пользовательские инструкции или скиллы и гадали, почему они не подхватываются? Новый скилл &lt;code&gt;/troubleshoot&lt;/code&gt; читает отладочные логи агента и сообщает, что произошло — какие инструменты были использованы или пропущены, почему инструкции не загрузились и что вызывает медленные ответы.&lt;/p&gt;
&lt;p&gt;Включите его с помощью:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;github.copilot.chat.agentDebugLog.enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;github.copilot.chat.agentDebugLog.fileLogging.enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Затем просто введите &lt;code&gt;/troubleshoot почему мой пользовательский скилл не загружается?&lt;/code&gt; в чат.&lt;/p&gt;
&lt;p&gt;Теперь также можно экспортировать и импортировать эти отладочные логи, что отлично подходит для обмена с командой, когда что-то работает не так, как ожидалось.&lt;/p&gt;
&lt;h2 id="поддержка-изображений-и-бинарных-файлов"&gt;Поддержка изображений и бинарных файлов&lt;/h2&gt;
&lt;p&gt;Агенты теперь могут читать файлы изображений с диска и бинарные файлы нативно. Бинарные файлы представлены в формате hexdump, а выводы изображений (например, скриншоты из встроенного браузера) отображаются в карусельном виде.&lt;/p&gt;
&lt;p&gt;Для .NET-разработчиков подумайте: вставьте скриншот UI-бага в чат, и агент поймёт, что не так, или пусть он проанализирует вывод рендеринга компонента Blazor.&lt;/p&gt;
&lt;h2 id="автоматические-ссылки-на-символы"&gt;Автоматические ссылки на символы&lt;/h2&gt;
&lt;p&gt;Небольшое улучшение качества жизни: когда вы копируете имя символа (класс, метод и т.д.) и вставляете его в чат, VS Code теперь автоматически преобразует его в ссылку &lt;code&gt;#sym:Name&lt;/code&gt;. Это даёт агенту полный контекст об этом символе без необходимости вручную добавлять его.&lt;/p&gt;
&lt;p&gt;Если вам нужен обычный текст, используйте &lt;code&gt;Ctrl+Shift+V&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="плагины-теперь-можно-включатьотключать"&gt;Плагины теперь можно включать/отключать&lt;/h2&gt;
&lt;p&gt;Раньше отключение MCP-сервера или плагина означало его удаление. Теперь их можно переключать — как глобально, так и для каждого рабочего пространства. Правый клик в представлении Extensions или Customizations — и готово.&lt;/p&gt;
&lt;p&gt;Плагины из npm и pypi также могут автоматически обновляться, хотя сначала запросят подтверждение, поскольку обновления означают запуск нового кода на вашей машине.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;VS Code 1.112 явно усиленно развивает агентный опыт — больше автономности, лучшая отладка, более строгая безопасность. Для .NET-разработчиков встроенная отладка браузера и улучшения Copilot CLI — это главные новшества.&lt;/p&gt;
&lt;p&gt;Если вы ещё не пробовали запустить полную сессию Copilot CLI в режиме Автопилот для .NET-проекта, этот релиз — хорошее время для начала. Просто не забудьте настроить разрешения и дайте ему поработать.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.visualstudio.com/updates/v1_112"&gt;Скачайте VS Code 1.112&lt;/a&gt; или обновите изнутри VS Code через &lt;strong&gt;Help &amp;gt; Check for Updates&lt;/strong&gt;.&lt;/p&gt;</content:encoded></item><item><title>С ноутбука в продакшен: развёртывание ИИ-агентов в Microsoft Foundry двумя командами</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/deploy-ai-agents-foundry-azd-two-commands/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/deploy-ai-agents-foundry-azd-two-commands/</guid><description>Azure Developer CLI теперь имеет команды 'azd ai agent', которые переносят вашего ИИ-агента с локальной разработки на живой эндпоинт Foundry за минуты. Вот полный рабочий процесс.</description><content:encoded>&lt;p&gt;Вы знаете тот разрыв между «работает на моей машине» и «развёрнуто и обслуживает трафик»? Для ИИ-агентов этот разрыв был болезненно широким. Нужно подготовить ресурсы, развернуть модели, настроить идентификацию, организовать мониторинг — и это до того, как кто-либо сможет реально вызвать вашего агента.&lt;/p&gt;
&lt;p&gt;Azure Developer CLI только что превратил это в &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-ai-agent-end-to-end/"&gt;дело двух команд&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="новый-рабочий-процесс-azd-ai-agent"&gt;Новый рабочий процесс &lt;code&gt;azd ai agent&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Давайте пройдём по тому, как это реально выглядит. У вас есть проект ИИ-агента — допустим, агент-консьерж для отеля. Он работает локально. Вы хотите запустить его на Microsoft Foundry.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd ai agent init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вот и всё. Две команды. &lt;code&gt;azd ai agent init&lt;/code&gt; генерирует инфраструктуру как код в вашем репозитории, а &lt;code&gt;azd up&lt;/code&gt; разворачивает всё в Azure и публикует вашего агента. Вы получаете прямую ссылку на вашего агента в портале Foundry.&lt;/p&gt;
&lt;h2 id="что-происходит-под-капотом"&gt;Что происходит под капотом&lt;/h2&gt;
&lt;p&gt;Команда &lt;code&gt;init&lt;/code&gt; генерирует реальные, проверяемые шаблоны Bicep в вашем репозитории:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Foundry Resource&lt;/strong&gt; (контейнер верхнего уровня)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Foundry Project&lt;/strong&gt; (где живёт ваш агент)&lt;/li&gt;
&lt;li&gt;Конфигурация &lt;strong&gt;развёртывания модели&lt;/strong&gt; (GPT-4o и т.д.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Managed identity&lt;/strong&gt; с правильными назначениями ролей RBAC&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azure.yaml&lt;/code&gt; для карты сервисов&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent.yaml&lt;/code&gt; с метаданными агента и переменными окружения&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ключевой момент: всё это принадлежит вам. Это версионированный Bicep в вашем репозитории. Вы можете его проверить, настроить и закоммитить рядом с кодом вашего агента. Никаких магических чёрных ящиков.&lt;/p&gt;
&lt;h2 id="внутренний-цикл-разработки"&gt;Внутренний цикл разработки&lt;/h2&gt;
&lt;p&gt;Что мне действительно нравится — это история локальной разработки. Когда вы итерируете над логикой агента, вы не хотите перезапускать развёртывание при каждом изменении промпта:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd ai agent run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Это запускает вашего агента локально. Комбинируйте с &lt;code&gt;azd ai agent invoke&lt;/code&gt; для отправки тестовых промптов, и у вас есть быстрый цикл обратной связи. Редактируете код, перезапускаете, вызываете, повторяете.&lt;/p&gt;
&lt;p&gt;Команда &lt;code&gt;invoke&lt;/code&gt; умная в плане маршрутизации — когда локальный агент запущен, она автоматически направляет на него. Когда нет — обращается к удалённому эндпоинту.&lt;/p&gt;
&lt;h2 id="мониторинг-в-реальном-времени"&gt;Мониторинг в реальном времени&lt;/h2&gt;
&lt;p&gt;Вот функция, которая меня купила. После развёртывания агента:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azd ai agent monitor --follow
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Каждый запрос и ответ, проходящий через вашего агента, транслируется в ваш терминал в реальном времени. Для отладки продакшен-проблем это бесценно. Никакого копания в log analytics, никакого ожидания агрегации метрик — вы видите, что происходит прямо сейчас.&lt;/p&gt;
&lt;h2 id="полный-набор-команд"&gt;Полный набор команд&lt;/h2&gt;
&lt;p&gt;Вот краткий справочник:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Команда&lt;/th&gt;
&lt;th&gt;Что делает&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;azd ai agent init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Генерирует проект агента Foundry с IaC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;azd up&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Разворачивает Azure-ресурсы и публикует агента&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;azd ai agent invoke&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Отправляет промпты удалённому или локальному агенту&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;azd ai agent run&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Запускает агента локально для разработки&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;azd ai agent monitor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Транслирует логи от опубликованного агента в реальном времени&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;azd ai agent show&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Проверяет состояние и здоровье агента&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;azd down&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Удаляет все Azure-ресурсы&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="почему-это-важно-для-net-разработчиков"&gt;Почему это важно для .NET-разработчиков&lt;/h2&gt;
&lt;p&gt;Хотя пример в анонсе написан на Python, история инфраструктуры не зависит от языка. Ваш .NET-агент получает тот же Bicep-шаблон, ту же настройку managed identity, тот же пайплайн мониторинга. И если вы уже используете &lt;code&gt;azd&lt;/code&gt; для своих .NET Aspire-приложений или развёртываний Azure, это вписывается прямо в ваш существующий рабочий процесс.&lt;/p&gt;
&lt;p&gt;Разрыв в развёртывании ИИ-агентов был одной из самых больших точек трения в экосистеме. Переход от работающего прототипа к продакшен-эндпоинту с правильной идентификацией, сетью и мониторингом не должен требовать недели DevOps-работы. Теперь для этого нужны две команды и несколько минут.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;azd ai agent&lt;/code&gt; доступен сейчас. Если вы откладывали развёртывание своих ИИ-агентов, потому что настройка инфраструктуры казалась слишком трудоёмкой, попробуйте это. Ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-ai-agent-end-to-end/"&gt;полным руководством&lt;/a&gt; для полной пошаговой инструкции, включая интеграцию с фронтенд-чат-приложением.&lt;/p&gt;</content:encoded></item><item><title>Фоновые ответы в Microsoft Agent Framework: больше никакой тревоги из-за таймаутов</title><link>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/background-responses-agent-framework-long-running-tasks/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ru/posts/emiliano-montesdeoca/background-responses-agent-framework-long-running-tasks/</guid><description>Microsoft Agent Framework теперь позволяет выносить длительные ИИ-задачи с помощью continuation-токенов. Вот как работают фоновые ответы и почему они важны для ваших .NET-агентов.</description><content:encoded>&lt;p&gt;Если вы создавали что-либо с моделями рассуждения, такими как o3 или GPT-5.2, вы знаете эту боль. Ваш агент начинает обдумывать сложную задачу, клиент сидит и ждёт, и где-то между «всё нормально» и «он завис?» ваше соединение падает по таймауту. Вся работа? Потеряна.&lt;/p&gt;
&lt;p&gt;Microsoft Agent Framework только что выпустил &lt;a href="https://devblogs.microsoft.com/agent-framework/handling-long-running-operations-with-background-responses/"&gt;фоновые ответы&lt;/a&gt; — и честно говоря, это одна из тех функций, которая должна была существовать с первого дня.&lt;/p&gt;
&lt;h2 id="проблема-с-блокирующими-вызовами"&gt;Проблема с блокирующими вызовами&lt;/h2&gt;
&lt;p&gt;В традиционной модели запрос-ответ ваш клиент блокируется до завершения работы агента. Это нормально для быстрых задач. Но когда вы просите модель рассуждения провести глубокое исследование, многоэтапный анализ или сгенерировать 20-страничный отчёт? Вы смотрите на минуты реального времени. В течение этого окна:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP-соединения могут упасть по таймауту&lt;/li&gt;
&lt;li&gt;Сетевые сбои убивают всю операцию&lt;/li&gt;
&lt;li&gt;Ваш пользователь смотрит на спиннер, гадая, происходит ли что-нибудь&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Фоновые ответы переворачивают этот подход.&lt;/p&gt;
&lt;h2 id="как-работают-continuation-токены"&gt;Как работают continuation-токены&lt;/h2&gt;
&lt;p&gt;Вместо блокировки вы запускаете задачу агента и получаете обратно &lt;strong&gt;continuation-токен&lt;/strong&gt;. Представьте его как квитанцию в ремонтной мастерской — вы не стоите у стойки и ждёте, а приходите, когда всё готово.&lt;/p&gt;
&lt;p&gt;Процесс прост:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Отправьте запрос с &lt;code&gt;AllowBackgroundResponses = true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Если агент поддерживает фоновую обработку, вы получаете continuation-токен&lt;/li&gt;
&lt;li&gt;Опрашивайте по своему расписанию, пока токен не вернёт &lt;code&gt;null&lt;/code&gt; — это значит, результат готов&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Вот версия на .NET:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AzureOpenAIClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://&amp;lt;myresource&amp;gt;.openai.azure.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetResponsesClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;lt;deployment-name&amp;gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentRunOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AllowBackgroundResponses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentSession&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateSessionAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;Write a detailed market analysis for the Q4 product launch.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Опрашиваем до завершения&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Если агент завершает немедленно (простые задачи, модели, не требующие фоновой обработки), continuation-токен не возвращается. Ваш код просто работает — никакой специальной обработки не нужно.&lt;/p&gt;
&lt;h2 id="стриминг-с-возобновлением-настоящая-магия"&gt;Стриминг с возобновлением: настоящая магия&lt;/h2&gt;
&lt;p&gt;Опрос подходит для сценариев «запустил и забыл», но что если вы хотите видеть прогресс в реальном времени? Фоновые ответы также поддерживают стриминг со встроенным возобновлением.&lt;/p&gt;
&lt;p&gt;Каждое потоковое обновление несёт свой continuation-токен. Если соединение прерывается посреди потока, вы продолжаете ровно с того места, где остановились:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentRunOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AllowBackgroundResponses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentSession&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateSessionAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentResponseUpdate&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;latestUpdate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunStreamingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;Write a detailed market analysis for the Q4 product launch.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;latestUpdate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Симулируем разрыв сети&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Возобновляем ровно с того места, где остановились&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;latestUpdate&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunStreamingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Агент продолжает обработку на стороне сервера независимо от того, что происходит с вашим клиентом. Это встроенная отказоустойчивость без написания логики повторных попыток или circuit breaker&amp;rsquo;ов.&lt;/p&gt;
&lt;h2 id="когда-это-действительно-использовать"&gt;Когда это действительно использовать&lt;/h2&gt;
&lt;p&gt;Не каждый вызов агента нуждается в фоновых ответах. Для быстрых завершений вы добавляете сложность без причины. Но вот где они реально полезны:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Сложные задачи рассуждения&lt;/strong&gt; — многоэтапный анализ, глубокие исследования, всё, что заставляет модель рассуждения действительно думать&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Генерация длинного контента&lt;/strong&gt; — детальные отчёты, многочастные документы, обширный анализ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ненадёжные сети&lt;/strong&gt; — мобильные клиенты, периферийные развёртывания, нестабильные корпоративные VPN&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Асинхронные UX-паттерны&lt;/strong&gt; — отправьте задачу, займитесь другим делом, вернитесь за результатами&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для .NET-разработчиков, создающих корпоративные приложения, последний пункт особенно интересен. Представьте Blazor-приложение, где пользователь запрашивает сложный отчёт — вы запускаете задачу агента, показываете индикатор прогресса и позволяете ему продолжить работу. Никакой WebSocket-гимнастики, никакой пользовательской инфраструктуры очередей, просто токен и цикл опроса.&lt;/p&gt;
&lt;h2 id="итог"&gt;Итог&lt;/h2&gt;
&lt;p&gt;Фоновые ответы уже доступны в .NET и Python через Microsoft Agent Framework. Если вы создаёте агентов, которые делают что-то сложнее простых вопросов-ответов, это стоит добавить в свой инструментарий. Паттерн с continuation-токенами сохраняет простоту, решая очень реальную продакшен-проблему.&lt;/p&gt;
&lt;p&gt;Ознакомьтесь с &lt;a href="https://devblogs.microsoft.com/agent-framework/handling-long-running-operations-with-background-responses/"&gt;полной документацией&lt;/a&gt; для полного справочника API и дополнительных примеров.&lt;/p&gt;</content:encoded></item><item><title>Emiliano Montesdeoca</title><link>https://thedotnetblog.com/ru/authors/emiliano-montesdeoca/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://thedotnetblog.com/ru/authors/emiliano-montesdeoca/</guid><description/><content:encoded/></item><item><title>Пишите для The .NET Blog</title><link>https://thedotnetblog.com/ru/contribute/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://thedotnetblog.com/ru/contribute/</guid><description>Делитесь своими знаниями с .NET-сообществом. Узнайте, как стать автором и отправить свою первую статью.</description><content:encoded>&lt;p&gt;The .NET Blog — это публикация, управляемая сообществом, где разработчики делятся инсайтами, туториалами и историями о .NET, Azure, ИИ и облачно-нативной разработке. &lt;strong&gt;Мы приветствуем вклад разработчиков любого уровня&lt;/strong&gt; — будь вы новичком, пишущим первую техническую статью, или опытным докладчиком.&lt;/p&gt;
&lt;h2 id="как-присоединиться"&gt;Как присоединиться&lt;/h2&gt;
&lt;p&gt;Всё хранится на GitHub и следует рабочему процессу pull request. Вот как начать:&lt;/p&gt;
&lt;h3 id="1-форкните-репозиторий"&gt;1. Форкните репозиторий&lt;/h3&gt;
&lt;p&gt;Перейдите на &lt;a href="https://github.com/thedotnetblog/blog"&gt;github.com/thedotnetblog/blog&lt;/a&gt; и форкните репозиторий в свой аккаунт GitHub.&lt;/p&gt;
&lt;h3 id="2-создайте-профиль-автора"&gt;2. Создайте профиль автора&lt;/h3&gt;
&lt;p&gt;Создайте папку &lt;code&gt;content/authors/your-username/&lt;/code&gt; с файлом &lt;code&gt;index.md&lt;/code&gt;, указав имя, роль и биографию. Добавьте изображение аватара (квадратное, минимум 200×200px) в &lt;code&gt;static/img/authors/&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="3-напишите-статью"&gt;3. Напишите статью&lt;/h3&gt;
&lt;p&gt;Создайте папку &lt;code&gt;content/posts/your-username/your-post-slug/&lt;/code&gt; и добавьте файл &lt;code&gt;index.md&lt;/code&gt; с заголовком, датой, автором, описанием и тегами.&lt;/p&gt;
&lt;h3 id="4-откройте-pull-request"&gt;4. Откройте Pull Request&lt;/h3&gt;
&lt;p&gt;Отправьте изменения в ваш форк и откройте pull request в ветку &lt;code&gt;main&lt;/code&gt;. Наша команда проверит его и даст обратную связь в течение нескольких дней.&lt;/p&gt;
&lt;h2 id="что-мы-ищем"&gt;Что мы ищем&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Туториалы&lt;/strong&gt; — пошаговые руководства по .NET, Azure, ИИ, Blazor, Aspire и другим технологиям&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Глубокий анализ&lt;/strong&gt; — детальное изучение технологий, паттернов или архитектур&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Истории сообщества&lt;/strong&gt; — ваш опыт использования .NET в продакшне&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Обзоры событий&lt;/strong&gt; — резюме конференций, митапов или вебинаров&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="рекомендации"&gt;Рекомендации&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Контент должен быть техническим и релевантным для экосистемы .NET&lt;/li&gt;
&lt;li&gt;Примеры кода должны быть точными и протестированными в реальном проекте&lt;/li&gt;
&lt;li&gt;Включите осмысленное описание и хотя бы один релевантный тег&lt;/li&gt;
&lt;li&gt;Статьи автоматически переводятся на все поддерживаемые языки&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="связаться-с-нами"&gt;Связаться с нами&lt;/h2&gt;
&lt;p&gt;Откройте issue на &lt;a href="https://github.com/thedotnetblog/blog/issues"&gt;GitHub&lt;/a&gt; или напишите нам в &lt;a href="https://x.com/thedotnetblog"&gt;X / Twitter&lt;/a&gt;. Будем рады видеть вас в сообществе!&lt;/p&gt;</content:encoded></item></channel></rss>