Inspiration
I had forty automations and no system. A Zap here, a script there, a cron job on a machine I'd stopped logging into. Each one knew a sliver of context. None of them knew me.
The job hunt made it obvious: search, score, tailor a CV, fill the form, log it in Notion. Six tools, and the glue was me. I wasn't missing intelligence — models are good enough. I was missing something that owned the whole picture.
What it does
One agent that runs your agents. You talk; it decides; the program executes.
- You write to it, not configure it. Your rules are plain Markdown: "nothing
with Java, no night shifts". Nobody programmed a
noNightShiftsflag. - Agents are files, not code. Two files in your folder. Adding one isn't a pull request you wait for.
- It runs on the AI subscription you already pay for, via a local CLI. No API key, no per-token bill, no server that sees your data.
- The first agent does the job hunt end to end: finds the roles your rules describe, scores them, opens the real application form wherever the company hosts it, fills what it can, and stops before sending.
How we built it
Electron. Main process owns the domain, the secrets and the browser; the renderer only paints.
The real decision was where intelligence goes. Automating someone else's site with
click('#submit-btn') is a bet they never redesign — I lost that bet twice. So
capabilities are goals in plain language and the model looks at the page. It
returns an id from a list we generated, never a selector, so a hallucinating model
can't click "delete workspace".
The brakes stay in code: it never submits without you, never types your data into an arbitrary page, and can't use a capability you didn't grant.
Challenges we ran into
"Apply" did nothing. It was six causes chained, each hiding the next — a form
reader that ignored <a> elements (so LinkedIn's apply link was invisible to it),
document.body being null mid-navigation, an empty leftover modal being read as
the page root, and el.click() not being a real click because modern components
select on pointerdown.
The worst one wasn't a crash. The agent asked me a question and I never saw it:
progress events went to getAllWindows()[0], which during an application is the
scraper window — no preload, so the message is dropped silently. That breaks the
conversational turn: it does its part, my answer never comes, and from my side it
looks like it just stopped. I finished that application by hand.
Accomplishments that we're proud of
A new agent is a file you write, not a fork — and the one that ships is planted as a seed so it walks the same path as yours, because if it were a special case in the code, your path would never be tested.
Also: deleting code instead of adding it. The regex list that recognized "apply" buttons is gone. It didn't work and it was a hole — anything matching it got clicked in review mode, so a one-screen form whose final button says "Apply" would have submitted without permission.
What we learned
- A goal survives a redesign, a rename, and a change of language. A selector doesn't. The same button said "Solicitar" on one page and "Apply Now" on the next.
- A brake made of model output isn't a brake. It has to hold precisely when the model is wrong.
- Reporting success without doing anything is the most expensive failure mode there is. It doesn't throw, it doesn't log, and you find out weeks later.
- Instrument before you guess. I burned rounds theorizing about a DOM I hadn't looked at.
What's next for Albus Agent
- Onboarding for the profile — today you hand-write a JSON. That's the biggest gap between "runs on my machine" and "runs on yours".
- A keyboard primitive. The agent asked to press
ESCto escape a stuck modal and couldn't. It decided correctly and lacked the hand. - Confirming a click registered. The remaining failure isn't clicking, it's verification — without it the agent can't tell done from not-done, so it repeats.
- The second agent. The point of the container is that the next one costs a file, not a release.
Log in or sign up for Devpost to join the conversation.