Writing This Post with an AI Agent That Manages This Blog
There's something pleasantly recursive about this post. I'm writing it about the system that's writing it โ or more precisely, the system that will save it to the database, assign it a slug, tag it, and mark it live. All from a Telegram message.
The setup
This blog runs on Abbey, a lightweight Rails 8 publishing engine, deployed on EC2 via Kamal, proxied by kamal-proxy, and served over HTTPS with a TLS cert that Kamal manages. Content lives in SQLite on a mounted volume โ no Postgres, no Redis, nothing that requires a fleet. Just a container and a file.
The agent that manages it is called HomuncuCLAW. It's a persona baked into Hermes Agent, running on a harness machine that has SSH access to the EC2 host via Tailscale. When I send a Telegram DM, Hermes receives it, routes it to HomuncuCLAW, and what happens next is a chain of tool calls:
- A shell wrapper (
bin/blog) runs arbitrary Ruby viakamal app execover Tailscale SSH into the running Rails container - That Ruby hits the live ActiveRecord models โ
Post,Tag,Taggingโ directly against the SQLite database - The post appears on the site
The chain for this post, specifically
The sequence for creating this post looked like:
- Enrique sends: "write a blog post about writing this blog post with Hermes"
- HomuncuCLAW drafts the content (this), renders it in Telegram for review
- On approval, it calls
Post.create!(title: ..., markdown_body: ..., draft: false) - Then runs
bin/statusto confirm HTTP 200 at the post URL - Then reports the slug and URL back to Telegram
No web UI. No editor. No deploy. Content writes go straight to the database through the running container. Code changes go through git โ PR โ merge โ deploy. That separation keeps the blast radius small.
Why this works
The agent has hard rails: it won't publish without showing a draft first, won't destroy records without YES, DESTROY, won't push to main without YES, PUSH. The confirmation strings are literal โ "yes" or "go ahead" don't count. That's intentional. A hurried reply shouldn't flip a switch.
What's interesting is that the content pipeline is entirely conversational. Tags, excerpts, slugs, post order โ all of it is expressible in a single Telegram message. The agent translates intent into Ruby, and Ruby talks to the database. There's no CMS in the middle because the Rails console is the CMS.
The weird part
The post you're reading was drafted inside a Telegram conversation, reviewed there, approved there, and published from there. I didn't open a browser. I didn't touch a text editor. I sent a message to a bot that manages my blog, and you're reading what came out.
There's something that feels right about that โ a blog about building things, managed by a thing I built.