

Join the discussion
Write your take first — we'll ask for email only when you're ready to publish.
- Hacker News
- It might be kind of cool to implement just a basic loop and let the agent itself to implement memory and all other aspects on the fly, fully embracing self-modifying code.
But it's also extremely brittle and unstable. It's really the opposite of what people look in agents.
by killerstorm - I always had this idea after reading so much about Lisp that I was designed for AI, but kinda forgot about it with all the craziness of the last years. When I read on the article the eval and the implications of agents self generating their code, it just clicked. Looking forward to experiment with this! kudos to the author!
- I made an interpreted lisp and stored the AST in postgres and exposed the functions with htmx, and honestly it works pretty great.by sroerick
- I never realized that when chatting with the bot, the entirety of the session was sent each time. I guess I just figured there was some state maintained Out There, rather than simply resubmitted each time.by whartung
- > Symbolic AI lost.
Symbolic AI lost? At what, surely not chess?
A symbolic AI solution to a problem requires vastly less energy. And is deterministic; you can cover it with expected input/output pair regression test cases.
by kazinator - Technically the current best chess engine is a neurosymbolic hybrid.
But I have found that sometimes the best use of an LLM is to write code for symbolic AI.
by ijk - Nice, but this is the equivalent of always running with `--dangerously-skip-permissions` with all the security implications of that.by scarredwaits
- Pi does this by default. Since the frontier lab agents are vibe coded you really should sandbox any agent you run period.
- Which realistically, is the only way to be productive with agents. If you aren't running them inside of something that limits their scope/impact/potential damage, you're already doing it wrong.
Most of those "permission"-systems are built on the idea that an LLM can decide what to ask for approval to run or not anyways, which obviously don't work out great in practice. Might as well give them blanket permission to do whatever, then put them in an isolated environment.
- This is beautiful, I can't deny that. But the claim that Claude Code is a fixed set of tools is quite wrong. Claude Code regularly generates new code to carry out tasks, and you can choose to promote those tasks to skills, workflows, etc.by skapadia
- 9 lines of python:
import json,sys,uuid;from subprocess import getoutput as sh;from urllib.request import Request as R,urlopen b={"model":"gpt-5.6","prompt_cache_key":uuid.uuid4().hex,"input":[],"tools":[{"type":"custom","name":"shell"}]} while prompt:=input("> "): b["input"]+=[{"role":"user","content":prompt}] while True: o=(r:=json.load(urlopen(R(sys.argv[1],json.dumps(b).encode(),{"Content-Type":"application/json"}))))["output"] b["input"]+=o;calls=[i for i in o if i["type"]=="custom_tool_call"];used=r["usage"]["total_tokens"]/10500 if not calls: print(o[-1]["content"][0]["text"],f'\n[{used:06.3f}%]'); break b["input"]+=[{"type":"custom_tool_call_output","call_id":i["call_id"],"output":sh(i["input"])} for i in calls]by tosh - Every Lisp program can be written in one line.by ySPARK
- nb:
- stdlib only, 0 external dependencies
- works with openai compatible api (including local models)
- shows context usage in % when turn goes back to user
- cache friendly (keeps stable prefix and provides uuid v4 as session cache key)
- uses 'shell' as open ended tool
'shell' as tool name is sufficient context for gpt 5.6 sol
by tosh - This is a thing of beauty, no matter what the general feeling in the comments seems to be against LISP. And yeah, you can do it in JS/TS/Python/etc., but somehow it doesn’t feel as elegant.by rcarmo
- So, writing an agent in Lisp is interesting but not particularly novel. If there’s a big idea here it’s giving Lisp’s eval function to the AI as a tool. Yes, AIs write Python and Bash all day long already, but those scripts are run out of process. In this case, the AI can modify the process running the harness, extending it directly and potentially changing it (evolving it). That’s powerful. And obviously quite dangerous. Definitely only for a sandbox. But I wonder how far that can go…by drob518
- Now this is AI going full circle, back to their roots. Yeah, I want to see that system working.by Shorel
- There is no good reason for running this in-process. The maximally inefficient Fibonacci function in the article is a good demonstration why: Call it with a slightly larger number, and your agent slows to a crawl, with no way to enforce a timeout. Call it with a slightly larger number yet, and you might bring your agent down entirely, with no way to recover.
There is a case to be made for a dynamically evolving "tool server", but it should be a separate process. That would be more flexible for other use cases too. For example, multiple independent agent processes could talk to one shared tool server. Like a blackboard system, more classic AI!
And if you really do want to evolve the agent itself: As the article observes, its entire state can be serialized. Nothing is gained from hanging on to one particular agent process. Serialize its state, ask the tool server to kill it, rewrite its code, then start the new version and replay the state.
by derdi - Maybe this is a reductive comment, but how does this differ from just letting your agent bash tool a `python -c` command (or anything of that class)? I'm not really getting where this is a "wow" moment?
It is always nice to appreciate how much power you get out of (Model + the absolute bare minimum of control flow). There is just so much baked into the models now that given an inch they will take a mile.
by hankbond - this is as if python was written in python, and you added support for llm in python so that it can write it's own codeby slim
- You're not wrong. I did a similar agent in lisp back with Sonnet 3.5 and had a wow moment, but the wow was mostly for seeing an agent working effectively at all at that point in time.
The part that killed it for me was losing everything if the lisp crashed (sonnet 3.5 was prone to doing that) and solving persistence had too many edge cases and confused the model.
Later realized that writing the agent as 20 lines of bash was equivalently powerful to the lisp agent, but made persistence trivial from the easy file system interop.
by wild_egg - The blog is about writing an agent when you dont already have an agent, but only a plain LLM. It stitches the minimal pieces together. Agents dont need lots of supporting infra, so it is good to keep the code concise. Not a wow moment for sure, though some people think that agents and harnesses are complicated.by pama
- By my eye it's not that different, it's riffing in it from a Lisp perspective.
It's pretty amazing to write your own agent BTW. I've got a zero-dependency all-in-one-file agent harness I wrote myself. I use it all the time now because I can get it from anywhere and I can know EXACTLY what it'll do (as much as you can with any model), what it's been told vs not. Using it as a harness for models I'm hosting myself makes me feel like some kind of LLM homesteader: it's a set of tools I'll always have that will only change as much as I want it to change.
by lelandbatey - If you give your agent a `bash` or `python -c` tool, it starts a separate process that produces some output and then exits. After that, only the output and the exit code are available.
In contrast, `eval` runs the code in the same execution context as the agent loop. When `eval` finishes, that execution context still exists. For example, any functions defined during an `eval` call remain available for later use.
by kmeaw - I like Lisp, I’ve used Common Lisp with a passion, but this doesn’t seem like a valid argument for Lisp.
Homoiconicity, as I understand, is that the code is structured data that is easy to programmatically modify, hence allowing Lisp macros. While some might disagree, I see Rust macros as the closest thing that demonstrates homoiconicity in mainstream Algol-based languages, as Rust macros modify the loosely structured token stream to produce new Rust code.
Eval, on the other hand, that’s more of a capability that comes from Lisp’s runtime, which used to be unique when Lisp was thriving, but not anymore — JS, Python, Ruby, all of the runtime-based languages have an eval function. The fact that they are not used as much is more of a security issue, not a capability issue, and I am not sure how having eval can be argued as Lisp being the language of agents.
by goranmoomin - > Homoiconicity, as I understand, is that the code is structured data that is easy to programmatically modify
I think a more accurate description is that lisp code is just cons cells and cons cells is both how we write the code and how the runtime itself implements lists. So there’s basically no distinction between a lisp list and the text representation of the source. Rust and its macros is a different situation because the text representation of the code and the syntax tree have completely different shapes
- It's not just eval. It's LISP macros what makes it an interesting powerful language for agents.by Shorel
- Does eval in these other languages evaluate ASTs or strings? It makes a difference.by mvc
- > Eval, on the other hand, that’s more of a capability that comes from Lisp’s runtime, which used to be unique when Lisp was thriving, but not anymore — JS, Python, Ruby, all of the runtime-based languages have an eval function.
And it's good we have those for troubleshooting but those eval still offer nowhere near the power of a Lisp REPL.
> and I am not sure how having eval can be argued as Lisp being the language of agents
I've seen several Lisp programmers saying that it's really the REPL (and the 'E' in REPL is for "Eval") that is the godsend when working with LLMs.
With LLMs we've seen terminals/ssh/tmux and CLI tools calling making a huge comeback (not that they ever went very far).
Now I wouldn't be surprised if we were soon to see a Lisp AI harness also using extensively the REPL becoming succesful.
It's too early to tell it's not a powerful combo (LLMs + Lisp REPL).
- A Lisp program that writes a Lisp program really just needs to produce a list of (nested lists) of tokens. A JavaScript program that writes a javascript program needs to generate a string that is syntactically valid JavaScript code. That is a much bigger task than just constructing a (nested) list.
Because Lisp syntax is so much simpler than that of JavaScript etc. it is much easier to avoid errors when generating code. In JavaScript you can use JSON to generate data, but JSON can not carry functions around.
I think this idea makes a lot sense. Instead of making the LLM generate JSON or XML, why not make it generate Lisp, which can carry both programs and data?
by galaxyLogic - > I see Rust macros as the closest thing that demonstrates homoiconicity in mainstream Algol-based languages
I don't know if you consider Elixir mainstream, but IMO their macro system is much closer to lisp's ideal.
Elixir is basically Lisp, but with better syntax, a modern ecosystem, and running on the Beam. Unlike languages like Rust, Elixir's conditionals and function definitions are just calls in the AST, even though the syntax looks mainstream and not like paren soup.
by miki123211