LM Studio とローカルLLMで理解する Microsoft Agent Framework ハーネスの仕組みと実行フロー
はじめに
Microsoft Agent Framework の公式ハーネスサンプルでは、TodoProvider と AgentModeProvider による計画とタスク管理を起点に、SubAgentsProvider による委譲や FileAccessProvider によるファイル入出力へと段階的に広げていきます。ここでのハーネスは、目的を達成するために手順を分けて進めるエージェント実行の枠組みです。コーディングエージェントは、その延長線上にある使い方の1つと捉えられます。
この記事では、その考え方をローカルLLMで試せるようにまとめた HarnessSample を作成して LM Studio のOpenAI互換API上でハーネスの主要要素がどう連携するかを追います。TodoProvider、AgentModeProvider、SubAgentsProvider、FileMemoryProvider を組み合わせた流れをローカルで確認できる構成に絞って整理しています。
この記事でできること
- ローカルLLMで Microsoft Agent Framework でハーネスを動かす
- Microsoft Agent Framework の主要 Provider の役割を理解して自分のプロジェクトへ応用する
- LM Studio と Web 検索ツールを組み合わせた実行例を確認する
このサンプルでは、まずハーネスの中核要素として下記の内容を確認していきます。
-
TodoProviderによる計画管理 -
AgentModeProviderによるplan/execute切り替え -
SubAgentsProviderによる役割分担 -
FileMemoryProviderによるharness-result.md保存
合わせて補助要素として下記の要素も扱います。
- LM Studio 接続
- Web検索ツールの併用
このサンプルで使うサブエージェントは下記の3つです。
OverviewResearchAgentImplementationAdviceAgentReviewChecklistAgent
公開リポジトリの中で主に見るファイルは下記の通りです。
src/HarnessSample/HarnessSample.csprojsrc/HarnessSample/Program.cssrc/HarnessSample/HarnessSampleApp.cssrc/HarnessSample/HarnessRuntimeFactory.cs
公開リポジトリ
サンプルの全体像
全体像は下記の通りです。
親エージェントには AIContextProvider 群と通常ツールの両方を登録しています。この記事では、ハーネスの中核である Provider 群と補助機能であるWeb検索ツールを分けて説明します。
LM Studio の接続設定
このサンプルでは、既存コードの LM Studio 設定をそのまま使います。
LM Studio の接続設定は HarnessSampleConfiguration.cs で固定しています。
- Endpoint:
http://localhost:1234/v1 - Model:
openai/gpt-oss-20b
接続の流れは下記の通りです。
OpenAIClient から GetChatClient(modelName) を取り、AsIChatClient() で Agent Framework 側へ渡します。
環境情報
この記事の確認時点で使っている主なバージョンは下記の通りです。
| 項目 | バージョン / 設定 |
|---|---|
| Microsoft Agent Framework |
Microsoft.Agents.AI 1.4.0 |
| 関連パッケージ |
Microsoft.Agents.AI.Abstractions 1.4.0 / Microsoft.Agents.AI.OpenAI 1.4.0 |
| .NET SDK | 10.0.203 |
| Target Framework | net10.0 |
| LM Studio | 0.4.11 |
| OpenAI 互換 Endpoint | http://localhost:1234/v1 |
| Model | openai/gpt-oss-20b |
MAFのv1.5.0でTodoProviderに変更が入りました。
v1.5.0を利用する場合はGetAllTodosメソッドの代わりにGetAllTodosAsyncメソッドを使ってください。
Microsoft Agent Framework のパッケージバージョンは HarnessSample.csproj、.NET SDK は global.json と dotnet --version、LM Studio はローカル環境の実行ファイル情報をもとに確認しています。
ハーネスの中核要素
公式ハーネスサンプル群では、大きく次の流れがあります。
- Step01:
TodoProviderとAgentModeProvider - Step02:
SubAgentsProvider - Step03: ファイル系プロバイダー
HarnessSample は、それらの考え方を1つのサンプルにまとめた構成です。ここで扱うのは Provider 群です。Web検索ツールはハーネスそのものの中核ではないため、後で補助ツールとして分けて扱います。
1. TodoProvider
TodoProvider は、エージェントに TODO を作成・更新・完了させるためのプロバイダーです。ここでは plan フェーズで TODO を作り、execute フェーズで完了項目を閉じます。
コンソール側では todoProvider.GetAllTodos(session) で状態を表示し、モデルが TODO を扱ったか確認できます。
2. AgentModeProvider
AgentModeProvider は、エージェントの現在モードを持つ仕組みです。このサンプルでは下記の2モードを使います。
planexecute
最初に plan で実行し、その後プログラム側から SetMode(session, "execute") で切り替えます。
ここでいう plan / execute は、Microsoft 公式の Harness Step01 Research サンプルの定義をベースにしています。
-
plan- 公式 README では
breaking down the topic - テーマを作業単位に分解し、TODO を作り、必要なら確認事項を出し、実行方針を固める段階
- 公式 README では
-
execute- 公式 README では
answering each research question - 承認後に各 TODO を実行し、調査、ツール利用、結果統合を進める段階
- 公式 README では
さらに公式の Step01 Research では、plan をユーザーが承認した後に execute モードへ切り替える流れになっています。この記事の HarnessSample では対話 UX を簡略化していますが、役割分担自体は同じで、plan で TODO と方針を作り、execute でサブエージェントや Web検索ツールを使って成果物を仕上げます。
この分離により、plan は「作業分解と方針決め」、execute は「委譲と成果物作成」に寄せやすくなります。
3. SubAgentsProvider
SubAgentsProvider は、親エージェントからサブエージェントへ仕事を振り、完了を待って結果を回収する仕組みです。
このサンプルでは、下記の3エージェントを用意しています。
OverviewResearchAgentImplementationAdviceAgentReviewChecklistAgent
役割は次のように分けています。
| サブエージェント | 役割 |
|---|---|
| OverviewResearchAgent | 概要、背景、重要ポイントを整理する |
| ImplementationAdviceAgent | 実装観点、使い方、設計の観点を整理する |
| ReviewChecklistAgent | 注意点、落とし穴、動作確認チェックを整理する |
execute フェーズでは、親エージェントに対して「少なくとも 2 つ以上のサブエージェントへ並列に依頼する」よう指示しています。
4. FileMemoryProvider
FileMemoryProvider は、エージェントがファイルを保存・読込するための仕組みです。このサンプルでは最終成果物を harness-result.md に保存します。
保存先は実行時の bin/.../agent-files/<session-folder>/ 配下です。
モデルが保存しなかった場合に備えて、プログラム側で EnsureResultFileSavedAsync(...) も入れています。
補助ツール
ここからは、ハーネスの中核要素とは別に、このサンプルで併用している補助ツールを見ます。
Web検索ツール
Web検索ツールは、エージェントの通常ツールとして登録しています。
有効化方法は OS 環境変数または .env ファイルです。現在の実装では、既存の環境変数を優先しつつ、起動時にリポジトリ直下の .env を読み込みます。複数の場所を検索対象にしているため scripts/.env にも対応していますが、通常はリポジトリ直下の .env を使う想定です。
Tavily
$env:TAVILY_API_KEY = "your-tavily-api-key"
TinyFish
$env:TINYFISH_API_KEY = "your-tinyfish-api-key"
$env:TINYFISH_LOCATION = "JP"
$env:TINYFISH_LANGUAGE = "ja"
この実装では、provider=auto のときに
- Tavily
- TinyFish
の順で使います。
TinyFish 側は OpenAPI ドキュメントから、次を前提にしています。
- Base URL:
https://api.search.tinyfish.ai - Header:
X-API-Key - Query parameter:
query,location,language
Tavily 側は POST /search を使う基本構成にしています。
注意: 実際のAPI 仕様は各サービスのドキュメントを確認してください。ここでは一般的な構成例を示しています。
また、API キーの管理やリクエストの実装はセキュリティや安定性の観点から適切に行ってください。
必要に応じてリクエスト間隔や呼び出し回数を調整し、レート制限にも配慮してください。
付属スクリプト
scripts/ フォルダには、API キー設定を補助するスクリプトを用意しています。
-
Set-HarnessSampleApiKeys.ps1- API キーを環境変数へ設定
-
Remove-HarnessSampleApiKeys.ps1- API キーを削除
-
New-HarnessSampleEnvFile.ps1-
.envテンプレートを生成
-
.\scripts\Set-HarnessSampleApiKeys.ps1 -TavilyApiKey "your-tavily-api-key" -Scope User
.\scripts\Remove-HarnessSampleApiKeys.ps1 -Scope User
.\scripts\New-HarnessSampleEnvFile.ps1
.env 自体は .gitignore で除外し、.env.example だけを公開対象にしています。
SearchWebAsync(query, provider, maxResults, notes)
返り値は JSON 文字列で、内部的には次のような shape にしています。
{
"provider": "tavily",
"query": "Microsoft Agent Framework Harness",
"results": [
{
"position": 1,
"title": "...",
"url": "https://...",
"snippet": "...",
"siteName": "..."
}
],
"summary": "..."
}
検索結果をそのまま埋め込むだけでは不安定なので、StructuredWebSearchAggregator で structured output に整形します。
SummaryKeyFindingsReferencesLanguage
補助コンテキスト
LM Studio のローカルモデルでは、テーマによって一般論や別文脈へ広がることがあります。
そのため、HarnessReferenceProvider という AIContextProvider を使い、次のようなローカル参照情報をコンテキストとして注入しています。
- 公式ハーネスサンプル群の要点
- この
HarnessSample実装で使っている構成 - 接続先やモデル名
- 親エージェント名
- サブエージェント名
- SaveFile の保存先と目的
ファイル構成
実装は役割ごとにファイルを分けています。
-
Program.cs- エントリポイント
-
HarnessSampleApp.cs- 起動と対話ループ
-
HarnessRuntimeFactory.cs- Agent / Provider / ツール組み立て
-
HarnessScenarioRunner.cs- plan / execute シナリオ実行
-
WebSearchService.cs- Web検索ツール本体
-
WebSearchClients.cs- Tavily / TinyFish 呼び出し
-
StructuredWebSearchAggregator.cs- 検索結果の structured output 化
実行フロー
Program.cs 自体は HarnessSampleApp を起動するだけの薄いエントリポイントです。
実際の責務は次のように分かれています。
Program.cs
-
HarnessSampleApp.RunAsync()を呼ぶ
HarnessSampleApp.cs
- LM Studio 接続を作る
- 対話ループでテーマを受け付ける
- 1 テーマごとに
HarnessRuntimeFactory.Create(...)とHarnessScenarioRunner.RunScenarioAsync(...)を呼ぶ
HarnessRuntimeFactory.cs
- 親エージェント、サブエージェント、各 Provider、Web検索ツールを組み立てる
HarnessScenarioRunner.cs
- plan / execute の 2 段階を実行する
- TODO / ChatHistory / StateBag / 保存ファイルを表示する
HarnessRuntime の役割
HarnessRuntime は、1テーマごとの実行単位に必要な要素をまとめて保持します。
AIAgentInMemoryChatHistoryProviderTodoProviderAgentModeProviderFileMemoryProviderSessionFolderPath
これにより、1回分の実行状態を分離して扱えます。
実行方法
LM Studio 側でOpenAI互換APIを有効にし、openai/gpt-oss-20b をロードした状態で下記を実行します。
dotnet run --project src/HarnessSample/HarnessSample.csproj
Web検索も使いたい場合は、先に API キーを設定します。
$env:TAVILY_API_KEY = "your-tavily-api-key"
# または
$env:TINYFISH_API_KEY = "your-tinyfish-api-key"
$env:TINYFISH_LOCATION = "JP"
$env:TINYFISH_LANGUAGE = "ja"
dotnet run --project src/HarnessSample/HarnessSample.csproj
起動すると入力例が表示されます。
-
1,2,3,4の番号でサンプルテーマ選択 - 任意の文字列で自由入力
-
exitで終了
実行結果の例
入力例 1 を選ぶと、起動後に plan モードで TODO と実行方針が表示され、その後 execute モードへ切り替わって結果保存まで進みます。実際の出力例は下記の通りです。(長いため一部省略しています。)
HarnessSample を開始します。
LM Studio Endpoint : http://localhost:1234/v1
Model : openai/gpt-oss-20b
Web Search Tool : enabled (TinyFish)
==================== Input Examples ====================
1. この HarnessSample 実装の使い方
2. この HarnessSample における SubAgents の役割
3. この HarnessSample における TodoProvider / AgentModeProvider / SubAgentsProvider / FileMemoryProvider の役割整理
4. Web検索 Tool を使った HarnessSample の調査フロー
Topic : この HarnessSample 実装の使い方
Initial Mode : plan
Working Folder : ...\agent-files\20260506_143717_7adbffdfd6b6434b9af1e22ff2d636d4
==================== Plan Response ====================
## Plan(現在のモード:plan)
... 途中省略 ...
Mode switched to: execute
==================== Execute Response ====================
- OverviewResearchAgent: テーマの概要・背景調査
- ImplementationAdviceAgent: 実装方針・設定項目
- Web検索ツールの利用: この実行では未使用
... 途中省略 ...
==================== TodoList ====================
- [x] #1 テーマ概要の整理
- [x] #2 実装ポイントの抽出
- [ ] #3 チェックリスト作成
- [ ] #4 最新情報のWeb検索
以上で execute モードにおける作業を完了し、harness-result.md を保存しました。
この実行では TODO の全項目にチェックは付きませんでしたが、現在の実装では異常ではありません。HarnessScenarioRunner は execute 後に TODO の完了数を検証しておらず、harness-result.md が無ければ保存だけを再試行する構成だからです。そのため、「一部の TODO は未完了だが、成果物の保存は成功する」という結果が発生しました。
Execute Response の抜粋
execute を抜粋して確認すると、サブエージェントから得られた要点や Web検索ツールの利用状況、TODO の進捗などが表示されていることがわかります。
==================== Execute Response ====================
**サブエージェントから得られた主要な要点**
- OverviewResearchAgent: Microsoft Agent Framework を使った .NET のサンプル実装、LM Studio エンドポイントなどを整理
- ImplementationAdviceAgent: LM Studio の起動、モデル指定、サブエージェントへの委譲フロー、ファイル保存の仕組みを整理
**Web検索ツールの利用**
- この実行では未使用
**Todoリストの進捗**
- ID 1 (`テーマ概要の整理`) と ID 2 (`実装ポイントの抽出`) は完了
- ID 3 (`チェックリスト作成`) と ID 4 (`最新情報のWeb検索`) は未完了
保存された harness-result.md の抜粋
保存された harness-result.md の先頭は下記の通りでした。
# HarnessSample の使い方
## Overview (OverviewResearchAgent 出力)
- Microsoft Agent Framework を使った .NET のサンプル実装。
- 「HarnessSample」プロジェクトとして配布され、AI アクションを段階的に管理できる。
- 目的:複数の AI サブエージェント(OverviewResearchAgent, ImplementationAdviceAgent, ReviewChecklistAgent)を組み合わせてタスクを計画・実行し、成果物を自動生成。LM Studio のローカル OpenAI 互換エンドポイント (http://localhost:1234/v1) を使用。
## Implementation Advice (ImplementationAdviceAgent 出力)
- 前提条件:LM Studio 起動、http://localhost:1234/v1 エンドポイントへのアクセス許可、モデル openai/gpt-oss-20b を設定済み。\n- 基本フロー:
1. LM Studio 起動(`lmstudio start`)。
2. `dotnet run --project HarnessSample/HarnessSample.csproj` で HarnessSampleAgent 実行。
注記:
このファイルは今回の実行で実際に保存された生成結果です。ログと参照実装を照合すると、下記の点が確認できました。
\nが本文中に混ざっており、Markdown の整形が崩れているReviewChecklistAgentの結果は未取得なのに、テンプレート上は後続でチェックリスト節を前提にしている- サンプルのため、このプロジェクトとは異なった内容も含まれている(例:
lmstudio startコマンド)
今回のログでは、ハーネスの流れとファイル保存までは確認できました。
まとめ
この記事ではローカルLLM上でハーネスの基本的な流れを順に追いました。TodoProvider、AgentModeProvider、SubAgentsProvider、FileMemoryProvider という中核要素に加えて、補助ツールとして Web検索ツールや現在日時取得の GetDateTime も併用しながら、plan から execute、SaveFile までの流れを確認しました。
このサンプルにフォルダ一覧取得やファイル読込の機能を追加していくとコードや資料を読みながら調査や修正方針を組み立てるコーディングエージェントに近い形へ拡張できそうです。
また合わせて、エラー時の確認ポイントや回復戦略まで含めて整理するとハーネスの実行フローをより実運用に近い視点で捉えやすくなります。
このサンプルが、Microsoft Agent Framework を使ってハーネスの構築やコーディングエージェントの実装を考える際の参考になれば幸いです。特にProvider やツールの役割分担のイメージを掴む一助になればと思います。
Microsoft Agent Framework の過去記事
一覧
Microsoft Agent Framework をローカルLLMで試してみる その1
Microsoft Agent Framework をローカルLLMで試してみる その2
Microsoft Agent Framework をローカルLLMで試してみる その3(LoggingFactory)
Microsoft Agent Framework をローカルLLMで試してみる その4(Tool)
Microsoft Agent Framework をローカルLLMで試してみる その5(AIFunction)
Microsoft Agent Framework をローカルLLMで試してみる その6(ChatHistoryProvider)
Microsoft Agent Framework をローカルLLMで試してみる その7(ChatHistoryProvider)
Microsoft Agent Framework をローカルLLMで試してみる その8(ChatHistoryProvider)
Microsoft Agent Framework をローカルLLMで試してみる その9(AIContextProvider)
Microsoft Agent Framework をローカルLLMで試してみる その10(AIContextProvider)
Microsoft Agent Framework をローカルLLMで試してみる その11(AIContextProviderで簡易RAG)
Microsoft Agent Framework をローカルLLMで試してみる その12(Structured Output)
Microsoft Agent Framework をローカルLLMで試してみる その13(ミドルウェア)
参考
- Microsoft Agent Framework 公式ハーネスサンプル
- 参照日: 2026年5月6日
Discussion
Notice:
SubAgentshas renamed toBackgroundAgentsvia .NET: Require TODO finish reason and rename SubAgents to BackgroundAgents#5902