Margarita introduces a deterministic scripting extension to Markdown that keeps your agents predictable. No more fighting with your prompt to make it follow your workflow steps.
Margarita is for people that are looking for repeatable scripts that add in the dynamic abilities of LLMs where it makes sense.
Use the right tool for the job. Write code-like logic where you need consistency. Bring in a code agent where you need complexity/ and dynamic responses.
Why Margarita
The syntax is a very minimal extension to markdown and will always run the same. No more having the llm skip a step in your workflow every 3rd time you run it. No more inventing properties your JSON objects. Keep control when you need control.
Most AI code harnesses hide the context from you. Margarita gives you complete control. Turf data you don't need. Add the specific tools you need and no more. Run Python functions locally instead of burning tokens on tool calls. All of these methods can keep your contexts focused and tight.
@effect context clearRemember React? Compose prompts together just like it. Use conditional logic and parameter passing. Render fragments in a loop. All the things you wished Markdown shipped with.
[[ snippets/role.mg is_admin=True permission="view" ]]What can you build?
Create a Margarita script that loads your inbox from Apple Mail, injects the results into a prompt, and gets a categorized summary with action items.
from src.applemail import load_emails
@effect func load_emails(limit=20) => result
<<
Summarize the last 20 emails I've gotten.
- Categorize them.
- Give me an action item list.
- Ignore spam type emails.
Here are the emails: ${result}
>>
@effect run
See full guide: Summarize Your Emails →
Want to build a custom ralph loop? Create a custom agent that has all the steps you want.
@effect input "What do you want to build?:" => userInput
// We have a prompt in this file to break input into tasks
// This is an example of an include
[[ break_down_input_into_tasks.mg input=userInput ]]
// Also tell the llm to store into the tasks var
<< Store the tasks into a json array in the variable `tasks`>>
@effect run
// The agent broke the tasks down now we implement each task
for task in tasks:
@state isDone = false
for i in range(MAX_ITERATIONS):
// Use the code agent to implement the task
@effect run
if isDone:
break
See full guide: Build a Custom Ralph Wiggum Loop →
Want to build an LLM enabled game? Create a game loop that prompts the model for the next move, then feeds the result back into the next turn's context.
if type == "mage":
[[ src/mage.mg ]]
elif type == "fighter":
[[ src/fighter.mg ]]
@state health = 100
@state isFree = false
for i in range(0, 100):
@effect input "What do you do?" => action
@effect run
if health <= 0: break
if isFree: break
See full guide: Build Dungeon Quest →
Automated code review pipelines. Scheduled reports. Data enrichment workflows. Slack bots. Anything that benefits from a repeatable, readable script driving an LLM.
Check out some of the other things you can do with Margarita
Your first .mgx file. Log a message, declare a state variable, write a prompt block, and run the agent — that's all it takes to get started with Margarita.
// Log a message before the agent starts
@effect log "Welcome to Margarita, let's get started!"
// Declare a state variable
@state variableA = "Hello World"
// Build the prompt
<< Why do we create ${variableA} programs? >>
// Run the agent
@effect run
Use @effect run to execute the agent at any point in your .mgx file. Run it multiple times — Margarita renders all accumulated << >> blocks into the prompt before each call.
# assistant.mgx
// 1. Add this to the context
<< You are a helpful assistant. What is the answer to life the universe and everything? >>
// 2. Run the agent
@effect run
// 3. Add more to the context
<< You need to think harder this time? >>
// 4. Run the agent again!
@effect run
Use if var == value: / else: to include or exclude sections of your prompt based on context. Use for item in list: to loop over data.
# access.mg
<< Access level: ${level} >>
if level == "admin":
<< You have full access. >>
else:
<< Read-only mode. >>
# tasks.mg
<< ## My Tasks >>
for task in tasks:
<< - ${task} >>
React-like composability with includes. Write a .mg fragment once and drop it into any script or template.
# components/greeting.mg
<< Hello, ${user}! >>
# report.mg
[[ components/greeting.mg user="Batman" ]]
Values stored by the agent, @effect func, or @effect tools persist for the lifetime of the run — any prompt block can read from state at any point.
# stateful.mgx
@state count = 5
@state user = "Batman"
<<
The agent can get/set state variables using markdown.
Update the count variable to 10 and print out the user variable.
>>
@effect run
Use @effect input to pause execution and prompt the user for a value. The response is stored in state and available to the rest of the script.
# build-assistant.mgx
// Pause and ask the user a question
@effect input "What do you want to build?:" => userInput
// Use the captured input in context
<<
You are a helpful build assistant.
Help the user build: ${userInput}
>>
@effect run
Use @memory var to declare a persistent variable that survives across runs. Values are read on startup and written back at the end — letting you build workflows that remember what happened last time.
# memory-example.mgx
// Declare a memory variable — loaded from persistent storage
@memory var valueA
<<
If valueA is not set, Set `valueA` to "This is a test of memory."
Otherwise write out it's set!
>>
@effect run
The agent has built-in tools — read_file, write_file, search_files, and ask_user. Just tell it what to read or write in your prompt and it handles the rest.
# file-example.mgx
// The agent reads and writes files on its own — no boilerplate needed
<<
Read the file at ./data/notes.txt
Summarize the key points and write the result to ./output/summary.md
>>
@effect run