Writing agents should be as easy as writing markdown.

Margarita turns Markdown scripts into full agentic workflows. Declare variables, call your LLM, and pass results between steps — all in repeatable scripts you can read and understand at a glance.

review.mgx
margarita run review.mgx

Why Margarita

01

Use any model, on any backend

Run the same script using Ollama, Copilot (adding more). Your script stays exactly the same.

margarita use ollama
02

Control your context, keep costs low

Most AI code harnesses hide the context from you. Margarita gives you complete control. Add only the tools you need. Run Python functions locally and update the context instead of burning tokens on tool calls.

@effect context clear
@effect func summarize("A really long text input") => summary
03

Compose prompts from reusable .mg files

Write a reusable prompt component and reuse it in your other scripts. Need to change it across your org? Just update it in one spot.

[[ snippets/role.mg is_admin=True permissions=["view"] ]]

What you can do

.mgx — agentic scripts

AI agents are now as easy as writing Markdown. Margarita lets you programmatically control the context, tools, and state sent to any model via .mgx files.

Hello World

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.

---
description: Hello World!
---

// 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

Running the Agent

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
---
description: A simple Margarita agent that answers a question.
---

// 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

Conditionals & Loops

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
---
parameter: level (string): Access level of the user, e.g. "admin" or "user".
---
<< Access level: ${level} >>
if level == "admin":
  << You have full access. >>
else:
  << Read-only mode. >>

# tasks.mg
---
description: A template that demonstrates looping over a list of tasks.
---
<< ## My Tasks >>
for task in tasks:
  << - ${task} >>

Includes

React-like composability with includes. Write a .mg fragment once and drop it into any script or template.

# components/greeting.mg
---
description: A simple greeting component that can be included in other templates.
parameters: user (string): The name of the person to greet.
---
<< Hello, ${user}! >>

# report.mg
---
description: A report template that includes a greeting component.
---
[[ components/greeting.mg user="Batman" ]]

State

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
---
description: Show how the agent state works.
---
@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

User Input

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
---
description: Prompt the user, then run the agent with their input.
---

// 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

Memory

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
---
description: Test Memory
---

// 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

Files

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
---
description: Read notes and write a summary
---

// The agent reads and writes files on its own — no boilerplate needed
<<
Read the file at ./data/notes.txt

Summarise the key points and write the result to ./output/summary.md
>>

@effect run