Hey, everyone. This talk is on this tradition,
intelligent agents in Emacs
using my Leonardo software individuals,
which I've mistyped as I just wrote here, I see.
Thank you to Sacha and everyone
at EmacsConf and Emacs, I guess.
Sorry that I was running late.
I'm screwlisp.small-web.org.
I run those one or two weekly shows for a long time,
the Lispy Gopher Climate.
I'm active on the Mastodon at @screwlisp@gamerplus.org.
I'm screwtape on lambda.moo.mud.org.
And I ported, over the last kind of year,
years, to some extent, I ported Eric Sandewall's system
for developing intelligent software agents,
which he finished working on in 2014.
I got it working again around 2025.
First, we're going to take a long arc.
We're going to motivate... This is the idea.
You can see I'm using Org Mode,
which I hope provides a good example
for all the Org-Mode-oriented talks this conference.
But you can also see
that I'm using Eduardo Ochs's eev minor mode with Org.
But we can see a little bit of the difference
between these two, and that will kind of evolve into
my style with the agent communication in Emacs.
So you can see I used eev anchors as my Emacs headings.
In eev, you just evaluate Elisp expressions
as links to places.
An anchor will link you somewhere else in the document.
So my table of contents links to my talk, I guess.
Anchors come in two halves,
so that's why I built that unique table of contents
experience there. What else am I going to say?
So first, let's just do some totally normal computing
because intelligence is going to be difficult to describe.
Let's just try and compute normally in Emacs in Org Mode
and then segue more so into eev,
and then maybe I would like if an agent was intelligent,
I would think that an intelligent agent
would do something like what I'm doing.
It should be recognizably similar to what I do myself.
I don't think the word intelligence is relevant
if it's not related to something I'm not familiar with.
Using Emacs as a human, reading headings from my article,
using Common Lisp. Right, my friend jeremy_list
wrote actually a big project,
but part of it was base64 encoding,
and I just yoinked his C code for base64 encoding, I think.
This is just clearly some C-based 64 encoding.
If you go to my blog, his project is actually a C++ project
and you can see me doing this with C++ rather than C.
But basically, you can go to my blog articles
if you want more detail to read something instead.
And then here's some embeddable Common Lisp,
Jack Daniel's ECL ANSI Common Lisp compiler I guess.
This is just what it looks like.
You can see I'm using Org Mode trickily,
using noweb to put the lines of the C source block
in this one. We're tangling it to this file
rather than evaluating it.
So, you know, literate programming, tangle and weave.
We're just using Org Mode
like the other Org Mode people
are all showing us this conference, I guess.
Then we have to compile it.
It's always hard to remember these invocations for me.
Results file. The file is my .fas file,
because the way ECL's C and C++ integration works
is that it just has to be seen by compile-file in Lisp.
I cached this earlier.
Oh, I should actually start Lisp, actually, shouldn't I?
How are we going to do this?
(setq inferior-lisp-program "ecl"). We could M-x slime.
Because... we better actually load this.
I did a dry run before.
I think we can just load this, because I already did it.
But I cached it. Let's nuke the cache.
Okay, I'm going to say that that probably worked.
Now, as you saw, that base64 encoding
was just, I guess, number to character code
to other character code. So I wrote this higher-level Lisp one,
but that's not really the point.
Obviously, Emacs also has Base64 encoding.
It's just a point that we might have
C++ and C external programs
that we'd like to be integrating
into our Emacs agents capabilities.
Here we can see a normal named Org Mode source block.
that calls that function, then an Org Mode source block
that calls Emacs's base64-decode-string as a way of
validating it, I guess.
We go to Org, so we can see...
I have a named call to that function calling the Lisp function
Org is just kind of like this.
It's cached but I don't seem to have run it before.
Then I do the Emacs decode.
So if we just run this using C-c C-c,
and we can kind of see
what Org Mode is like a little bit here.
All right, yes, so as we can see,
oh hang on, let's run this as well actually.
So the C embeddable Common Lisp
base64 encoding gets us this.
And then Emacs is decoding and gets us back,
kind of validates it. I think I'm missing some things.
I don't pad characters out to the correct byte lengths,
that kind of thing, but it's fine.
And then I kind of contrast that to,
I really like what my friend mdhughes.tech,
game dev of the ages, calls REPL-driven development,
which he says is kind of the opposite of literate coding.
I think eev, at least for me,
is kind of like REPL-driven development.
So in eev, if you just press F8, the thing happens.
And if it's a red star line,
the thing is an Emacs Lisp thing,
and otherwise it goes to the eepitch target.
So if I do this, great, now I'm pitching to that slime
REPL ECL I made. And then I pressed F8. Press F8 again.
The string got coerced to a list.
F8. Now it's car codified.
I quite like this, because this looks like something I can do
and understand doing and reason about doing.
Then I form a command to send from Lisp to Emacs.
Then I do it and I recover the string from the beginning.
I guess I had one of these here. Oh, by the way, look at
What Org Mode did with an eev source block.
And then when I close the source block
using C-c ',
it brings me back to the Org doc,
which was a cool synergy between the eev minor mode
and eev source blocks in Org Mode that I noticed.
And so I kind of want my agents to be like this eev usage.
Clearly, Org is super powerful,
but I don't even like writing calls like this,
where you write the function that will happen last first,
so you're kind of writing right to left, first to last.
Whereas in REPL-driven development,
I guess I'm writing top to bottom,
and eev, I guess, executable logs
are logs that are like that.
So I kind of like eev's view for reasoning
more than Org's Tangle.
Obviously, Tangle is trying to do tricky things,
but maybe they have different specializations,
and eev's one is more close
to my own version of intelligence, maybe.
Software individuals using eev in Emacs like a human.
Yeah, you can always visit my blog post for more detail.
Right, I made a CLOS object
in Common Lisp to wrap doing this.
It's not really the topic.
It's in the appendix somewhere if you need it.
So I've just executed that.
You can look at the appendix in your own time.
Jumping over to actually starting
our hypothetical intelligent agent.
I guess we're doing eev here.
So if we open this, press F8 a bunch of times.
Oh, and if you were cloning it yourself,
I guess that's what you would do. setq eepitch-buffer-name.
Oh yeah, if you went to an eepitch shell and then came back.
You would have had to do that, but I didn't.
I didn't, so I didn't need to.
Sandewall's style is to use relative paths
to tell which agent is acting inside a software individual.
Remembering a software individual
is potentially a bunch of agents.
And we load... So one individual,
all the agents in each individual share a kernel.
So only one agent in one software individual
is active at any given time, but the agents are separate.
They just all have to share the kernel resource,
which is the Remus agent. Oh, I got rid of this.
And start the CLE is the thing.
Oh, I did need to have an EmacsConf knowledge base.
Well, let's just keep eepitching for a little bit.
So I think I made... I'm going to call it emacsconf-kb.
Right, that looks likely. And I think that the agent...
I can check this. I could have checked that.
I could have done something like (get emacsconf-kb contents).
Yeah, and you can see
there's a location inside it which is agent1,
which I assume is an entity file
that I was working with before.
And then what were we going to do?
Oh yeah, back to the embeddable Common Lisp image.
So if I just press our button back to there...
And so my idea is that for an Emacs agent,
basically, I'd like to have an Emacs Lisp list.
And just when stuff gets into that list,
the agent which is always running, but running slowly,
will incrementally just do the stuff it finds in that list.
Populating that list probably gets into stuff
like your Beliefs, Desires, Intents framework
and those kind of well-known and well-studied algorithms.
That's not the point here.
I just want to have a list in Emacs that my ECL...
I'm just going to run a loop in ECL,
and the ECL is going to keep sending
anything it finds in that Emacs Lisp list
to the software agent. The agent is also in Emacs,
so it would be able to populate its own list itself
if it had an idea of evaluating desires and chances to improve
whatever it wants to improve
and chances to avoid whatever it wants to avoid.
We talked a little bit too much. Let's just start this.
Sorry that I'm manually setting up my screen.
Then let's put CLisp over here.
Right, we could work with this, right?
This loop isn't very important.
It's just a Common Lisp loop. I copy my friend jmbr's style
of using Lisp machine-style keyword arguments
instead of symbols like cl-loop,
the compatibility thing in Emacs Lisp does.
I'd never initialized that. Well, let's do that.
Okay, now we have the list.
And just every 30, let's turn it down to every 20 seconds.
Hypothetically, it's going to put
whatever it finds in there, into there.
And so, I think, yeah, and now... Great.
So here I'm just going to fill it with stuff.
And this is quite interesting, I think.
It just shows I can put a whole bunch of stuff into that list.
Ideally, the agent would populate it itself
with a BDI algorithm or something.
But if we just put some stuff in there,
we'll see that it will all get sent
basically using Eduardo's eepitch internal machinery, at least.
And hence, it meets my requirement
that it works exactly like I work.
And then in eev, I just have to press M-e.
Oh, it works via Emacs server, and I didn't start that,
so if we server-start, hopefully...
And then, ideally, things will just begin happening
in this slime-repl C/Lisp agent.
Oh, if this was still running.
Okay, well we got at least one,
but hypothetically lots of these will happen.
So, show agent, I guess,
happened over here. I put a whole bunch of "sleep-for"s in,
because I thought that going slowly
would make it seem more human.
Like I saw in Eduardo's talk last year
which is where I learned about eev.
The system is a little fragile.
Hypothetically, we have a whole bunch of agents.
I guess every time it gets sent,
it checks that we're in the right agent.
And it's not actually just sending a string,
it's sending a sequence of string actions over there.
And so we see Emacs Lisp hypothetically put,
I guess it put this "foo bar baz!" into an entity, message-1,
which should be of type message, I guess, conceivably.
I forget if I set that up earlier.
It's in the appendix somewhere.
And then it just called, it did a sequence of actions
which was really just one action of showing that.
And then I called b64-encode on message1,
which I believe will have set message-1 encoded.
Can I check that manually while it's happening?
Disaster. Well that's what it should have been.
Well, I did mention it was a little bit fragile.
What if we put... Can we kind of rescue this?
I don't want to try redoing this. It's slightly fragile.
What it would do, we can see the actions are kind of getting there,
but somehow my message didn't end up getting encoded
by that sequence of actions.
So this decode will have also made the decoded one be null.
Let's just do it manually. Should have worked.
b64-encode, which calls out to Emacs
to get everything actually done.
Oh, I got interrupted by the agent.
Well, if I do it manually, it worked.
Hypothetically, the queue thing should have worked. Great.
Well, you can see it's kind of working.
Could be more robust.
The reason is that I think what I did is a bit fragile,
but the intent is that FIPA,
Foundation for Intelligent Physical Agents's
SL standard has tools for reliability
through repetition and checking outcomes and that kind of thing.
So I would use those. I'm not putting too much work
into being ultra-reliable right now, but it kind of worked.
We saw, I guess, at least Embeddable Common Lisp
believed it used emacsclient externally, asynchronously,
to send these to Emacs within Emacs.
I put a whole bunch of sleeps into its thing
to make it look slow and human-like, kind of happened
because Emacs' model is that it's kind of single-threaded.
Can I just... I bet if we run this again
It'll at least look like it's succeeding
because I fixed the base64 encoding
and so forth in the background. I wonder if it will.
In the meantime, let's wrap up this talk to some extent.
Then I'm just kind of saying what I'm expecting to happen.
I took out next action.
Originally, I was keeping the list inside of the agent.
Then I decided to keep the list inside Emacs
because I have kind of first class Emacs is my IDE,
so I have better access to what's going on in my IDE.
Then I wanted to talk about intelligence a little bit
in whatever my remaining time is.
I just have these great bullet points
of nosrednA yduJ and Eric Sandewall.
So nosrednA yduJ, when she was on the show quite a long time ago,
she... I keep describing things as expert systems
and she wanted to know what I meant
when I said expert systems,
and I gave her a Lisp software example
and she said she personally wrote
that software in the 80s that I was referring to
and she wanted to know how it was an expert system.
What I mean when I say expert system
is a system that works kind of like I do and eev's eepitch does.
It's where we can really reason
in a very human-relatable way
about what the inputs to the program is.
And also a program should be exposed to other programs
in terms of like a well-structured transfer of knowledge as inputs,
and it should have a well-structured
transfer of knowledge kind of outputs.
I don't know why this b64-encode message wasn't working.
Then we kind of faked it into working.
It's going to be embarrassing for me
if anybody watches this. But yeah, so yduJ's thing...
And then I was going to also build
that into Eric Sandewall's one.
So this is my vision of expert systems
as kind of maybe this is an important
general style loosely associated with Lisp.
Same as the Lisp editor Emacs.
So Eric Sandewall's description of intelligence
was that his grandchildren were intelligent.
So if we had software agents that were intelligent,
this would be true if and maybe only if they were similar
to his grandchildren
who were a good reference for intelligence.
And grandchildren live for a really long time.
They kind of learn gradually.
They don't run on GPUs for a few minutes
and then get thrown out forever, something like that.
And so this is the kind of vision of, I guess,
the Leonardo system software individual stuff.
You can see we kind of faked it into...
at least the show get message one decoded bits were working.
I'm not sure what was happening
with the Elisp ones that worked interactively,
but then they didn't work in my loopy thing.
Oh yeah, and then so I mentioned
thank you to Sacha at the start of this talk.
And so Eric Sandewall's emphasis
that you'd really like intelligent software agents,
Leonardo system agents, to be like your grandchildren.
And I was talking to somebody, maybe to Ramin Honary
who's doing the schemacs talk this year
about Sacha's writing.
A lot of Sacha's writing is about
her experiences of life and technology,
and especially raising A*
and her observations of her progeny A*'s
experiences of life and technology,
I would say as well as being
the Emacs News and Emacs conf doer that she is.
Yeah, and so I think a lot of what Sacha is seen doing
and concerned with are specifically what Eric Sandewall
identifies as the study of intelligence as such,
as should apply to computing as well. That was my thought
on Sacha, Eric Sandewall, intelligence, and yduJ.
I have this note from pizzapal...
I didn't realize that Microsoft had announced
that 2025 was going to be the year of the software agent.
I only found this out in hindsight
when I saw people crowing on the Mastodon
about how Microsoft had basically declared
that their Year of the Agent marketing campaign
was a failure
where basically people didn't like the same old web services
but now while you're accessing,
while you're formally kind of accessing a web service,
the kind of web service that used to be called
serverless web services, this kind of thing,
but you're just being gibbered at by Microsoft Copilot
while you're trying to use regular services.
And people turned out not to like this.
I think that, as we can see in this agent,
the agent really needs to be running on its own clock
and independently of you.
Like if you imagine your body is getting
novel, slightly speculative instructions from your brain
constantly throughout your entire waking day, quite slowly,
this is what an agent should be like.
And it should be... Sandewall wrote about this.
Basically, computer programs
aren't going to want to use human natural language with each other.
There's nothing desirable about that,
so you wouldn't have two hypothetical Microsoft agents,
which are just regular web services with
a GPT model gibbering at you
while you're trying to use the web service.
I think we can see...
Microsoft did the wrong thing with the word agent,
allowing that agent is an overloaded term like static.
I'm going to stop this. I'm not going to try and fix this.
Sorry, everybody. Thank you. Talk to you on the Mastodon.
Hopefully, see you on the show.
See you at your conference talks.
My blog has writing and examples of this with multi-agents,
more C and C++ stuff, Lisp things.
You're welcome to come on my show to be interviewed,
however formally we do that. See everybody next time.