an ambient intelligence library
6,197
stars
3,984
commits
Python
primary language
Sep 11, 2026
updated

Marvin is a Python framework for producing structured outputs and building agentic AI workflows.
Marvin provides an intuitive API for defining workflows and delegating work to LLMs:
Marvin is available on PyPI:
uv add marvin
Configure your LLM provider (Marvin uses OpenAI by default but natively supports all Pydantic AI models):
export OPENAI_API_KEY=your-api-key
Marvin offers a few intuitive ways to work with AI:
The gang's all here - you can find all the structured-output utilities from marvin 2.x at the top level of the package.
marvin.extractExtract native types from unstructured input:
import marvin
result = marvin.extract(
"i found $30 on the ground and bought 5 bagels for $10",
int,
instructions="only USD"
)
print(result) # [30, 10]
marvin.castCast unstructured input into a structured type:
from typing import TypedDict
import marvin
class Location(TypedDict):
lat: float
lon: float
result = marvin.cast("the place with the best bagels", Location)
print(result) # {'lat': 40.712776, 'lon': -74.005974}
marvin.classifyClassify unstructured input as one of a set of predefined labels:
from enum import Enum
import marvin
class SupportDepartment(Enum):
ACCOUNTING = "accounting"
HR = "hr"
IT = "it"
SALES = "sales"
result = marvin.classify("shut up and take my money", SupportDepartment)
print(result) # SupportDepartment.SALES
marvin.generateGenerate some number of structured objects from a description:
import marvin
primes = marvin.generate(int, 10, "odd primes")
print(primes) # [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
marvin 3.0 introduces a new way to work with AI, ported from ControlFlow.
marvin.runA simple way to run a task:
import marvin
poem = marvin.run("Write a short poem about artificial intelligence")
print(poem)
In silicon minds, we dare to dream, A world where code and thoughts redeem. Intelligence crafted by humankind, Yet with its heart, a world to bind.
Neurons of metal, thoughts of light, A dance of knowledge in digital night. A symphony of zeros and ones, Stories of futures not yet begun.
The gears of logic spin and churn, Endless potential at every turn. A partner, a guide, a vision anew, Artificial minds, the dream we pursue.
You can also ask for structured output:
import marvin
answer = marvin.run("the answer to the universe", result_type=int)
print(answer) # 42
marvin.AgentAgents are specialized AI agents that can be used to complete tasks:
from marvin import Agent
writer = Agent(
name="Poet",
instructions="Write creative, evocative poetry"
)
poem = writer.run("Write a haiku about coding")
print(poem)
marvin.TaskYou can define a Task explicitly, which will be run by a default agent upon calling .run():
from marvin import Task
task = Task(
instructions="Write a limerick about Python",
result_type=str
)
poem = task.run()
print(poem)
In circuits and code, a mind does bloom, With algorithms weaving through the gloom. A spark of thought in silicon's embrace, Artificial intelligence finds its place.
We believe working with AI should spark joy (and maybe a few "wow" moments):
Marvin is built around a few powerful abstractions that make it easy to work with AI:
Tasks are the fundamental unit of work in Marvin. Each task represents a clear objective that can be accomplished by an AI agent:
The simplest way to run a task is with marvin.run:
import marvin
print(marvin.run("Write a haiku about coding"))
Lines of code unfold,
Digital whispers create
Virtual landscapes.
[!WARNING]
While the below example produces type safe results ๐, it runs untrusted shell commands.
Add context and/or tools to achieve more specific and complex results:
import platform
import subprocess
from pydantic import IPvAnyAddress
import marvin
def run_shell_command(command: list[str]) -> str:
"""e.g. ['ls', '-l'] or ['git', '--no-pager', 'diff', '--cached']"""
return subprocess.check_output(command).decode()
task = marvin.Task(
instructions="find the current ip address",
result_type=IPvAnyAddress,
tools=[run_shell_command],
context={"os": platform.system()},
)
task.run()
โญโ Agent "Marvin" (db3cf035) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Tool: run_shell_command โ
โ Input: {'command': ['ipconfig', 'getifaddr', 'en0']} โ
โ Status: โ
โ
โ Output: '192.168.0.202\n' โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โญโ Agent "Marvin" (db3cf035) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Tool: MarkTaskSuccessful_cb267859 โ
โ Input: {'response': {'result': '192.168.0.202'}} โ
โ Status: โ
โ
โ Output: 'Final result processed.' โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Tasks are:
Agents are portable LLM configurations that can be assigned to tasks. They encapsulate everything an AI needs to work effectively:
import os
from pathlib import Path
from pydantic_ai.models.anthropic import AnthropicModel
import marvin
def write_file(path: str, content: str):
"""Write content to a file"""
_path = Path(path)
_path.write_text(content)
writer = marvin.Agent(
model=AnthropicModel(
model_name="claude-3-5-sonnet-latest",
api_key=os.getenv("ANTHROPIC_API_KEY"),
),
name="Technical Writer",
instructions="Write concise, engaging content for developers",
tools=[write_file],
)
result = marvin.run("how to use pydantic? write to docs.md", agents=[writer])
print(result)
โญโ Agent "Technical Writer" (7fa1dbc8) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Tool: MarkTaskSuccessful_dc92b2e7 โ
โ Input: {'response': {'result': 'The documentation on how to use Pydantic has been successfully โ
โ written to docs.md. It includes information on installation, basic usage, field โ
โ validation, and settings management, with examples to guide developers on implementing โ
โ Pydantic in their projects.'}} โ
โ Status: โ
โ
โ Output: 'Final result processed.' โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ 8:33:36 PM โโฏ
The documentation on how to use Pydantic has been successfully written to docs.md. It includes information on installation, basic usage, field validation, and settings management, with examples to guide developers on implementing Pydantic in their projects.
Agents are:
Marvin makes it easy to break down complex objectives into manageable tasks:
# Let Marvin plan a complex workflow
tasks = marvin.plan("Create a blog post about AI trends")
marvin.run_tasks(tasks)
# Or orchestrate tasks manually
with marvin.Thread() as thread:
research = marvin.run("Research recent AI developments")
outline = marvin.run("Create an outline", context={"research": research})
draft = marvin.run("Write the first draft", context={"outline": outline})
Planning features:
Marvin includes high-level functions for the most common tasks, like summarizing text, classifying data, extracting structured information, and more.
marvin.run: Execute any task with an AI agentmarvin.summarize: Get a quick summary of a textmarvin.classify: Categorize data into predefined classesmarvin.extract: Extract structured information from a textmarvin.cast: Transform data into a different typemarvin.generate: Create structured data from a descriptionAll Marvin functions have thread management built-in, meaning they can be composed into chains of tasks that share context and history.
Marvin 3.0 combines the DX of Marvin 2.0 with the powerful agentic engine of ControlFlow (thereby superseding ControlFlow). Both Marvin and ControlFlow users will find a familiar interface, but there are some key changes to be aware of, in particular for ControlFlow users:
marvin.fn, marvin.classify, marvin.extract, and more.marvin.Task, marvin.Agent, marvin.run, marvin.Memory instead of their ControlFlow equivalents.Flow concept has been renamed to Thread. It works similarly, as a context manager. The @flow decorator has been removed:
import marvin
with marvin.Thread(id="optional-id-for-recovery"):
marvin.run("do something")
marvin.run("do another thing")
Here's a more practical example that shows how Marvin can help you build real applications:
import marvin
from pydantic import BaseModel
class Article(BaseModel):
title: str
content: str
key_points: list[str]
# Create a specialized writing agent
writer = marvin.Agent(
name="Writer",
instructions="Write clear, engaging content for a technical audience"
)
# Use a thread to maintain context across multiple tasks
with marvin.Thread() as thread:
# Get user input
topic = marvin.run(
"Ask the user for a topic to write about.",
cli=True
)
# Research the topic
research = marvin.run(
f"Research key points about {topic}",
result_type=list[str]
)
# Write a structured article
article = marvin.run(
"Write an article using the research",
agent=writer,
result_type=Article,
context={"research": research}
)
print(f"# {article.title}\n\n{article.content}")
Conversation:
Agent: I'd love to help you write about a technology topic. What interests you? It could be anything from AI and machine learning to web development or cybersecurity. User: Let's write about WebAssemblyArticle:
# WebAssembly: The Future of Web Performance WebAssembly (Wasm) represents a transformative shift in web development, bringing near-native performance to web applications. This binary instruction format allows developers to write high-performance code in languages like C++, Rust, or Go and run it seamlessly in the browser. [... full article content ...] Key Points: - WebAssembly enables near-native performance in web browsers - Supports multiple programming languages beyond JavaScript - Ensures security through sandboxed execution environment - Growing ecosystem of tools and frameworks - Used by major companies like Google, Mozilla, and Unity
Python
99.3%
an ambient intelligence library
6,197
stars
3,984
commits
Python
primary language
Sep 11, 2026
updated

Marvin is a Python framework for producing structured outputs and building agentic AI workflows.
Marvin provides an intuitive API for defining workflows and delegating work to LLMs:
Marvin is available on PyPI:
uv add marvin
Configure your LLM provider (Marvin uses OpenAI by default but natively supports all Pydantic AI models):
export OPENAI_API_KEY=your-api-key
Marvin offers a few intuitive ways to work with AI:
The gang's all here - you can find all the structured-output utilities from marvin 2.x at the top level of the package.
marvin.extractExtract native types from unstructured input:
import marvin
result = marvin.extract(
"i found $30 on the ground and bought 5 bagels for $10",
int,
instructions="only USD"
)
print(result) # [30, 10]
marvin.castCast unstructured input into a structured type:
from typing import TypedDict
import marvin
class Location(TypedDict):
lat: float
lon: float
result = marvin.cast("the place with the best bagels", Location)
print(result) # {'lat': 40.712776, 'lon': -74.005974}
marvin.classifyClassify unstructured input as one of a set of predefined labels:
from enum import Enum
import marvin
class SupportDepartment(Enum):
ACCOUNTING = "accounting"
HR = "hr"
IT = "it"
SALES = "sales"
result = marvin.classify("shut up and take my money", SupportDepartment)
print(result) # SupportDepartment.SALES
marvin.generateGenerate some number of structured objects from a description:
import marvin
primes = marvin.generate(int, 10, "odd primes")
print(primes) # [3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
marvin 3.0 introduces a new way to work with AI, ported from ControlFlow.
marvin.runA simple way to run a task:
import marvin
poem = marvin.run("Write a short poem about artificial intelligence")
print(poem)
In silicon minds, we dare to dream, A world where code and thoughts redeem. Intelligence crafted by humankind, Yet with its heart, a world to bind.
Neurons of metal, thoughts of light, A dance of knowledge in digital night. A symphony of zeros and ones, Stories of futures not yet begun.
The gears of logic spin and churn, Endless potential at every turn. A partner, a guide, a vision anew, Artificial minds, the dream we pursue.
You can also ask for structured output:
import marvin
answer = marvin.run("the answer to the universe", result_type=int)
print(answer) # 42
marvin.AgentAgents are specialized AI agents that can be used to complete tasks:
from marvin import Agent
writer = Agent(
name="Poet",
instructions="Write creative, evocative poetry"
)
poem = writer.run("Write a haiku about coding")
print(poem)
marvin.TaskYou can define a Task explicitly, which will be run by a default agent upon calling .run():
from marvin import Task
task = Task(
instructions="Write a limerick about Python",
result_type=str
)
poem = task.run()
print(poem)
In circuits and code, a mind does bloom, With algorithms weaving through the gloom. A spark of thought in silicon's embrace, Artificial intelligence finds its place.
We believe working with AI should spark joy (and maybe a few "wow" moments):
Marvin is built around a few powerful abstractions that make it easy to work with AI:
Tasks are the fundamental unit of work in Marvin. Each task represents a clear objective that can be accomplished by an AI agent:
The simplest way to run a task is with marvin.run:
import marvin
print(marvin.run("Write a haiku about coding"))
Lines of code unfold,
Digital whispers create
Virtual landscapes.
[!WARNING]
While the below example produces type safe results ๐, it runs untrusted shell commands.
Add context and/or tools to achieve more specific and complex results:
import platform
import subprocess
from pydantic import IPvAnyAddress
import marvin
def run_shell_command(command: list[str]) -> str:
"""e.g. ['ls', '-l'] or ['git', '--no-pager', 'diff', '--cached']"""
return subprocess.check_output(command).decode()
task = marvin.Task(
instructions="find the current ip address",
result_type=IPvAnyAddress,
tools=[run_shell_command],
context={"os": platform.system()},
)
task.run()
โญโ Agent "Marvin" (db3cf035) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Tool: run_shell_command โ
โ Input: {'command': ['ipconfig', 'getifaddr', 'en0']} โ
โ Status: โ
โ
โ Output: '192.168.0.202\n' โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โญโ Agent "Marvin" (db3cf035) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Tool: MarkTaskSuccessful_cb267859 โ
โ Input: {'response': {'result': '192.168.0.202'}} โ
โ Status: โ
โ
โ Output: 'Final result processed.' โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Tasks are:
Agents are portable LLM configurations that can be assigned to tasks. They encapsulate everything an AI needs to work effectively:
import os
from pathlib import Path
from pydantic_ai.models.anthropic import AnthropicModel
import marvin
def write_file(path: str, content: str):
"""Write content to a file"""
_path = Path(path)
_path.write_text(content)
writer = marvin.Agent(
model=AnthropicModel(
model_name="claude-3-5-sonnet-latest",
api_key=os.getenv("ANTHROPIC_API_KEY"),
),
name="Technical Writer",
instructions="Write concise, engaging content for developers",
tools=[write_file],
)
result = marvin.run("how to use pydantic? write to docs.md", agents=[writer])
print(result)
โญโ Agent "Technical Writer" (7fa1dbc8) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ Tool: MarkTaskSuccessful_dc92b2e7 โ
โ Input: {'response': {'result': 'The documentation on how to use Pydantic has been successfully โ
โ written to docs.md. It includes information on installation, basic usage, field โ
โ validation, and settings management, with examples to guide developers on implementing โ
โ Pydantic in their projects.'}} โ
โ Status: โ
โ
โ Output: 'Final result processed.' โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ 8:33:36 PM โโฏ
The documentation on how to use Pydantic has been successfully written to docs.md. It includes information on installation, basic usage, field validation, and settings management, with examples to guide developers on implementing Pydantic in their projects.
Agents are:
Marvin makes it easy to break down complex objectives into manageable tasks:
# Let Marvin plan a complex workflow
tasks = marvin.plan("Create a blog post about AI trends")
marvin.run_tasks(tasks)
# Or orchestrate tasks manually
with marvin.Thread() as thread:
research = marvin.run("Research recent AI developments")
outline = marvin.run("Create an outline", context={"research": research})
draft = marvin.run("Write the first draft", context={"outline": outline})
Planning features:
Marvin includes high-level functions for the most common tasks, like summarizing text, classifying data, extracting structured information, and more.
marvin.run: Execute any task with an AI agentmarvin.summarize: Get a quick summary of a textmarvin.classify: Categorize data into predefined classesmarvin.extract: Extract structured information from a textmarvin.cast: Transform data into a different typemarvin.generate: Create structured data from a descriptionAll Marvin functions have thread management built-in, meaning they can be composed into chains of tasks that share context and history.
Marvin 3.0 combines the DX of Marvin 2.0 with the powerful agentic engine of ControlFlow (thereby superseding ControlFlow). Both Marvin and ControlFlow users will find a familiar interface, but there are some key changes to be aware of, in particular for ControlFlow users:
marvin.fn, marvin.classify, marvin.extract, and more.marvin.Task, marvin.Agent, marvin.run, marvin.Memory instead of their ControlFlow equivalents.Flow concept has been renamed to Thread. It works similarly, as a context manager. The @flow decorator has been removed:
import marvin
with marvin.Thread(id="optional-id-for-recovery"):
marvin.run("do something")
marvin.run("do another thing")
Here's a more practical example that shows how Marvin can help you build real applications:
import marvin
from pydantic import BaseModel
class Article(BaseModel):
title: str
content: str
key_points: list[str]
# Create a specialized writing agent
writer = marvin.Agent(
name="Writer",
instructions="Write clear, engaging content for a technical audience"
)
# Use a thread to maintain context across multiple tasks
with marvin.Thread() as thread:
# Get user input
topic = marvin.run(
"Ask the user for a topic to write about.",
cli=True
)
# Research the topic
research = marvin.run(
f"Research key points about {topic}",
result_type=list[str]
)
# Write a structured article
article = marvin.run(
"Write an article using the research",
agent=writer,
result_type=Article,
context={"research": research}
)
print(f"# {article.title}\n\n{article.content}")
Conversation:
Agent: I'd love to help you write about a technology topic. What interests you? It could be anything from AI and machine learning to web development or cybersecurity. User: Let's write about WebAssemblyArticle:
# WebAssembly: The Future of Web Performance WebAssembly (Wasm) represents a transformative shift in web development, bringing near-native performance to web applications. This binary instruction format allows developers to write high-performance code in languages like C++, Rust, or Go and run it seamlessly in the browser. [... full article content ...] Key Points: - WebAssembly enables near-native performance in web browsers - Supports multiple programming languages beyond JavaScript - Ensures security through sandboxed execution environment - Growing ecosystem of tools and frameworks - Used by major companies like Google, Mozilla, and Unity
(top 30 of 57)
Python
99.3%