<?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>Dotnet | The .NET Blog</title><link>https://thedotnetblog.com/ru/tags/dotnet/</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, 11 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/ru/tags/dotnet/index.xml" rel="self" type="application/rss+xml"/><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>Windows App Dev CLI v0.3: F5 из терминала и UI-автоматизация для агентов</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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/news/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/news/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/news/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>Хватит нянчить терминал: отсоединённый режим Aspire меняет рабочий процесс</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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>Кластеризация пинов наконец появилась в .NET MAUI Maps — Одно свойство, ноль проблем</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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/news/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/news/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/news/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>Azure MCP Server 2.0 выпущен — Self-Hosted Agentic Cloud Automation здесь</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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>Изолированный режим Aspire устраняет кошмар конфликтов портов при параллельной разработке</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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>C# 15 получает типы-объединения — и это именно то, что мы просили</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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>Дашборд Aspire 13.2 теперь с API телеметрии — и это меняет всё</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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/news/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>Foundry Agent Service вышел в GA: что действительно важно для .NET-разработчиков агентов</title><link>https://thedotnetblog.com/ru/news/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/news/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/news/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/news/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 Agent Framework: больше никакой тревоги из-за таймаутов</title><link>https://thedotnetblog.com/ru/news/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/news/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></channel></rss>