モデル / データセット
PrefectHQ/marvin avatar
PrefectHQ/marvin

Marvin 3.x レビュー: 構造化出力とタスク指向エージェントを Python の型でまとめる

an ambient intelligence library

スター 6,199フォーク 415PythonApache-2.0

ひと目でわかる

これは何?
Prefect が公開する Python ライブラリ Marvin は、LLM の出力を Pydantic の型に押し込み、Task / Agent / Thread という抽象でエージェント処理を組み立てる。便利さの代わりに、実行時の依存と抽象の重さを引き受ける設計だ。
誰に向いている?
採用を検討すべきなのは、LLM の戻り値を dict や文字列のまま扱うのをやめ、Pydantic の型で検証しながらタスクを積み上げたい Python チームだ。逆に、単発のテキスト生成やチャット応答だけが目的なら、Marvin の抽象は荷が重い。
商用利用できる?
できます。Apache-2.0 は寛容なライセンスで、著作権表示とライセンス表示を残せば、使用・改変・販売が可能です。
今もメンテナンスされている?
されています。最後のコミットは 4 日前です。
何の言語で書かれている?
主に Python です(GitHub の言語統計による)。

回答はプロジェクトの GitHub データ(最終同期:2026年9月15日)と当サイトの分析に基づくもので、法的助言ではありません。

オープンソース詳細解説

Marvin が埋めようとしているのは型の隙間である

LLM を業務コードに組み込むと、戻り値が文字列や緩い JSON のまま流れてくる。呼び出し側は正規表現で切り出し、失敗したら再試行し、それでも駄目なら人間が読む。Marvin が狙うのはこの隙間だ。README は「a Python framework for producing structured outputs and building agentic AI workflows」と述べており、extract、cast、classify、generate の 4 つのユーティリティで「unstructured input」を Python の型に落とす。対象読者は、LLM の出力を既存の型付きコードに接続したい Python 開発者である。プロンプトを書くのではなく、型と命令を書くという立場を取る。

extract と cast は何を入力に取り、何を返すのか

README の例では、marvin.extract に文字列と int を渡すと [30, 10] が返る。第 3 引数の instructions で「only USD」と制約をかけている点が重要で、抽出対象の型と自然言語の制約を分離している。marvin.cast は TypedDict で定義した Location を渡すと {'lat': 40.712776, 'lon': -74.005974} のような辞書を返す。classify は Enum のメンバーを返し、generate は「odd primes」から int を 10 個生成する。いずれも戻り値が Python の型として確定するため、後続の処理で分岐や検証がしやすい。ただし README に載っている出力はあくまで例示であり、同じ入力で常に同じ値が返る保証はどこにも書かれていない。

Task と Agent は ControlFlow から移植された層である

Marvin 3.0 で追加されたエージェント制御は、Prefect の別プロジェクト ControlFlow から移植されたと README が明記している。最小の入口は marvin.run で、文字列を渡せばテキストが返り、result_type=int を渡せば 42 のような整数が返る。明示的に組む場合は marvin.Task に instructions と result_type を渡し、tools と context を添える。README の例では、シェルコマンドを実行する関数を tools に渡し、context に OS 名を入れ、result_type に Pydantic の IPvAnyAddress を指定している。実行時にはエージェント名、ツール名、入力、ステータス、出力がボックス表示でログに出る。何が起きたかを追える形にしているのが、この層の設計意図だ。

tools に渡した関数は信頼境界の外側にある

README はシェルコマンド実行の例に対して「While the below example produces type safe results, it runs untrusted shell commands」という警告を付けている。型安全であることと安全であることは別だという宣言である。LLM が生成した引数がそのまま subprocess に渡る構造なので、許可するコマンドを絞る、実行ユーザーを分ける、といった対策はライブラリ側ではなく利用側の責任になる。エージェントに渡すツールの設計は、Marvin の使い勝手ではなくセキュリティ境界の設計として扱うべきだ。

Thread とマルチエージェントは抽象の重さを伴う

README は Task を Thread に組み合わせて「more complex behaviors」を編成できると説明し、複数エージェントの調整も機能として挙げている。一方で、これらの抽象の具体的な API や制約は提示された資料からは読み取れない。Task、Agent、Thread という 3 層を先に覚える必要があり、単一のプロンプトで足りる用途には明らかに過剰である。抽象を増やすほど、モデルを差し替えたときの挙動の変化も追いにくくなる。小さく始めて、タスクの分割が実際に必要になった時点で層を足すほうが素直だ。

導入は uv add と環境変数 1 つから始まる

インストールは PyPI から行い、README のコマンドは uv add marvin である。既定のプロバイダは OpenAI で、export OPENAI_API_KEY=your-api-key を設定すれば動く。OpenAI 以外を使う場合は Pydantic AI が対応するモデルをネイティブに扱えると README は述べており、具体的なモデル指定の方法は Pydantic AI 側のドキュメントに委ねられている。つまり Marvin はモデル接続の層を自作せず、Pydantic AI に預ける構成を取っている。プロバイダを乗り換えるたびに設定を書き直す必要は薄いが、対応状況は Pydantic AI の側に追従することになる。

Pydantic AI を直接使う場合との違い

Marvin は Pydantic AI の上に乗っていると読めるが、提供するのはモデル抽象ではなくタスクの組み立て方である。Pydantic AI を直接使うなら、エージェント定義と出力型の検証は自分で書き、実行の順序や再試行も自分で決める。Marvin はそこに Task、Agent、Thread という語彙と、実行ログの表示を足す。逆に言えば、タスク分割が不要な用途では Marvin の層は何も足さない。単一のエージェントで完結する処理なら、依存を 1 つ減らして Pydantic AI を直接叩くほうが構成は短くなる。

Apache-2.0 とバージョン追従のコスト

ライセンスは Apache-2.0 で、商用利用を含む利用が可能な条項を含むが、個別の法的判断はここでは扱わない。バージョンは v3.2.5 から v3.2.7 まで約 2 か月で 3 回のリリースが記録されており、パッチ更新の頻度は低くない。3.0 で ControlFlow からエージェント層が入った経緯があるため、2.x 系の extract や cast だけを使うコードと、3.x 系の Task を使うコードでは前提が異なる。依存を固定するか、少なくともマイナー更新のたびに tools まわりの挙動を確認する運用を決めてから導入したほうがよい。

編集部の結論

採用を検討すべきなのは、LLM の戻り値を dict や文字列のまま扱うのをやめ、Pydantic の型で検証しながらタスクを積み上げたい Python チームだ。逆に、単発のテキスト生成やチャット応答だけが目的なら、Marvin の抽象は荷が重い。導入前に確認すべきは、tools に渡す関数が副作用を持つ場合の扱いと、OpenAI 以外のモデルを Pydantic AI 経由で使うときの設定方法の 2 点である。

公式情報源

  1. License: Apache-2.0
  2. PrefectHQ/marvin on GitHub
  3. Project website
  4. README
  5. Releases
コミュニティノート

コミュニティノート