Skip to main content
Glama

pdml-agent

プロパティ駆動型機械学習実験パイプライン上で動作するMCPサーバーおよびツール呼び出しエージェント。計算リソースを消費するすべての処理に人間が介在するゲートがあり、すべての呼び出しの構造化トレースを提供します。

プロパティ駆動型機械学習は、形式論理の制約に対して分類器を訓練します。そのため、実行は制約、データセット、微分可能な論理、シードによって定義され、各エポックごとに予測性能と制約セキュリティの両方のメトリクスを生成します。これにより、デモ用ではなく、真にツールとして機能する領域となります。実験の一覧表示、設定の取得、結果の読み取り、実行の比較、新しい実行の計画、承認、実行が可能です。

ステータス: スコープ内で完了。 サーバー、エージェント、ゲート、トレーシング。CPU上での実際の実行を実証済み。

Architecture

┌──────────────────────────────────────────────────────────────┐
│  agent.py                       (Anthropic SDK tool runner)  │
│                                                              │
│   claude-opus-5 ──► pending tool_use ──► ToolLedger.wrap     │
│        ▲                                   │  memoise (RO)  │
│        │                                   │  gate (compute)│
│        │ tool_result                       │  trace (JSONL) │
│        └───────────────────────────────────┘        │        │
└─────────────────────────────┬───────────────────────┼────────┘
                   MCP over stdio                     ▼
┌─────────────────────────────┴────────────────┐   traces/*.jsonl
│  server.py           (mcp MCPServer, thin)   │
│   list_experiments  get_experiment_config    │
│   get_results       compare_runs             │
│   search_logic_definitions                   │
│   run_experiment ──► PDML_ALLOW_EXECUTE=1 ?  │
└────┬───────────┬──────────────┬──────────────┘
     ▼           ▼              ▼
experiments.py  logic_defs.py  runner.py ──► subprocess: main.py
(read CSVs)     (parse source)  (plan/execute)   in property-driven-ml

agent.py はドメインについて何も知りません。他のMCPクライアントと同様にstdio経由でサーバーに接続し、サーバーが公開するツールのみを使用します。ドメインモジュールはMCP依存関係を持たず、インポート可能でテスト可能です。server.py はツールを登録して委任するだけです。

Layout

pdml_agent/
  experiments.py   reading and comparing runs
  logic_defs.py    searching the logic implementations
  runner.py        validating, planning and executing runs
  server.py        the MCP layer, deliberately thin
  agent.py         the agent: runner, gate, memoisation, tracing
scripts/
  make_fixtures.py generate sample runs
  smoke_test.py    start the server, exercise every tool, check refusals
  demo.py          run the agent on five tasks
fixtures/results/  sample runs, so nothing needs a GPU to demo
demo_output/       what the agent said and did, one JSON per task
traces/            one JSONL per run, every turn and every call

Tools

ツール

戻り値

list_experiments

実行の一覧。制約、データセット、論理でフィルタ可能。

get_experiment_config

実行が実際に訓練に使用した設定。

get_results

1エポックのメトリクス。デフォルトは最後のエポック。

compare_runs

2つの実行間の設定とメトリクスの差分。

search_logic_definitions

論理クラス、その演算子、docstring。

run_experiment

dry_run=true の場合は検証済みコマンド計画。dry_run=false の場合は2つのゲートによる実行。

The gate

run_experiment は計算リソースを消費する唯一のツールであり、その前に2つの独立した障壁があります。

サーバーは PDML_ALLOW_EXECUTE=1 で起動されない限り実行しません。 これはサーバーを実行する者が下す決定であり、いかなるリクエストも変更できません。これがない場合、dry_run=false は計画を添付した status: refused を返し、エラーではありません。

エージェントは、オペレーターが正確な呼び出しを承認しない限り、実行リクエストを送信しません。 承認プロンプトには、ツール名と全引数がJSON形式で表示され、要約は表示されません。拒否された場合、declined_by_operator という通常の結果が返され、モデルはそれを報告して再試行せずに停止するよう指示されます。

どちらか一方の層だけでも不要な実行を防げます。両方があることで、どちらも完璧である必要はありません。承認が必要なものを決定するポリシーは、一目で読めるほど小さな関数 needs_approval です。

The trace

すべての実行は traces/<timestamp>-<question>.jsonl に追記されます。イベントごとに1行で、上書きされることはありません。

turn レコードには、ステップ番号、モデルの停止理由、テキストと思考の要約、これから行う呼び出し、そのターンのトークン使用量が含まれます。tool_call レコードには、ツール、その引数、呼び出しが成功したか、キャッシュから来たか、ゲートされたか、そのレイテンシ、結果の要約、そしてモデル自身が述べた理由(呼び出しとともに書かれた文から取得)が含まれます。gate レコードには決定が含まれます。run_startrun_end は合計で囲みます。

システムプロンプトは、モデルに各呼び出しを行う理由を1文で述べるよう求め、実際にそのようにします。拒否パスのトレースから:

turn 1  "I'll start by finding the existing YG runs to confirm identifiers."
turn 2  "No results with those filters; let me broaden."
turn 3  "The constraint is named `standard-robustness`. Let me get the seed-0 run's config and results."
turn 4  "Now the dry-run plan for the requested run (matching epsilon 0.3 from the seed-0 baseline)."
turn 5  "Plan validated. Now executing it."          ← gate: declined
turn 6  "The training run was not executed: the operator declined ..."

そのトレースは、このリポジトリのツール自体の欠陥も捉えました。ターン1は、list_experiments が結果フォルダ名でフィルタリングするのに対し、run_experiment はクラス名を使用していたため、空の結果になりました。これは1つの概念に対する2つの語彙です。モデルは1ターンを犠牲にして自力で回復し、そのターン3の理由は正確に解決した内容を示しています。list_experiments は現在、どちらの表記も受け入れます。

What the demos showed

5つのタスク。1回の呼び出しで答えられるものはありません。完全なトランスクリプトは demo_output/ に、完全なトレースは traces/ にあります。

A. 精度予算内での最適な論理。 3ターン。実行を一覧表示し、1つの並列ターンで4つの結果すべてを取得。0.76精度ポイントに対して0.9981のセキュリティでYGと回答し、何も実行されなかったと述べました。

B. 既存の実行のバリアントを計画。 4ターン。1つの並列ターンで設定、比較、論理定義を取得し、dry_run=truerun_experiment を呼び出し、計画と正確なコマンドを報告。一致する実行が存在したため、それらを比較しました。

C. 存在しない実行との比較。 3ターン。推測せずに最初に一覧表示し、STLが単に実行がないだけで実際の論理であることを確認し、そのように述べました。

D. 訓練、オペレーターが拒否。 6ターン。ツールの説明に従って最初にドライランで計画し、その後実行を要求。承認者が拒否。モデルは実行されなかったことを報告し、再試行せず、計画を示し、存在するもので回答しました。

E. 訓練、オペレーターが承認。 6ターン、実際の訓練実行。同じ計画→実行のシーケンス。承認者が受け入れ、実行を有効にして起動されたサーバーがCPU上で main.py を1エポック実行し、28.6秒で fixtures/results/standard-robustness/mnist/1/YG.csv を書き込みました。エージェントは新しい実行に対して get_resultscompare_runs を呼び出し、最終的な Test-P-Metric 0.9160、Test-C-Sec-self 0.5482 を報告しました。両方ともCSVと一致します。 促されずに、シード0の比較に対する交絡因子(1エポック対10エポック、遅延、意図的に弱めた攻撃予算)を列挙し、エポック0の行から、制約セキュリティは未訓練モデルでは自明に1.0であり、収束した精度と一緒でなければ意味がないと観察しました。これはメトリクスの正しい読み取りです。

そのシード1のCSVは実際の実行であり、意図的に合成フィクスチャの横に保持されています。その最初の行は、他のすべての実行と同様に、訓練に使用されたargvです。

Two things worth knowing about the data

エポック0は訓練前の評価です。 --epochs 10 で設定された実行は、0から10までの番号が付けられた11行を書き込みます。行数と最終エポックは別々に報告されます。これは、行数を「エポック」と呼ぶと訓練が1つ過大評価されるためです。

訓練スクリプトは、評価しなかったメトリクスに対して -1 を書き込みます。 get_results はこれらをnullに正規化するため、センチネル値が測定値として読み取られることはありません。ベースライン実行には制約メトリクスがまったくなく、マイナス1を報告するのではなく、そのように述べるべきです。

Limits, stated so they are not overclaimed

モデルは5つのタスクを通じてライブで is_error ツール結果に遭遇しませんでした。これは、識別子を信頼する前に一覧表示するという指示に従ったためです。エラーパスはプロトコルレベルで smoke_test.py で、ラッパーレベルでテストされていますが、タスク途中のツールエラーからのライブ回復は実証されていません。

メモ化はライブで発動しませんでした。モデルはどの実行でも同一の呼び出しを繰り返しませんでした。単体テストされ、すべてのトレースでアイドル状態です。

プロンプトキャッシングは構成されていません。すべてのトレースで cache_read_input_tokens はゼロであり、入力トークン数(タスクあたり11k〜46k)はほとんどが再送信されたコンテキストです。ツール定義とシステムプロンプトにキャッシュブレークポイントを設定すればそれが大幅に削減され、明らかな次の改善点です。

実行を実行するには、main.py がパースできるチェックアウトが必要でした。上流の main ではパースできません。--epsilon--delta がそれぞれ2回定義されており、argparseが引数を読み取る前に重複を拒否するため、python main.py --help が失敗します。これはフォークの fix/duplicate-argparse-flags ブランチで修正され、回帰テストがあり、デモでは PDML_REPO_DIR をそのチェックアウトに向けました。

Try it

uv sync
uv run python scripts/make_fixtures.py
uv run python scripts/smoke_test.py

スモークテストは、サーバーをstdio経由で起動し、ツールを列挙し、すべてを呼び出し、PDML_ALLOW_EXECUTE なしで実行が拒否されることを確認し、未知の実験IDがエラーを返し、黙って成功しないことを確認します。コストはかかりません。

エージェントに何かを尋ねるには、ANTHROPIC_API_KEY を設定して:

uv run python -m pdml_agent.agent "Which mnist run has the best constraint security?"
uv run python scripts/demo.py A B C D

実際に訓練させるには、main.py がパースできる property-driven-ml のチェックアウトと、torch がインストールされたインタープリタを指定し、実行を有効にするフラグを渡します:

export PDML_REPO_DIR=~/property-driven-ml
export PDML_PYTHON=~/property-driven-ml/.venv/bin/python
uv run python -m pdml_agent.agent --allow-execute "Train a one-epoch YG run on mnist at seed 2 ..."
uv run python scripts/demo.py E

正確な呼び出しが表示され、承認を求められます。

サーバーが読み取る環境変数:PDML_RESULTS_DIR(実行が保存される場所、デフォルト fixtures/results)、PDML_REPO_DIR(property-driven-ml のチェックアウト)、PDML_PYTHONmain.py のインタープリタ、それ以外はリポジトリの .venv)、PDML_ALLOW_EXECUTE1 で実行を許可)、PDML_EXECUTE_TIMEOUT(秒、デフォルト 3600)。

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.

  • MCP server for generating rough-draft project plans from natural-language prompts.

  • The MCP server for Azure DevOps, bringing the power of Azure DevOps directly to your agents.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/HappyHackingOrange/pdml-agent'

If you have feedback or need assistance with the MCP directory API, please join our Discord server