λ - a minimal coding agent in Lisp (build log)
Lisp played a central role in early AI research, including the AI boom of the 1980s. I’ve been reading about Lisp and lambda calculus.
Lambda calculus is fascinating, and I’m still trying to understand it. With three syntactic forms, lambda calculus is powerful enough to express any computable function. I’m reading Eitan Lees’s introduction to the lambda calculus.
I use pi as my coding agent. Pi is a minimal agent with four tools: Read, Write, Edit, and Bash. I can write my own tools using these 4 (I wrote myself a web search tool using just these 4 tools) or install tools from other people as extensions. I find this combination of minimalism and extensibility elegant.
I’m trying to use Lisp to write a minimal agent harness by hand and give it one tool: eval. In Lisp, eval lets you pass code to the interpreter; it executes the code and returns the result.
Many Lisp dialects are homoiconic: code and data share the same representation. That makes it easier to treat code as data and evaluate it. McCarthy defined eval as both a formal definition of Lisp and an interpreter. Steve Russell later implemented it on the IBM 704. Developers familiar with JavaScript may recognize the idea. JavaScript also has an eval function, but it does not share Lisp’s homoiconic representation. Developers are advised to avoid passing untrusted input to eval because it can execute arbitrary code. The same applies to Lisp’s eval. We should not run untrusted code with it.
Following pi’s example, what if we go more minimal? What if eval is the only tool an agent has? Can it build tools for itself and become useful?
I’m not using AI agents to write code for this project until λ itself can generate code.
Logs
2026-08-29 13:33
Because eval can execute arbitrary code and the agent can send any code, I didn’t want to run untrusted code directly on my machine. So, had to set up sandboxing with Docker containers. Also, had to connect Emacs to Lisp running in Docker.
Emacs now works.
Next goal is to write a function that calls an LLM.
Repo is live at Lambda