🙆

LM Studio とローカルLLMで理解する Microsoft Agent Framework ハーネスの仕組みと実行フロー

に公開
1

はじめに

Microsoft Agent Framework の公式ハーネスサンプルでは、TodoProviderAgentModeProvider による計画とタスク管理を起点に、SubAgentsProvider による委譲や FileAccessProvider によるファイル入出力へと段階的に広げていきます。ここでのハーネスは、目的を達成するために手順を分けて進めるエージェント実行の枠組みです。コーディングエージェントは、その延長線上にある使い方の1つと捉えられます。

この記事では、その考え方をローカルLLMで試せるようにまとめた HarnessSample を作成して LM Studio のOpenAI互換API上でハーネスの主要要素がどう連携するかを追います。TodoProviderAgentModeProviderSubAgentsProviderFileMemoryProvider を組み合わせた流れをローカルで確認できる構成に絞って整理しています。

この記事でできること

  • ローカルLLMで Microsoft Agent Framework でハーネスを動かす
  • Microsoft Agent Framework の主要 Provider の役割を理解して自分のプロジェクトへ応用する
  • LM Studio と Web 検索ツールを組み合わせた実行例を確認する

このサンプルでは、まずハーネスの中核要素として下記の内容を確認していきます。

  • TodoProvider による計画管理
  • AgentModeProvider による plan / execute 切り替え
  • SubAgentsProvider による役割分担
  • FileMemoryProvider による harness-result.md 保存

合わせて補助要素として下記の要素も扱います。

  • LM Studio 接続
  • Web検索ツールの併用

このサンプルで使うサブエージェントは下記の3つです。

  • OverviewResearchAgent
  • ImplementationAdviceAgent
  • ReviewChecklistAgent

公開リポジトリの中で主に見るファイルは下記の通りです。

  • src/HarnessSample/HarnessSample.csproj
  • src/HarnessSample/Program.cs
  • src/HarnessSample/HarnessSampleApp.cs
  • src/HarnessSample/HarnessRuntimeFactory.cs

公開リポジトリ

https://github.com/yy7613/HarnessSample

サンプルの全体像

全体像は下記の通りです。

親エージェントには 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.jsondotnet --version、LM Studio はローカル環境の実行ファイル情報をもとに確認しています。

ハーネスの中核要素

公式ハーネスサンプル群では、大きく次の流れがあります。

  • Step01: TodoProviderAgentModeProvider
  • Step02: SubAgentsProvider
  • Step03: ファイル系プロバイダー

HarnessSample は、それらの考え方を1つのサンプルにまとめた構成です。ここで扱うのは Provider 群です。Web検索ツールはハーネスそのものの中核ではないため、後で補助ツールとして分けて扱います。

1. TodoProvider

TodoProvider は、エージェントに TODO を作成・更新・完了させるためのプロバイダーです。ここでは plan フェーズで TODO を作り、execute フェーズで完了項目を閉じます。

コンソール側では todoProvider.GetAllTodos(session) で状態を表示し、モデルが TODO を扱ったか確認できます。

2. AgentModeProvider

AgentModeProvider は、エージェントの現在モードを持つ仕組みです。このサンプルでは下記の2モードを使います。

  • plan
  • execute

最初に plan で実行し、その後プログラム側から SetMode(session, "execute") で切り替えます。

ここでいう plan / execute は、Microsoft 公式の Harness Step01 Research サンプルの定義をベースにしています。

  • plan
    • 公式 README では breaking down the topic
    • テーマを作業単位に分解し、TODO を作り、必要なら確認事項を出し、実行方針を固める段階
  • execute
    • 公式 README では answering each research question
    • 承認後に各 TODO を実行し、調査、ツール利用、結果統合を進める段階

さらに公式の Step01 Research では、plan をユーザーが承認した後に execute モードへ切り替える流れになっています。この記事の HarnessSample では対話 UX を簡略化していますが、役割分担自体は同じで、plan で TODO と方針を作り、execute でサブエージェントや Web検索ツールを使って成果物を仕上げます。

この分離により、plan は「作業分解と方針決め」、execute は「委譲と成果物作成」に寄せやすくなります。

3. SubAgentsProvider

SubAgentsProvider は、親エージェントからサブエージェントへ仕事を振り、完了を待って結果を回収する仕組みです。

このサンプルでは、下記の3エージェントを用意しています。

  • OverviewResearchAgent
  • ImplementationAdviceAgent
  • ReviewChecklistAgent

役割は次のように分けています。

サブエージェント 役割
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 のときに

  1. Tavily
  2. 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 に整形します。

  • Summary
  • KeyFindings
  • References
  • Language

補助コンテキスト

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 を起動するだけの薄いエントリポイントです。

実際の責務は次のように分かれています。

  1. Program.cs
  • HarnessSampleApp.RunAsync() を呼ぶ
  1. HarnessSampleApp.cs
  • LM Studio 接続を作る
  • 対話ループでテーマを受け付ける
  • 1 テーマごとに HarnessRuntimeFactory.Create(...)HarnessScenarioRunner.RunScenarioAsync(...) を呼ぶ
  1. HarnessRuntimeFactory.cs
  • 親エージェント、サブエージェント、各 Provider、Web検索ツールを組み立てる
  1. HarnessScenarioRunner.cs
  • plan / execute の 2 段階を実行する
  • TODO / ChatHistory / StateBag / 保存ファイルを表示する

HarnessRuntime の役割

HarnessRuntime は、1テーマごとの実行単位に必要な要素をまとめて保持します。

  • AIAgent
  • InMemoryChatHistoryProvider
  • TodoProvider
  • AgentModeProvider
  • FileMemoryProvider
  • SessionFolderPath

これにより、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 の全項目にチェックは付きませんでしたが、現在の実装では異常ではありません。HarnessScenarioRunnerexecute 後に 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上でハーネスの基本的な流れを順に追いました。TodoProviderAgentModeProviderSubAgentsProviderFileMemoryProvider という中核要素に加えて、補助ツールとして Web検索ツールや現在日時取得の GetDateTime も併用しながら、plan から execute、SaveFile までの流れを確認しました。

このサンプルにフォルダ一覧取得やファイル読込の機能を追加していくとコードや資料を読みながら調査や修正方針を組み立てるコーディングエージェントに近い形へ拡張できそうです。
また合わせて、エラー時の確認ポイントや回復戦略まで含めて整理するとハーネスの実行フローをより実運用に近い視点で捉えやすくなります。

このサンプルが、Microsoft Agent Framework を使ってハーネスの構築やコーディングエージェントの実装を考える際の参考になれば幸いです。特にProvider やツールの役割分担のイメージを掴む一助になればと思います。

Microsoft Agent Framework の過去記事

一覧

参考

Discussion