{"id":148,"library":"marvin","title":"Marvin (PrefectHQ)","description":"AI functions and agentic workflow library by PrefectHQ. Provides decorator-based AI functions (marvin.fn, marvin.classify, marvin.extract, marvin.cast) and agent/task orchestration. v3.0 released 2024 — merged with ControlFlow, switched LLM backend from OpenAI-only to Pydantic AI (multi-provider). Current version: 3.2.7 (Mar 2026). WARNING: 'marvin' on PyPI is PrefectHQ's AI library — not the SDSS astronomy Marvin library (sdss-marvin on PyPI).","status":"active","version":"3.2.7","language":"python","source_language":"en","source_url":"https://github.com/PrefectHQ/marvin","tags":["marvin","prefect","llm","structured-output","agents","python","ai-functions"],"install":[{"cmd":"pip install marvin","lang":"bash","label":"Python"}],"dependencies":[{"reason":"LLM backend from v3. Replaces direct OpenAI dependency from v2.","package":"pydantic-ai","optional":false},{"reason":"Default model provider. Marvin uses OpenAI by default — set OPENAI_API_KEY.","package":"openai","optional":true}],"imports":[{"note":"marvin.settings.openai.api_key pattern from v2 is gone in v3. Set OPENAI_API_KEY env var or configure via pydantic-ai settings.","wrong":"from marvin import settings\nsettings.openai.api_key = 'sk-...'\nresult = marvin.extract(...)","symbol":"marvin.extract","correct":"import marvin\n\nresult = marvin.extract(\n    'i found $30 on the ground and bought 5 bagels for $10',\n    int,\n    instructions='only USD amounts'\n)\nprint(result)  # [30, 10]"},{"note":"ai_fn decorator from v1/old docs renamed to marvin.fn in v2+. Both may exist but marvin.fn is canonical.","wrong":"from marvin import ai_fn\n\n@ai_fn\ndef sentiment(text: str) -> float:\n    ...","symbol":"marvin.fn decorator","correct":"import marvin\n\n@marvin.fn\ndef sentiment(text: str) -> float:\n    \"\"\"Returns sentiment score from -1.0 (negative) to 1.0 (positive).\"\"\"\n\nscore = sentiment('I love this product!')\nprint(score)  # ~0.9"},{"note":"ControlFlow's @flow decorator removed in v3. Use marvin.Thread() context manager instead. ControlFlow is now merged into marvin.","wrong":"from controlflow import flow\n\n@flow\ndef my_flow():\n    ...","symbol":"marvin.Thread (v3)","correct":"import marvin\n\nwith marvin.Thread() as thread:\n    marvin.run('What is quantum computing?')\n    marvin.run('How does that relate to AI?')"}],"quickstart":{"code":"# pip install marvin\nimport marvin\nimport os\n\n# Set OPENAI_API_KEY env var — marvin uses OpenAI by default\n\n# Structured extraction\nnumbers = marvin.extract(\n    'I paid $45 for lunch and $12 for coffee',\n    int,\n    instructions='USD amounts only'\n)\nprint(numbers)  # [45, 12]\n\n# Classification\ncategory = marvin.classify(\n    'The new iPhone has great camera features',\n    labels=['tech', 'sports', 'politics']\n)\nprint(category)  # 'tech'\n\n# AI function\n@marvin.fn\ndef translate(text: str, language: str) -> str:\n    \"\"\"Translates text to the given language.\"\"\"\n\nprint(translate('Hello world', 'Spanish'))  # 'Hola mundo'","lang":"python","description":"Core marvin 3.x structured output functions."},"warnings":[{"fix":"Set OPENAI_API_KEY env var. Or configure other providers via pydantic-ai settings.","message":"marvin v2 was OpenAI-only. v3 uses Pydantic AI as backend supporting all providers. marvin.settings.openai.api_key configuration pattern from v2 is gone.","severity":"breaking","affected_versions":">= 3.0.0"},{"fix":"Replace @flow decorated functions with 'with marvin.Thread(): marvin.run(...)' pattern.","message":"ControlFlow's @flow decorator removed in v3. ControlFlow merged into marvin. Use marvin.Thread() context manager instead.","severity":"breaking","affected_versions":">= 3.0.0"},{"fix":"Reset SQLite data after version updates during development. Production: handle migrations manually.","message":"Thread/message history storage changed to SQLite in v3. No database migrations available — expect data loss when updating during development.","severity":"breaking","affected_versions":">= 3.0.0"},{"fix":"pip install marvin for AI functions. pip install sdss-marvin for astronomy. Never mix.","message":"Name collision: 'marvin' PyPI package is PrefectHQ's AI library. 'sdss-marvin' is the SDSS astronomy toolkit. LLMs may conflate them. They are completely unrelated.","severity":"gotcha","affected_versions":"all"},{"fix":"Set OPENAI_API_KEY or configure a different pydantic-ai provider explicitly.","message":"Marvin defaults to OpenAI gpt-4o. No model specified = OpenAI API call. Fails silently with AuthenticationError if OPENAI_API_KEY not set.","severity":"gotcha","affected_versions":"all"},{"fix":"Use @marvin.fn not @ai_fn.","message":"ai_fn decorator from very old v1 docs still appears in many tutorials. Renamed to marvin.fn in v2+.","severity":"gotcha","affected_versions":">= 2.0"},{"fix":"Install build essentials and C/C++ libraries in your Alpine environment (e.g., 'apk add build-base libstdc++'). Alternatively, use a glibc-based Python image or ensure you're using a Rust toolchain specifically compiled for musl targets.","message":"Installation of Python packages with Rust extensions (e.g., 'temporalio') often fails on Alpine Linux (musl) due to dynamic linking requirements of the Rust toolchain or its dependencies (e.g., missing 'libgcc_s.so.1' and '_Unwind' symbols). This occurs because the Rust components might be compiled for glibc, which is incompatible with musl environments.","severity":"breaking","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T08:47:03.239Z","next_check":"2026-06-24T00:00:00.000Z","problems":[{"fix":"Set the `OPENAI_API_KEY` or `MARVIN_OPENAI_API_KEY` environment variable before running your application. Alternatively, you can configure it programmatically using `marvin.settings.openai.api_key = 'your_key_here'` (though environment variables are recommended for production).","cause":"Marvin often defaults to using OpenAI for its language models and requires an API key to be set, even when other providers might be intended for use or local models are running.","error":"ValueError: OpenAI API key not found!"},{"fix":"Update your imports to use the new names: `from marvin import fn, Agent` instead of `from marvin import ai_fn, ai_model`.","cause":"In Marvin v3.0+, the API was significantly refactored, and older function names like `ai_fn` and `ai_model` were renamed to `fn` and `Agent` respectively. Attempting to import the old names from the top-level `marvin` package will result in an `ImportError`.","error":"ImportError: cannot import name 'ai_fn' from 'marvin'"},{"fix":"Upgrade your `openai` package to the latest version using `pip install --upgrade openai` and update your code to use the modern client API (e.g., `from openai import OpenAI; client = OpenAI(); client.chat.completions.create(...)`).","cause":"This error typically arises when using an outdated version of the `openai` Python library (specifically versions older than 1.0.0) with code that expects the newer client-based API for chat completions. Marvin uses Pydantic AI which interfaces with various LLM providers, including OpenAI, making this a common dependency issue.","error":"AttributeError: module 'openai' has no attribute 'ChatCompletion'"}],"ecosystem":"pypi","meta_description":null,"install_score":38,"install_tag":"stale","quickstart_score":33,"quickstart_tag":"draft","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":6.23,"mem_mb":77.8,"disk_size":"367M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":8.13,"mem_mb":84.5,"disk_size":"399M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":9.05,"mem_mb":82.9,"disk_size":"385M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":8.55,"mem_mb":85.7,"disk_size":"384M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":8.8,"mem_mb":77.9,"disk_size":"80.5M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":7.63,"mem_mb":77.9,"disk_size":"80M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"draft","tag_description":"notable failures across runtimes","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}