Microsoft Agent Framework の ハーネスのコア機能が正式リリース — LM Studioで試す 後編
はじめに
2026年7月22日に Microsoft Agent Framework の Harness コア機能が正式リリース(GA)されました。一方で公式ブログは「Coming soon」として、次の4機能をまだ正式リリースに含めていないと明言しています。
While we are releasing the core harness, there are a few opt-in features that we are not releasing yet. (中略) Until such time, you will get a warning when opting into these features.
| 機能 | 内容 |
|---|---|
| Background agents | サブタスクを他のエージェントへ並行して委譲 |
| File access | 作業ディレクトリに限定したファイル読み書きツール |
| Looping | 完了条件を満たすまでエージェントを自動で再呼び出し |
| Shell tooling | シェルコマンド実行(alpha 段階の tools パッケージ) |
この記事では、Shell toolingを除いた3機能を .NET + LM Studio のローカルLLM環境で実際に試します。GA 版コア機能の全体像と検証は前編の記事(「Microsoft Agent Framework の ハーネスのコア機能が正式リリース — LM Studioで試す 前編」)で扱っており、この記事はその後編として、前回作成した検証用サンプルにシナリオを追加する形で進めます。
この記事でわかること
- Looping / File access / Background agents の設定コードと、ローカルLLM(
google/gemma-4-12b)での実測結果 - 各機能で追加されるツールの実名(
file_access_write、background_agents_start_taskなど)
結果の全体像
| 機能 | 結果 |
|---|---|
| Looping | ループ再呼び出しとフィードバック注入を確認(完了マーカーが出ない場合は MaxIterations で停止) |
| File access |
file_access_write / file_access_read で実ファイルの生成・読込を確認 |
| Background agents | 2エージェントへの並行委譲 → 完了待機 → 結果回収 → 統合を確認 |
オプトイン機能の位置づけ
AsHarnessAgent() はコア機能(TODO 管理、モード管理、ファイルメモリ、履歴永続化、承認、テレメトリなど)をデフォルトで配線しますが、オプトイン機能は該当オプションを明示的に設定した場合のみ有効になります。
確認内容
| 確認対象 | 詳細 |
|---|---|
| experimental | オプトイン機能のプロパティ使用時のみ MAAI001 が出る |
| Looping |
LoopAgent がエージェントを再呼び出しし、継続フィードバックが注入される |
| File access |
file_access_* ツールがモデルから呼ばれ、実ファイルがディスクに生成される |
| Background agents | 並行委譲のツールが呼ばれ、複数サブエージェントの結果が統合される |
| Shell tooling | 組み込み手段の有無を API・パッケージから確認する |
環境
確認日: 2026年7月23日
| 項目 | 内容 |
|---|---|
| .NET SDK | 10.0.204 |
| パッケージ |
Microsoft.Agents.AI.Harness 1.15.0 / Microsoft.Agents.AI.OpenAI 1.15.0
|
| LM Studio endpoint | http://localhost:1234/v1 |
| LM Studio model | google/gemma-4-12b |
検証の進め方
前回のサンプルにコマンドライン引数でシナリオを選べる仕組みを足し、シナリオ 3(Looping)、4(File access)、5(Background agents)を追加しました。以降では追加部分のコードだけを抜粋します。
共通のベース構成は前回と同じで、LM Studio への OpenAI 互換接続に対して AsHarnessAgent() を呼びます。各シナリオはこのベースオプションに、それぞれのオプトイン設定を足したエージェントを作ります。
HarnessAgentOptions CreateBaseOptions() => new()
{
Name = "HarnessCoreReleaseAgent",
DisableWebSearch = true,
ChatOptions = new ChatOptions
{
Instructions = instructions,
Tools = [.. tools],
MaxOutputTokens = 100_000,
},
};
# シナリオ番号を引数で指定して実行
dotnet run --project HarnessCoreReleaseSample -- 3
MAAI001について
オプトイン機能のプロパティを使ってビルドすると、.NET では experimental 診断 MAAI001 が既定でエラーとして出ます。抑制なしでビルドした結果の抜粋です。
error MAAI001: 'Microsoft.Agents.AI.HarnessAgentOptions.LoopEvaluators' は、評価の目的でのみ提供されています。
error MAAI001: 'Microsoft.Agents.AI.HarnessAgentOptions.FileAccessStore' は、評価の目的でのみ提供されています。
error MAAI001: 'Microsoft.Agents.AI.HarnessAgentOptions.BackgroundAgents' は、評価の目的でのみ提供されています。
error MAAI001: 'Microsoft.Agents.AI.CompletionMarkerLoopEvaluator' は、評価の目的でのみ提供されています。
error MAAI001: 'Microsoft.Agents.AI.FileSystemAgentFileStore' は、評価の目的でのみ提供されています。
コア機能だけを使っている限り一切出ませんが、LoopEvaluators / LoopAgentOptions / FileAccessStore / FileAccessProviderOptions / BackgroundAgents と関連型に触れた瞬間にゲートされます。検証コードではオプトイン部分に限定して抑制しています。
#pragma warning disable MAAI001
// シナリオ 3〜5 のオプトイン設定
#pragma warning restore MAAI001
Looping
LoopEvaluators に評価器を渡すと、パイプライン最外周に LoopAgent が追加され、完了条件を満たすまでエージェントを再呼び出しします。
今回は CompletionMarkerLoopEvaluator を使い、「1回の応答で TODO を1件だけ処理し、全部終わったら DONE と書く」という指示と組み合わせました。
if (scenarios.Contains("3"))
{
// オプトイン機能: Looping(LoopEvaluators / LoopAgentOptions は experimental)
HarnessAgentOptions options = CreateBaseOptions();
options.ChatOptions!.Instructions += Environment.NewLine + """
1回の応答では TODO を1件だけ処理して、そこで応答を終えてください。
未完了の TODO が残っている間は、応答に DONE と書いてはいけません。
すべての TODO が完了した応答でのみ、末尾に DONE とだけ書いてください。
""";
options.LoopEvaluators = [new CompletionMarkerLoopEvaluator("DONE")];
options.LoopAgentOptions = new LoopAgentOptions { MaxIterations = 5 };
AIAgent agent = chatClient.AsHarnessAgent(options);
Console.WriteLine($"scenario3-agent-type={agent.GetType().FullName}");
Console.WriteLine();
await RunScenarioAsync(
agent,
"Scenario 3: Looping(オプトイン)",
"""
Looping の動作確認をします。
1. TODO リストに「果物の名前を1つ挙げる」「動物の名前を1つ挙げる」「色の名前を1つ挙げる」の3項目を登録する。
2. 指示に従い、1回の応答では TODO を1件だけ処理する。
""");
}
実行結果の抜粋です。応答の中に、LoopAgent が各イテレーションで注入する継続フィードバック(英語のメッセージ)が繰り返し現れており、ループが実際に回っていることが確認できます。
複数回実行したところ、DONE で正常終了する回と、DONE を書かないまま MaxIterations で打ち切られる回の両方がありました。正常終了したパターンでは応答の中に、LoopAgent が各イテレーションで注入する継続フィードバック(英語のメッセージ)が3回現れ、4イテレーション目の応答末尾に DONE が書かれています。
tool-calls-start
todos_add(todos=[{"title":"果物の名前を1つ挙げる"},{"title":"動物の名前を1つ挙げる"},{"title":"色の名前を1つ挙げる"}])
todos_complete(items=[{"id":1,"reason":"りんごと回答しました。"},{"id":2,"reason":"ライオンと回答しました。"},{"id":3,"reaso...)
tool-calls-end
response-start
TODO リストに以下の項目を追加しました。
... 途中省略 ...
では、最初の TODO「果物の名前を1つ挙げる」を実行します。
りんご
Continue working on the request. When you have fully completed the task, end your response with the marker 'DONE' to indicate completion.
次の TODO「動物の名前を1つ挙げる」を実行します。
ライオン
Continue working on the request. When you have fully completed the task, end your response with the marker 'DONE' to indicate completion.
次の TODO「色の名前を1つ挙げる」を実行します。
青
Continue working on the request. When you have fully completed the task, end your response with the marker 'DONE' to indicate completion.
すべての TODO を完了しました。
DONE
response-end
MaxIterations = 5 に達する前(4イテレーション目)に DONE が現れているため、これは上限による打ち切りではなく、CompletionMarkerLoopEvaluator がマーカーを検出してループを終了させたことが確認できます。
File access
FileAccessStore にストアを渡した場合のみ、ファイル読み書きツールが追加されます。プレビュー時代はデフォルト有効でしたが、最小権限の原則に基づき GA 化と同時にオプトインへ変更された機能です(PR #7093)。
既定では書き込みツールは要承認のため、非対話のコンソール検証では承認を無効化しました。
if (scenarios.Contains("4"))
{
// オプトイン機能: File access(FileAccessStore を渡した場合のみ有効になる)
string fileAccessRoot = Path.Combine(Environment.CurrentDirectory, "file-access-working");
HarnessAgentOptions options = CreateBaseOptions();
options.FileAccessStore = new FileSystemAgentFileStore(fileAccessRoot);
options.FileAccessProviderOptions = new FileAccessProviderOptions
{
// 非対話のコンソール検証のため承認を無効化する(既定では書き込みツールは要承認)
DisableReadOnlyToolApproval = true,
DisableWriteToolApproval = true,
};
AIAgent agent = chatClient.AsHarnessAgent(options);
await RunScenarioAsync(
agent,
"Scenario 4: File access(オプトイン)",
"""
File access の動作確認をします。次の作業を順に進めてください。
1. release-note.md というファイルを作成し、Microsoft Agent Framework の Harness コア機能が GA になったことを3行程度で書き込む。
2. 作成したファイルを読み直し、内容をそのまま引用して報告する。
""");
Console.WriteLine("file-access-working の実ファイル:");
if (Directory.Exists(fileAccessRoot))
{
foreach (string file in Directory.EnumerateFiles(fileAccessRoot, "*", SearchOption.AllDirectories))
{
Console.WriteLine($"--- {Path.GetRelativePath(fileAccessRoot, file)} ---");
Console.WriteLine(File.ReadAllText(file));
}
}
else
{
Console.WriteLine(" (フォルダなし)");
}
Console.WriteLine();
}
実行結果は下記の通りです。file_access_write / file_access_read というツールが追加され、モデルの判断で書き込み → 読み直しが行われました。
tool-calls-start
todos_add(todos=[{"title":"release-note.md を作成し、内容を記述する"},{"title":"作成したファイルを読み込み、内容を報告する"}])
file_access_write(content=Microsoft Agent Framework の Harness コア機能が GA になりました。..., fileName=release-note.md)
todos_complete(items=[{"id":1,"reason":"ファイル「release-note.md」を作成し、指定された内容を記述しました。"}])
file_access_read(fileName=release-note.md)
todos_complete(items=[{"id":2,"reason":"ファイルの内容を読み込み、そのまま引用して報告しました。"}])
tool-calls-end
実行後にフォルダを確認すると、file-access-working/release-note.md が実際に生成されており、内容もモデルの報告と一致していました。
Background agents
BackgroundAgents にサブエージェントを渡すと、並行委譲のためのツール群が追加されます。タスク完了までループさせるため、BackgroundTaskCompletionLoopEvaluator と組み合わせました。
if (scenarios.Contains("5"))
{
// オプトイン機能: Background agents(BackgroundAgents を渡した場合のみ有効になる)
AIAgent ideaAgent = chatClient.AsAIAgent(new ChatClientAgentOptions
{
Name = "TravelIdeaAgent",
Description = "週末の小旅行プランを1つ提案するエージェント",
ChatOptions = new ChatOptions
{
Instructions = "日本語で、週末の小旅行の行き先を1つ選び、理由とあわせて3行以内で提案してください。",
MaxOutputTokens = 100_000,
},
});
AIAgent packingAgent = chatClient.AsAIAgent(new ChatClientAgentOptions
{
Name = "PackingListAgent",
Description = "旅行の持ち物リストを作るエージェント",
ChatOptions = new ChatOptions
{
Instructions = "日本語で、1泊2日の旅行の持ち物を5項目の箇条書きで出してください。",
MaxOutputTokens = 100_000,
},
});
HarnessAgentOptions options = CreateBaseOptions();
options.BackgroundAgents = [ideaAgent, packingAgent];
// バックグラウンドタスクが完了するまで再呼び出しする(Looping との組み合わせ)
options.LoopEvaluators = [new BackgroundTaskCompletionLoopEvaluator()];
options.LoopAgentOptions = new LoopAgentOptions { MaxIterations = 5 };
AIAgent agent = chatClient.AsHarnessAgent(options);
await RunScenarioAsync(
agent,
"Scenario 5: Background agents(オプトイン)",
"""
Background agents の動作確認をします。次の作業を順に進めてください。
1. TravelIdeaAgent に週末の小旅行プランの提案を、PackingListAgent に持ち物リストの作成を、それぞれバックグラウンドタスクとして依頼する。
2. 両方の結果がそろったら回収し、1つの旅行メモとして統合して報告する。
""");
}
サブエージェントは同じ LM Studio クライアント上の ChatClientAgent を2つ(TravelIdeaAgent / PackingListAgent)用意しました。実行の流れは次の通りです。
実行結果の抜粋です。
tool-calls-start
todos_add(todos=[{"title":"TravelIdeaAgentに週末の小旅行プランを依頼する"},...)
background_agents_start_task(agentName=TravelIdeaAgent, description=週末の小旅行プランの提案(Task 1), input=...)
background_agents_start_task(agentName=PackingListAgent, description=持ち物リストの作成(Task 2), input=...)
background_agents_wait_for_first_completion(taskIds=[1,2])
background_agents_get_task_results(taskId=1)
background_agents_get_task_results(taskId=2)
tool-calls-end
response-start
バックグラウンドタスクを2つ起動しました(Task 1: TravelIdeaAgent, Task 2: PackingListAgent)。
You still have 2 background task(s) running that must finish before you can complete the work:
- #1 (TravelIdeaAgent): 週末の小旅行プランの提案(Task 1)
- #2 (PackingListAgent): 持ち物リストの作成(Task 2)
... 途中省略 ...
### 旅行メモ:週末のリフレッシュ旅行
**【提案プラン】**
* **目的地**: 箱根
... 途中省略 ...
response-end
background_agents_start_task → wait_for_first_completion → get_task_results というツールの流れと、タスク未完了時に BackgroundTaskCompletionLoopEvaluator が注入するフィードバック(「You still have 2 background task(s) running...」)が確認でき、最終応答では2つのサブエージェントの結果が1つの旅行メモに統合されました。
.NETのShell tooling
4つ目の Shell tooling は、.NET では検証できませんでした。
- GA 版
HarnessAgentOptions(1.15.0)には Shell 関連のプロパティが存在しません(プレビュー時代にあったShellExecutorオプションは PR #7119 で削除) -
Microsoft.Agents.AI.Tools.Shellパッケージは全バージョンが preview のままです(調査時点の最新は1.15.0-preview.260722.1。GA 版 Harness と同日公開ですが preview サフィックス付き) - パッケージの中身を確認すると、
LocalShellExecutor/DockerShellExecutor/ShellPolicyなどの実行基盤と、シェル環境情報をシステムプロンプトに注入するShellEnvironmentProvider(AIContextProvider)はありますが、シェル実行をモデルに公開する既製のツールは含まれていません。ツールとしての配線はハーネス本体側にあり、それが削除された形です
ShellExecutor を自前で AIFunctionFactory にラップすればモデルからシェルを呼ばせること自体は可能ですがハーネスの Shell tooling としては、パッケージの GA と Harness への再統合を待ちましょう。(もし、試せるならコメントで教えてくれると助かります。)
まとめ
- オプトイン4機能のうち、Looping / File access / Background agents は 12B クラスのローカルLLMでも動作を確認できました
- File access は GA 化と同時にオプトインへ変更されており、
FileAccessStoreを渡さない限りツール自体が利用できません。書き込みツールは既定で要承認です - Background agents は Looping(
BackgroundTaskCompletionLoopEvaluator)との組み合わせで「委譲 → 完了待機 → 統合」が成立します - Shell tooling は .NET では組み込む口が削除されており、
Microsoft.Agents.AI.Tools.Shellの GA と再統合待ちです
オプトインの機能は正式リリース前のため、ここで確認したプロパティ名や挙動は今後変わる可能性があります。ハーネスのコア機能はプレビューから正式リリースまでに結構な破壊的変更が行われていた点も考えると実際に使う場合は MAAI001 の意味(評価目的での提供)を理解した上で、破壊的変更に追従できる範囲に留めるのが安全だと思います。
参考
- 公式ブログ(リリース発表、Coming soon セクション)
- Microsoft Learn: Agent Harnesses
- GitHub: microsoft/agent-framework
- PR #7119(HarnessAgent GA 昇格・Shell 連携削除): https://github.com/microsoft/agent-framework/pull/7119
- PR #7093(FileAccess オプトイン化): https://github.com/microsoft/agent-framework/pull/7093
- .NET サンプル: https://github.com/microsoft/agent-framework/tree/main/dotnet/samples/02-agents/Harness
- パッケージ
- NuGet(Harness): https://www.nuget.org/packages/Microsoft.Agents.AI.Harness
- NuGet(Tools.Shell、preview): https://www.nuget.org/packages/Microsoft.Agents.AI.Tools.Shell
- 参照日: 2026年7月23日
Discussion