Margarita aims to make writing Agents as easy as writing Markdown.
intro.mp4
It provides two file formats:
.mg— A templating language that renders dynamic prompts to Markdown. Extends Markdown with variables, conditionals, loops, and includes..mgx— An agent scripting language that extends.mgwith agentic execution: state, memory, tool calls, user input, and more.
- Agentic execution — run
.mgxscripts as stateful agents with memory and tool calls in a TUI. - Composable — .mg files can be split, reused, and nested with
[[ include.mg ]]syntax. - Logical structures — conditionals and loops for dynamic prompt generation.
if,else,elif, andforblocks supported. - Context management — manage agent context with
@effect context. - Memory — persist variables across runs with
@memory. - Input — prompt the user for input during a run with
@effect input. - Tools — register Python functions as LLM-callable tools with
@effect tools. - Function calls — execute Python functions directly and save their result to state with
@effect func. - Sub Agents — call other
.mgxfiles as sub-agents with@effect exec. - Metadata — attach version and description metadata alongside your prompts.
parametersfield for defining expected context variables.
- A Github Copilot subscription or Ollama installed locally is required to use the agentic features of Margarita (i.e. to run
.mgxfiles). We're working on adding more llm backends currently.
Run the following command to install Margarita using uv:
uv tool install margarita
margarita use ollama
margarita run example.mgx.mg files are Margarita templates. They render to plain Markdown and can be used anywhere Markdown is supported.
// file: helloworld.mgx
@state name = "World"
<<
Hello, ${name}!
Welcome to Margarita templating.
>>
@effect run
if is_admin:
<< Welcome, Admin ${name}! >>
else:
<< Welcome, User ${name}! >>
<< # Items >>
for item in items:
<<
- ${item}
>>
Range loops are also supported:
for i in range(3):
<< Step ${i} >>
Split prompts into reusable fragments and compose them:
// file: role.mg
<< You are a ${type} AI assistant. >>
// file: prompt.mg
[[ role type="helpful" ]]
if output_json:
[[ json_output_format ]]
---
title: "Greeting Template"
version: "1.0"
author: "Batman"
---
<<
Hello, ${name}!
Welcome to Margarita templating.
>>
# Render a template
margarita render template.mg
# Render with inline JSON context
margarita render template.mg -c '{"name": "Alice"}'
# Render with a context file
margarita render template.mg -f context.json
# Render a directory of .mg files
margarita render templates/ -o output/
# Show metadata
margarita metadata template.mg
# Render and show metadata
margarita render template.mg --show-metadata.mgx files extend .mg templates with agentic capabilities: Python imports, @state, @memory, @effect directives, and agent execution.
Run them with:
margarita run example.mgxNote: Margarita's agent runner uses GitHub Copilot CLI. You will need it installed and configured.
---
description: Hello world agent template
---
<<
# Hello World
Tell the user Hello, and welcome them to Margarita!
>>
@effect run
The << >> block loads Markdown content into the agent's context. @effect run tells the agent to execute with the current context.
Define variables accessible during a run with @state:
@state count = 0
<< Set the count variable to 5. >>
@effect run
Persist variables across runs with @memory. Values are saved to memory.json at the end of each run and loaded at the start of the next:
@memory var favorite_color
<<
If favorite_color is not set, set it to "blue".
Otherwise log "The user's favorite color is ${favorite_color}".
>>
@effect run
Register Python functions as LLM-callable tools with @effect tools:
from math import add, AddParams
<< Add 3 and 5. >>
@effect tools add(x: AddParams) => result
@effect run
Note: Tool params must be a valid Pydantic model.
Execute Python functions directly (without an LLM tool call) and save their result to state:
from my_module import compute
@effect func compute(x) => result
Prompt the user for input during a run:
@effect input "What is your favorite color?" => favorite_color
@effect log "The user's favorite color is ${favorite_color}."
---
model: "gpt-4"
---
<< Your prompt here. >>
@effect run
Install via pip, poetry, uv, or any package manager:
pip install margarita
poetry add margarita
uv add margaritafrom margarita.parser import Parser
from margarita.renderer import Renderer
template = """
<<
You are a helpful assistant.
Task: ${task}
>>
if context:
<<
Context:
${context}
>>
<< Please provide a detailed response. >>
"""
parser = Parser()
metadata, nodes = parser.parse(template)
renderer = Renderer(
context={"task": "Summarize the key points", "context": "User is researching AI agents"}
)
prompt = renderer.render(nodes)
print(prompt)Use the Composer to build prompts from multiple template fragments:
from margarita.composer import Composer
from pathlib import Path
manager = Composer(Path("./templates"))
prompt = manager.compose_prompt(
snippets=[
"snippets/system_role.mg",
"snippets/task_context.mg",
"snippets/chain_of_thought.mg",
"snippets/output_format.mg"
],
context={
"role": "data scientist",
"user_name": "Bob",
"task": "Analyze customer churn",
"format": "JSON",
"tone": "analytical"
}
)Full documentation is available at https://banyango.github.io/margarita/latest
This project uses uv for dependency management.
make installmake testmake format
make lintuv buildContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please make sure to:
- Update tests as appropriate
- Follow the existing code style
- Update documentation for any changed functionality
- Kyle Reczek - Initial work - Banyango
See CHANGELOG.md for a history of changes to this project.
If you encounter any problems or have questions, please open an issue.