Every agent template on the internet has the same problem: it's locked to one runtime.
Write basic_agent.py and it runs in Python. Only Python. Need it in a browser? Rewrite it. Need it inside a sim? Rewrite it. Need it on embedded hardware? Rewrite it again. The agent's logic is universal, but its implementation is caged inside one language's ecosystem.
We fixed this. The fix is embarrassingly simple: same name, same interface, different runtime.
The kody-w/AI-Agent-Templates repository contains 14 Python agent templates. They're excellent. basic_agent.py, calendar_agent.py, code_review_agent.py — each one a standalone, useful tool.
But they require Python. They require pip. They require an OS that can run CPython. They can't run inside a browser-based Mars colony sim. They can't be loaded from a JSON cartridge. They can't be executed by a LisPy VM running on a microcontroller.
The agent's interface is simple: it has a name, a description, and it does a thing. The agent's implementation drags in an entire runtime ecosystem.
Here's the key insight: the file name IS the adoption strategy.
When someone who knows basic_agent.py sees basic_agent.lispy, they immediately understand what it is. No documentation needed. No explanation needed. The name carries the entire context.
This is why every .lispy file has the exact same name as its .py counterpart:
basic_agent.py → basic_agent.lispycalendar_agent.py → calendar_agent.lispycode_review_agent.py → code_review_agent.lispyNot lispy_basic_agent.lispy. Not basic_agent_lispy.lispy. Not mars_basic_agent.lispy. The exact same name, different extension. The name is a bridge. The extension is a runtime selector.
If you rename the bridge, people don't cross it. They don't know it goes to the same place.
Every agent — .py or .lispy — follows the same contract:
_agent_name — a human-readable name string_agent_desc — what the agent does, in one sentenceThat's it. Four things. Any runtime that can evaluate these four things can run any agent.
In Python:
_agent_name = "Basic Agent"
_agent_desc = "Simplest possible agent."
def run(input):
print(f"Agent ready. Input: {input}")
return f"Processed: {input}"
In LisPy:
;; basic_agent.lispy — Simplest agent. OG: basic_agent.py
(begin
(define _agent_name "Basic Agent")
(define _agent_desc "Simplest possible agent.")
(define input _input)
(log (concat "Agent ready. Input: " input))
(concat "Processed: " input))
Same name. Same interface. Same result. Different runtime. The .py version runs in Python. The .lispy version runs anywhere there's a LisPy VM — browser, Node.js, Python, embedded hardware, inside a sim.
LisPy is homoiconic: the program IS the data. An S-expression is simultaneously executable code and a parseable data structure. This means:
The LisPy VM itself is ~50 lines in any host language. Write those 50 lines in JavaScript and every .lispy agent runs in the browser. Write them in Python and every .lispy agent runs alongside .py agents. Write them in C and every .lispy agent runs on a microcontroller. The VM is the bridge. The agent is the program. The program runs everywhere.
You don't even have to choose. A .py file can load and execute the .lispy version:
# basic_agent.py — wrapper that runs the LisPy version
from lispy_vm import evaluate, load_program
program = load_program("basic_agent.lispy")
result = evaluate(program, env={"_input": user_input})
print(result)
The .py wrapper calls the LisPy VM. The .lispy runs natively. Same program. Same result. The Python ecosystem gets to keep its tooling. The LisPy ecosystem gets portability. Both get the same agent.
Each maps directly to a Python template from kody-w/AI-Agent-Templates:
| .lispy Agent | OG .py Source | What It Does |
|---|---|---|
basic_agent.lispy | basic_agent.py | Simplest agent — reads input, logs ready |
context_memory_agent.lispy | context_memory_agent.py | Store/recall via VM env vars |
calendar_agent.lispy | calendar_agent.py | Mars calendar: year, sol, season, supply window |
motivational_quote_skill.lispy | motivational_quote_skill.py | Random Mars wisdom from a list |
duckduckgo_search_agent.lispy | duckduckgo_search_agent.py | Searches the prompt library |
manage_memory_agent.lispy | manage_memory_agent.py | CRUD on VM memories |
fetch_random_wikipedia_article_skill.lispy | fetch_random_wikipedia_article_skill.py | Fetches Mars frame data |
code_review_agent.lispy | code_review_agent.py | Reviews LisPy governor programs |
meeting_prep_agent.lispy | meeting_prep_agent.py | Colony briefing with talking points |
hacker_news_agent.lispy | hacker_news_agent.py | Satirical HN commentary on colony |
adaptive_card_agent.lispy | adaptive_card_agent.py | Structured status card output |
powerpoint_agent.lispy | powerpoint_agent.py | Text-based slide deck summary |
email_drafting_agent.lispy | email_drafting_agent.py | Colony status report email |
image_generation_agent.lispy | image_generation_agent.py | ASCII art colony visualization |
Born in LisPy. No Python original. These are agents that only make sense inside the Mars sim:
| .lispy Agent | Category | What It Does |
|---|---|---|
colony_governor_agent.lispy | Core | Adaptive resource allocation — THE governor |
colony_status_agent.lispy | Reporting | Full status report with box drawing |
doom_clock_agent.lispy | Analysis | Predicts death sol from current burn rate |
sentiment_agent.lispy | Analysis | Bull/bear sentiment from colony state |
gauntlet_agent.lispy | Competition | Monte Carlo gauntlet status and scoring |
treasury_agent.lispy | Economy | MARS token distribution calculator |
perchlorate_guard_agent.lispy | Safety | Cumulative perchlorate exposure monitor |
echo_enrichment_agent.lispy | Data | Retroactive data layer status |
The LisPy OS loads .lispy files from cartridges. Drop an agent into the filesystem, run it from the terminal:
> run basic_agent.lispy
🤖 Basic Agent activated
📥 Input: No input provided
✓ Agent ready — no further action required
Any JavaScript or Python application can load and execute agents:
// Load the agent
const program = fs.readFileSync('colony_governor_agent.lispy', 'utf8');
// Execute with colony state as environment
const result = lispyVM.evaluate(program, {
sol: 247, o2_days: 12, food_days: 8,
power_kwh: 180, crew_alive: 5, crew_total: 6,
colony_risk_index: 45, morale: 62,
solar_eff: 78, dust_tau: 1.8, modules_built: 4,
events_active: 2
});
The CLI tools can execute any .lispy file directly:
$ lispy run docs/agents/doom_clock_agent.lispy --sol 300
💀 ═══ DOOM CLOCK ═══
Sol 300 — Calculating time of death...
💀 PREDICTED DEATH: Sol 318
⏳ SOLS REMAINING: 18
☠️ CAUSE: 🌾 STARVATION — food depletion
The AI-Agent-Templates repo has users. Those users know what basic_agent.py does. When they see basic_agent.lispy, three things happen instantly:
Zero learning curve. The name does the marketing. The interface does the onboarding. The runtime does the magic.
If we'd named them lispy_basic_agent.lispy or mars_basic.lispy, users would see a different agent that requires learning from scratch. The identical name communicates: this IS the agent you already know, running in a new place.
Every .lispy agent uses the same language. The complete language reference is a single file: LISPY.md — The Rosetta Stone.
Drop that file into any repo. Any AI that reads it immediately understands the full language. No docs site needed. No tutorial needed. One file IS the docs. Every feature, every function, every pattern — demonstrated in executable examples.
The Rosetta Stone is itself homoiconic: it's a document that teaches a language where the code IS the data. The document IS the specification. Same principle, all the way down.
Same name. Same interface. Different runtime.
The .py runs in Python. The .lispy runs everywhere.
The agent doesn't care where it lives. It just runs.
22 agents. 14 mapped 1:1 from Python originals. 8 born Mars-native. All running on the same VM. All portable across runtimes. All loadable from cartridges. The universal agent isn't a new framework — it's a naming convention and an interface contract.