Skip to content

What Is the program.md Pattern for Programming AI Agents?

The Problem

I’ve been building agent workflows lately and I kept running into the same issue. Every time I wanted to tweak how my AI agent behaves, I had to dive into Python code. Change a prompt? Modify a Python file. Add a new strategy? Write more Python. Adjust the agent’s decision-making logic? You guessed it—more Python.

This gets messy fast. Your codebase becomes a mix of actual logic and scattered prompt strings. Version control gets confusing. Non-technical team members can’t help. And honestly, it just feels wrong to write natural language instructions inside Python string literals.

I think there’s a better way. It’s called the program.md pattern.

What Is the program.md Pattern?

The program.md pattern is a paradigm where you define your AI agent’s behavior in Markdown files instead of traditional code. These Markdown files become the “program” that your agent interprets and executes.

Here’s the key insight from the community: “The core idea is that you’re not touching any of the Python files like you normally would as a researcher. Instead, you are programming the program.md Markdown files.”

This approach is quietly becoming a real paradigm shift in how we build autonomous agents.

How It Works

The structure is straightforward. You create a program.md file that contains your agent’s instructions, strategies, and behavioral rules. Your Python (or JavaScript) code then reads this file and uses it to guide the agent’s actions.

Let me show you what this looks like:

program.md execution flow
| (Markdown) | - Instructions
+-------------------+ - Strategies
| - Decision rules
v
+-------------------+
| Agent Runtime | <- Reads and interprets
| (Python/JS) | program.md
+-------------------+
|
v
+-------------------+
| Execution | <- Agent takes action
| Loop | based on instructions
+-------------------+

The Eval Loop Pattern

The execution flow follows a simple pattern:

eval loop pseudocode
1. Read program.md
2. Parse instructions
3. Execute current step
4. Evaluate result
5. Update state

As one Reddit commenter noted: “The eval loop itself isn’t new, but the program.md pattern is what’s actually interesting here.”

Benefits of This Approach

I see several clear advantages:

AspectTraditional Codeprogram.md Pattern
Who can modifyDevelopers onlyAnyone who can write
Version controlCode diffsClear intent changes
Iteration speedSlow (code, test, debug)Fast (edit markdown, run)
Prompt visibilityBuried in stringsFront and center
Team collaborationRequires technical skillsWriters can contribute

For Researchers

You focus on the behavior, not the implementation. Want to test a new strategy? Edit the Markdown. No need to touch Python files or worry about breaking existing code.

For Teams

Non-technical team members can now contribute to agent behavior. Product managers can tweak prompts. Domain experts can add knowledge. The barrier to contribution drops significantly.

For Auditing

Every decision your agent makes traces back to documented instructions. You can see exactly what the agent was told to do and why. This makes debugging and compliance much easier.

Basic Implementation

Let me show you a simple implementation:

agent.py
from pathlib import Path
from typing import Optional
class ProgramMDAgent:
def __init__(self, program_path: str = "program.md"):
self.program_path = program_path
self.instructions = self._load_program()
self.state = {}
def _load_program(self) -> str:
"""Load instructions from program.md file."""
path = Path(self.program_path)
if not path.exists():
raise FileNotFoundError(f"Program file not found: {self.program_path}")
return path.read_text()
def execute(self, context: dict) -> Optional[str]:
"""Execute based on loaded instructions."""
# Agent interprets and acts on instructions
# This is where the magic happens
pass

The program.md file itself might look like this:

program.md
# Agent Instructions
## Goal
Research the given topic thoroughly and produce a summary.
## Strategy
1. Search for relevant information
2. Read top 5 sources
3. Extract key points
4. Synthesize findings
## Rules
- Always cite sources
- Keep summaries under 500 words
- Flag uncertain information

Advanced Implementation with Sections

For more complex agents, you can structure your program.md with dedicated sections:

advanced_agent.py
from pathlib import Path
from dataclasses import dataclass
from typing import Dict, List, Optional
import re
@dataclass
class ProgramSection:
title: str
content: str
class AdvancedProgramMDAgent:
def __init__(self, program_path: str = "program.md"):
self.program_path = program_path
self.sections: Dict[str, ProgramSection] = {}
self._parse_program()
def _parse_program(self) -> None:
"""Parse program.md into sections."""
content = Path(self.program_path).read_text()
# Split by ## headers
pattern = r'##\s+(.+?)\n(.+?)(?=##|\Z)'
matches = re.findall(pattern, content, re.DOTALL)
for title, body in matches:
self.sections[title.lower()] = ProgramSection(
title=title.strip(),
content=body.strip()
)
def get_section(self, name: str) -> Optional[str]:
"""Get a specific section's content."""
section = self.sections.get(name.lower())
return section.content if section else None
def get_strategy(self) -> str:
"""Get the strategy section."""
return self.get_section("strategy") or "No strategy defined."

program.md vs Traditional Code

Here’s a direct comparison:

traditional_approach.py
# Traditional: Prompts buried in code
def analyze_topic(topic: str) -> str:
prompt = """
You are a research assistant.
Your goal is to analyze the given topic.
Strategy:
1. Search for sources
2. Read and extract key points
3. Write a summary
Rules:
- Be accurate
- Cite sources
"""
return llm.generate(prompt, topic)
program_md_approach.py
# program.md: Instructions in a separate file
def analyze_topic(topic: str, program_path: str) -> str:
instructions = Path(program_path).read_text()
return llm.generate(instructions, topic)

The difference is clear. With program.md, your instructions live separately from your code. You can edit them without touching Python. You can version them independently. You can let non-developers contribute.

Common Mistakes

When adopting this pattern, I’ve seen people make these mistakes:

  1. Putting everything in one massive program.md - Break it into multiple files when it gets too long. Use includes or imports.

  2. Not version controlling the markdown files - Treat them like code. They need Git history too.

  3. Making instructions too vague - Natural language doesn’t mean imprecise. Be specific about what the agent should do.

  4. Forgetting to validate the markdown - Parse and validate your instructions. Catch errors early.

  5. Mixing logic and instructions - Keep behavior in program.md, keep control flow in your Python/JS code.

  6. No feedback loop - Your agent should learn from its mistakes. Include reflection steps in your instructions.

When to Use program.md vs Code

I recommend program.md when:

  • You iterate frequently on agent behavior
  • Non-technical team members need to contribute
  • You want clear auditability of agent decisions
  • Your prompts are complex and benefit from structure

Stick with traditional code when:

  • Your agent logic is simple and stable
  • You’re building a quick prototype
  • You need maximum performance (no file I/O overhead)
  • Your team is all developers

Summary

The program.md pattern shifts how we think about programming AI agents. Instead of burying instructions in code, we elevate them to first-class citizens in Markdown files. This makes agent behavior more accessible, more maintainable, and more collaborative.

The eval loop isn’t new, but the idea of “programming in natural language docs” is quietly becoming the real paradigm shift. If you’re building autonomous agents, I think this approach is worth serious consideration.

Start simple. Create a program.md file. Define your agent’s goal, strategy, and rules. Let your Python code read and execute. Iterate from there.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments