# magentic: turning Python functions into LLM calls with @prompt and @chatprompt

> magentic is a Python library that turns a function signature into an LLM call. The decorators are easy to adopt; the hard part is knowing when the model is the wrong implementation for a function.

**jackmpcollins/magentic** — Seamlessly integrate LLMs as Python functions

- Repository: https://github.com/jackmpcollins/magentic
- Website: https://magentic.dev/
- Stars: 2,426 · Forks: 127
- Language: Python
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/jackmpcollins-magentic

## The gap magentic fills between a prompt string and a typed Python call

Most LLM code starts as a string concatenation and a JSON parse. The prompt lives in one file, the response schema lives in a comment, and nothing type-checks. magentic's answer is to make the function signature the contract. You write a normal Python function with annotations, decorate it, and leave the body empty. The decorator reads the annotations, builds the prompt, calls the model, and returns an object of the declared type.

The README states the project's purpose directly: use the @prompt and @chatprompt decorators to create functions that return structured output from an LLM, and combine LLM queries and tool use with traditional Python code. That second clause is the part that matters. The library is not a framework that owns your control flow. It is a set of decorators you drop into ordinary Python, which means the surrounding code stays testable with the tools you already use.

The audience is therefore narrow and specific. If you are building a Python service, a data pipeline, or a CLI where a model has to produce a value of a known shape, this fits. If you want an agent runtime with planning, memory, and a web interface, this is the wrong layer.

## How @prompt, @chatprompt and @prompt_chain move data

The mechanism is template substitution plus schema enforcement. With @prompt you pass a single string containing curly-brace fields. When the function is called, the arguments are inserted into the template and the result is sent to the model. The return annotation is not decoration: it is converted into a schema the model must satisfy. The README shows a plain str return and a pydantic BaseModel return, and notes that any type supported by pydantic can be used.

@chatprompt is the same pipeline with a message list instead of one string. You supply SystemMessage, UserMessage and AssistantMessage objects, and the README states that format fields denoted by curly braces are filled in all messages except FunctionResultMessage. The AssistantMessage example in the README contains a filled-in pydantic object, which is how few-shot prompting is expressed here: you show the model a completed answer rather than describing the format in prose.

Function calling changes the return type rather than the call. When you pass functions=[...] to the decorator, the model may respond with a FunctionCall object instead of a final value. That object holds the chosen function and the arguments the model produced. Calling it executes your Python function. @prompt_chain wraps this in a loop: it resolves FunctionCall objects, feeds the results back to the model, and repeats until a final answer is produced. The README's weather example is exactly this shape, where get_current_weather is called first and its return value informs the final string.

The composition rule is the most interesting design decision. LLM-backed functions created with these decorators can themselves be passed as functions to other decorated functions. That gives you a call graph of model-backed steps, each one separately testable, rather than one large prompt.

## Installing magentic and getting a first structured result

The package requires Python 3.10 or newer according to pyproject.toml. Install it with pip, or with uv if that is your toolchain.

```bash
pip install magentic
```

```bash
uv add magentic
```

The README says to configure your OpenAI API key by setting the OPENAI_API_KEY environment variable, and points to the configuration docs for other providers. The base install depends on openai, pydantic, pydantic-settings, filetype, logfire-api and typing-extensions. Anthropic and litellm are optional extras, so a non-OpenAI provider may need an extra install step that the README does not spell out on the front page.

A first real use is a function that returns a pydantic model rather than a string. This is where the library earns its place, because the return value is a validated object and not text you have to parse.

```python
from magentic import prompt
from pydantic import BaseModel


class Superhero(BaseModel):
    name: str
    age: int
    power: str
    enemies: list[str]


@prompt("Create a Superhero named {name}.")
def create_superhero(name: str) -> Superhero: ...


create_superhero("Garden Man")
```

The README gives the expected result as a Superhero instance with name 'Garden Man', age 30, power 'Control over plants' and enemies ['Pollution Man', 'Concrete Woman']. Your values will differ because the model generates them. What you should check is the type: you get a Superhero object, not a dict or a string, and a response that does not fit the schema is where the retry behaviour described in the docs comes in.

If you want to try function calling, the README's search example passes functions=[search_twitter, search_youtube] to @prompt with a FunctionCall[str] return annotation. The model picks a function and arguments, and you decide when to call the returned object. Note that the decorator does not execute it for you.

## Where magentic hands control back to the model, and where that hurts

The FunctionCall design is honest about a real problem: the model chooses which function to call and what arguments to pass. The README's own example shows the model returning a search_twitter call with the query 'LLMs' and category 'latest' for the question about the latest news on LLMs. Nothing in the library guarantees that choice is correct. If your application cannot tolerate a wrong tool selection, you need a validation layer, and the README does not describe one.

@prompt_chain has the same exposure with a longer leash. It resolves calls and continues until a final answer is reached. A model that keeps requesting functions, or requests one that fails, is a loop you have to bound yourself. The README does not document a maximum iteration count or a timeout for the chain.

There is a second boundary worth stating plainly. The project is a library, not a service. It has no persistence, no queue, no scheduling, and no UI. If your requirement is a long-running agent that survives a process restart, magentic gives you the LLM call and leaves the surrounding machinery to you.

Finally, the maintenance picture. The last push to the default branch was on 2026-03-11, which is the same day as the v0.41.1 release. The release before that, v0.41.0, was on 2025-10-14. The version numbers are still below 1.0, so the API can change between minor releases. Pin the version in production.

## magentic compared with Microsoft's Magentic-One and Magentic-UI

Search traffic for this project is tangled up with Microsoft research. Queries like Magentic-One, Magentic one GitHub and Magentic one paper refer to a different thing entirely, and the confusion is worth clearing up because it changes what you should install.

Magentic-One is a multi-agent system from Microsoft Research, described in a paper, with an orchestrator agent coordinating specialized agents to complete open-ended tasks. Magentic-UI is a related interface project. Both are agent systems. jackmpcollins/magentic is a Python library for calling models from functions. The name overlap is unfortunate and the topics list on the repository includes both 'magentic' and 'magnetic' as well as 'magenta', which suggests the author is aware of the collision.

The practical difference is the unit of work. With Magentic-One you hand over a task and an orchestrator decides the steps. With this library you write the steps in Python and the model fills in the parts that need judgement. If your problem is 'browse this site and book a table', the orchestrator model is the right shape. If your problem is 'given this ticket text, return a typed triage record', writing that as a decorated function is simpler and far easier to test.

A closer alternative in spirit is calling the provider SDK directly and validating with pydantic yourself. That gives you full control over retries, streaming and message construction, at the cost of writing the schema plumbing and the retry logic that magentic already provides.

## Licence, dependencies and the cost of upgrading

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive licence and it is the same one used by most of the Python ecosystem. It is not legal advice; if you are redistributing the library inside a product, have your own counsel review the notice requirements.

The dependency list is short and mostly uncontroversial: pydantic, openai, pydantic-settings, filetype, logfire-api and typing-extensions. Two of those deserve attention. The openai package is a base dependency even if you plan to use Anthropic or another provider, so it will be installed regardless. logfire-api is the API-only package, which means the tracing integration does not force the full Logfire SDK on you.

Upgrade cost is driven by the pre-1.0 versioning. Between v0.40.0 in June 2025 and v0.41.0 in October 2025 there was a minor bump, and v0.41.1 followed in March 2026. Minor bumps below 1.0 commonly carry breaking changes. The repository ships a Makefile with a test target that runs pytest and a typecheck target that runs mypy in strict mode, which tells you the project takes its own type surface seriously, but that does not protect your code from a signature change. Pin the version, read the release notes before bumping, and keep your decorated functions thin so a change in the decorator contract touches few call sites.

## Conclusion

Adopt magentic when your LLM usage is already shaped like a Python function: typed inputs, a pydantic model or built-in return type, and a call site you want to unit test. Skip it when you need a hosted multi-agent product with a browser UI, or when your task is deterministic string manipulation that does not need a model at all. Before committing, verify three things in your own environment: that your provider is one of the configured options, that your return type is expressible as a pydantic model, and that a wrong FunctionCall name or a malformed JSON response is something your code handles rather than crashes on.

## FAQ

### What is magentic and how is it different from Microsoft Magentic-One?

jackmpcollins/magentic is a Python library that turns decorated functions into LLM calls using @prompt and @chatprompt. Magentic-One is a separate multi-agent system from Microsoft Research that appears in search results under a similar name.

### How do I install magentic?

The README gives pip install magentic, or uv add magentic if you use uv. It requires Python 3.10 or newer, and the README says to set the OPENAI_API_KEY environment variable for the default provider.

### Does magentic return plain strings or structured objects?

It respects the return type annotation of the decorated function. The README states this can be any type supported by pydantic, including a pydantic model, and shows both a str return and a BaseModel return.

### Can magentic call my own Python functions?

Yes, by passing functions=[...] to the decorator. The README states the model may return a FunctionCall object holding the chosen function and arguments, which you then call to execute the function.

## Sources

- [jackmpcollins/magentic on GitHub](https://github.com/jackmpcollins/magentic)
- [License: MIT](https://github.com/jackmpcollins/magentic/blob/main/LICENSE)
- [Project website](https://magentic.dev/)
- [README](https://github.com/jackmpcollins/magentic/blob/main/README.md)
- [Releases](https://github.com/jackmpcollins/magentic/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jackmpcollins-magentic
