output
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.
## Why Marvin?
We believe working with AI should spark joy (and maybe a few "wow" moments):
- ๐งฉ **Task-Centric Architecture**: Break complex AI workflows into manageable, observable steps.
- ๐ค **Specialized Agents**: Deploy task-specific AI agents for efficient problem-solving.
- ๐ **Type-Safe Results**: Bridge the gap between AI and traditional software with type-safe, validated outputs.
- ๐๏ธ **Flexible Control**: Continuously tune the balance of control and autonomy in your workflows.
- ๐น๏ธ **Multi-Agent Orchestration**: Coordinate multiple AI agents within a single workflow or task.
- ๐งต **Thread Management**: Manage the agentic loop by composing tasks into customizable threads.
- ๐ **Ecosystem Integration**: Seamlessly work with your existing code, tools, and the broader AI ecosystem.
- ๐ **Developer Speed**: Start simple, scale up, sleep well.
## Core Abstractions
Marvin is built around a few powerful abstractions that make it easy to work with AI:
### Tasks
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`:
```python
import marvin
print(marvin.run("Write a haiku about coding"))
```
```bash
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:
```python
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()
```
```bash
โญโ 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:
- ๐ฏ **Objective-Focused**: Each task has clear instructions and a type-safe result
- ๐ ๏ธ **Tool-Enabled**: Tasks can use custom tools to interact with your code and data
- ๐ **Observable**: Monitor progress, inspect results, and debug failures
- ๐ **Composable**: Build complex workflows by connecting tasks together
### Agents
Agents are portable LLM configurations that can be assigned to tasks. They encapsulate everything an AI needs to work effectively:
```python
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)
```