Elma: the agent system I built on parental leave
.............. .......::::::..... .....::::::::::::... .....::::::----:::::... ...::::---------:::... ..... ::::------------:::.. .......... ::-----=====----:: .............. :----=======---::. ############### ### ### ..... ### .. ######### .....:::::::.... ---=========--:::. ############### ### ### ### ######### .....::::::::::... --=========---::.. ### ### ###### ###### ### ### ....:::::::::::::.. --========---::... ### ### ###### ####@@ @@@ :::.. ### ....:::::-----::::. --=======---:::.. ### ### ### ### #@@ @@@ -:::: ### ....:::::------:::: ---=====---:::.. ### ### ### ### ##@ @@@ ### .....::::-------::: ----------:::.. ############ ### ### ### ##@ @@@@@@@@@###### .....:::::------::: :--------:::.. ############ ### ### ### ### @@@@@@@@@###### ......:::::----:::: :::----::::.. ### ### ### ### @@@ ### .......:::::::::::. :::::::::... ### ### ### ### @@@ ---:: ### ......:::::::::.. ...:::::... ### ### ### ### @@@ --::: ### ......:::::::... ......... #** ### ### ### @@@ ::::. ### ......:::..... ...... *********###### ############### ### . ### @@@ ::... ### ........... ************### ############### ### .. ### ### .... ### ......... ... .. ....... .......:::....... ..... ............. .... ... ...... ......... ............ ................ > elma --status_ o 2 agents running
One of the coolest things I've made so far on my parental leave is Elma.
Elma is a tool for agent orchestration. In other words, a system that can spin up AI agents and put them to work on tasks for me.
I'm far from the first to build a system like this. There are already hundreds of them. Even so, I was always missing that last bit. And now that we have AI to help us, it's faster (and more fun) to build your own than to use something finished, or to spend the time getting to know an open source tool before you can build on top of it.
From a couple of hours to a whole lot
Elma started as a small tool that was supposed to help me with specific tasks, mostly coding tasks. The plan was a couple of hours of work. Before I knew it, a whole lot of hours had gone by and a pile of new features had shipped.
PLANNED ##................................................ 2 hours ACTUAL #####################################............. 111 hours -------------------------------------------------------------------------- 0fdc7f1 shipped grok build via cli fa169e4 shipped github-integration b2f38b8 shipped slack-integration 857d6fd shipped vercel-integration 67d044e shipped notes in a git repo 775b058 shipped design.md library 3d6bbca shipped settings (far too many) 8da6bf2 shipped home page with widgets bad59ec shipped custom composer 4200335 shipped ask: just chat > 27ec3b6 shipped live agent view elma/main 12 of 16 features
A server that never sleeps
I wanted a place where my agents could work without my MacBook having to stay on around the clock. So I started looking into the options. Then I remembered that I had an Ubuntu VPS at Hostinger that I had never got round to cancelling. It used to run a Hermes agent, but once Grok Bot came along it stopped mattering, and I simply forgot to cancel it.
Now I had a VPS. But how on earth do I get an agent to talk to a server?
Hmm...
The answer, of course, was to host the whole project on the VPS. That way everything runs locally, and I can also use what's already on the server, like CLI tools and local data. That came in handy later too, when I needed local databases.
The tool was now running, and I could reach it from my private IP at home. So far, so good.
\|/ 12:20 -O- /|\ .---------------------. +---------------------+ | .-----------------. | | [ ] :.|:...:| 01 | | | > elma | | |---------------------| | | task sent | | tasks | [ ] .:|:|:|:. 02 | | | | | --------->--------->- |---------------------| | '-----------------' | | [ ] :....||:: 03 | '---------------------' +---------------------+ /_______________________\ ______________________________________________________________________________ MacBook online VPS hostinger · ubuntu sending tasks o running 3 tasks done
Integrations, because you can
Then came the part I often end up doing: things had to be connected. GitHub, Slack, Vercel and many, many more.
Now that we have AI, we might as well do it “properly”. Not because it was needed, since the system is my own and only for me. But because it's easy, and because I sleep better at night when it's completely finished. So I built a whole library of integrations. You might as well add a load of things you'll never use.
[ GitHub ]
|
[ + many more ] | [ Slack ]
(never used) | ////
\\\ | ////
\\\ | ////
\\\ | ////
+------------+
| |
[ Hostinger ] ------------- | ELMA | o.------------- [ Vercel ]
| |
+------------+
//// | \.o
//// | \\\
//// | \\\
//// o \\\
[ Hetzner ] . [ Grok Build ]
|
|
[ DeepSeek ]
5 callsNow I had three things in place:
- A VPS where my tool runs.
- Agents: Grok Build, which runs through the CLI on my VPS, and DeepSeek Flash for ordinary chat and the AI features scattered around the system.
- GitHub, so my agents have somewhere to keep their code.
Updates in one click
My next challenge: I knew I would keep building on the system, but I couldn't be bothered to sit stuck in a terminal with an SSH connection to my VPS, using Claude, Grok or something else from there.
The solution was actually pretty simple. I installed Git on the VPS and wrote a script that watches whether my GitHub repo has new changes compared to the version running on the server. If it does, an “Update” button appears. One click, and the script pulls the changes, installs them and restarts the whole system. Done.
+------------------------+ +------------------------+ | GITHUB | git fetch | VPS | | byhartvig/elma | <--------------------o | /srv/elma | | main b09516a | same | live b09516a | | | == | | +------------------------+ +------------------------+ everything is up to date +-------------+ | UPDATE | +-------------+ last update: none yet > git pull origin main .................... [ ] > npm ci .................................. [ ] > npm run build ........................... [ ] > restart elma ............................ [ ]
After that I made a whole lot of changes, especially to the UI, because that's one of my greatest loves ❤️

What Elma can do
Just to sum up, this is what the system could now do:
- Agents that solve tasks in my repos, each on its own branch.
- Integrations with AI models, GitHub, Slack, servers and much more.
- Notes, stored in a Git repo or on the server.
- Design: a library of design.md files and instructions that the agents follow, and that can be pulled straight from my Git repos.
- Settings with far too many options.
- A home page with widgets showing the essentials, and a custom composer for sending tasks off.
- Ask, a chat interface where you can just chat instead of setting agents to work.
- Agent view, where I can follow what an agent is doing in real time.
- Boxes, a list of the servers I've connected, with a quick way to start up more, for example at Hostinger or Hetzner.
- Memory, where the agents save what they learn along the way, such as how I want things done, or something about me.
- Schedules, where I can quickly set agents to run recurring tasks, like cron jobs.
main -------o------o-oo-------o--o-----oo-------o--------o--------o--o----oooo-----
\/ \ \ / / / \
/\ \ \ / / / \
ing-ci --o----o--o--o \ \ o agent/update-home --o/---oo / \
\ \ / / \
\ \ / / \
\ o agent/dark-mode --o--o/---o--o
\ /
\ /
o agent/new-widget --o---o----o-o
o commit \ new branch / merge to main 1 agent running · 4 mergedThe system was finished. It was lovely, and everything just worked.

But something was missing
Well, not quite. It felt as if it was missing life. Something that seemed to think for itself. And yes, I'm not Dario from Anthropic, so I do know that an AI isn't alive. Not even if it has a SOUL.md file.
A system that runs agents around the clock should also be able to improve itself. Both from the workflows it runs, and over time, as it (and I) get a better idea of where we're headed.
So I built one more agent on top of my agent system. It's called Steward. It keeps an eye on everything in the system: the other agents, what they're doing, and how their workflows are running. It also watches my Git repos, my pipelines and the errors that come up. And it learns how I work.
....... STEWARD watching the system \ ....... ....... ------------------------------------------ .... .... > new commit in byhartvig/Portfolio ... ... > you wrote in your notes 507 times .. o schedules > you're most active 08:00-11:00 ... . . . . . ... > all schedules are running on time ... . o . ....... > agent #14 h .. . . ........... .. . ............... ------------------------------------------ ... +................... .. . +::::............ IDEA widget · from your habits .. . . ++:::o:agent #14 ... . #++::::::::... Your to-dos on the home page ... . . . . . #+++::::... The open to-dos from all your notes, .. #+++:.. nearest deadline first. ... ##... .... . .... ....... ....... ....... [ Approve ] [ Not now ]
Steward simply “lives” in the system. When it sees something that could be added, changed or removed, it suggests it, and I approve with one click. If I describe what I'd like to see on the home page, it even designs a new widget for me itself.

The future is tailor-made
I believe modular systems like this are the future. Systems tailored to you, to me, or to your mother-in-law. Systems that “know” you and so know what needs doing, maybe before you do.
AI is cool. And it's only getting cooler.