Table of Contents

Marvin

Marvin is a Python framework by Prefect for producing structured outputs from LLMs and building agentic AI workflows. With 6.1K+ GitHub stars, it provides intuitive building blocks – cast, classify, extract, generate – that bridge AI unpredictability with type-safe, observable, composable software patterns. Version 3.0 introduces full agentic control flow with Tasks, Agents, and Threads.

Overview

Marvins philosophy treats AI capabilities as engineering building blocks rather than black-box magic. Each function enforces type safety via Pydantic, maintains observability, and composes naturally into larger workflows. The framework prioritizes making LLM interactions reliable and predictable while keeping the API minimal.

Core design principles:

Installation

pip install marvin
# or with uv
uv add marvin

Configure your LLM provider:

export OPENAI_API_KEY="your-api-key"

Core Functions

Marvin provides high-level functions for common LLM tasks:

import marvin
from pydantic import BaseModel
 
 
# --- cast: Convert unstructured text to typed objects ---
class Location(BaseModel):
    city: str
    state: str
    country: str
 
location = marvin.cast("The Big Apple", target=Location)
# Location(city=New York, state=NY, country=US)
 
 
# --- classify: Categorize data into labels ---
sentiment = marvin.classify(
    "I absolutely love this product!",
    labels=["positive", "negative", "neutral"]
)
# "positive"
 
 
# --- extract: Pull structured data from text ---
class Contact(BaseModel):
    name: str
    email: str
 
contacts = marvin.extract(
    "Reach out to Alice at alice@example.com or Bob at bob@test.io",
    target=Contact
)
# [Contact(name=Alice, email=alice@example.com),
#  Contact(name=Bob, email=bob@test.io)]
 
 
# --- generate: Produce structured outputs ---
colors = marvin.generate(
    target=str,
    instructions="Generate 5 creative color names for a cyberpunk palette",
    n=5
)
 
 
# --- fn: AI-powered function decorator ---
@marvin.fn
def summarize(text: str, max_words: int = 50) -> str:
    "Summarize the given text in the specified number of words."
 
summary = summarize("Long article text here...", max_words=30)

Agentic Workflows (v3.0)

Marvin v3.0 introduces a full agentic control flow engine:

graph TD subgraph Thread["marvin.Thread: shared context"] A[Task 1: Research] --> B[Task 2: Write Article - agent=Writer] B --> C[Task 3: Review and Edit - agent=Editor] end

import marvin
from pydantic import BaseModel
 
 
class Article(BaseModel):
    title: str
    content: str
    key_points: list[str]
 
 
# Define specialized agents
writer = marvin.Agent(
    name="Writer",
    instructions="Write clear, engaging content for a technical audience."
)
 
editor = marvin.Agent(
    name="Editor",
    instructions="Review and improve articles for clarity and accuracy."
)
 
# Orchestrate with a Thread (shared context)
with marvin.Thread() as thread:
    # Task 1: Research
    key_points = marvin.run(
        "Research the top 5 trends in AI agent frameworks for 2025",
        result_type=list[str]
    )
 
    # Task 2: Write (assigned to writer agent)
    draft = marvin.run(
        "Write a technical article using the research",
        agent=writer,
        result_type=Article,
        context={"research": key_points}
    )
 
    # Task 3: Edit (assigned to editor agent)
    final = marvin.run(
        "Review and polish the article",
        agent=editor,
        result_type=Article,
        context={"draft": draft}
    )
 
print(f"Title: {final.title}")
print(final.content)

Planning and Teams

import marvin
 
# AI-powered task decomposition
tasks = marvin.plan("Create a comprehensive blog post about AI trends")
marvin.run_tasks(tasks)
 
# Team coordination
from marvin import Team, Swarm
 
# Structured team with delegation rules
research_team = Team(
    agents=[researcher, analyst],
    instructions="Collaborate on research tasks"
)
 
# Swarm: free-form delegation among agents
creative_swarm = Swarm(agents=[writer, designer, editor])

Integration with Prefect

Marvin integrates naturally with Prefect for production orchestration:

from prefect import flow
import marvin
 
@flow
def process_github_issue(issue_payload: dict):
    summary = marvin.cast(
        issue_payload["body"],
        target=str,
        instructions="Summarize this GitHub issue in one sentence"
    )
 
    category = marvin.classify(
        summary,
        labels=["bug", "feature_request", "question", "documentation"]
    )
 
    response = marvin.generate(
        target=str,
        instructions=f"Write a helpful response to this {category} issue",
        context={"summary": summary}
    )
 
    return {"summary": summary, "category": category, "response": response}

Key Features in v3.0

References

See Also