Guardrails for Unfeeling Robots

Last updated on 20th October 2026

This year has been incredible. For the first time in years, I am learning and fully engaged with my programming career. I am not starved for creative outlets or feeling as though I am stagnating. Long may it last.

One of the reasons for this is that I am using agents to write 100% of the code I ship, and also to do a significant portion of the busy-work I used to have to do by hand. Like a caveman. This doesn’t usually happen without giving significant power over to something that feels nothing about performing wildly destructive actions randomly.

Models and harnesses are getting better at preventing destructive actions in a coding context; but their systems are not bullet proof. They are also not good at preventing non-coding disasters.

The kind where the model wants to send hundreds of mails out because it has misunderstood the right time or way to follow an instruction. The kind where it replies to a work message with the wrong information or language. The kind where it wants to delete a GitHub repository because you asked it to clean up, and it spares no thought for the fallout of its actions.

Shell

Shortly after deciding to hand over so much to robots, I realised these things could happen to me. I built a small web app to act as a shell around my credentials. It’s called Shell, and my instance of it lives at shell.assertchris.dev.

Shell is two things:

  1. Filament admin for provisioning bot API tokens and service accounts, and for storing the credentials for these service accounts.
  2. An API my bot can call to do useful things in those services.

Shell protects me in a couple ways. Firstly, it hides the service credentials in a place my bot can never see (the production database it does not have access to). My bot can never hit these services directly because it’ll get a 401 rejection.

Secondly, my bot can only do what I expose via Shell’s API endpoints. This is expecially useful for services where scoping the credtials is difficult or impossible. To use Gmail IMAP, you need an app password. It’s their own special way of reminding you how insecure the internet really is. The app password will let my bot do anything to my email (acting as me!) if I let it. It can delete anything. It can reply to anyone. That’s obviously bad.

Shell only exposes API endpoints for reading mail and downloading attachments. My bot can never use it to send email.

We use JIRA at work. JIRA’s API is massive and inscrutible. It’s very difficult to pick the correct scopes when provisioning a JIRA API token. I don’t have to, because I can limit what my bot can do, when I store an “all scopes” JIRA token in Shell.

Why am I telling you this?

I am making Shell open source. I am tired of telling people I have this thing and not being able to share a link to where they can see and use it. Shell looks like something I made and only use for myself. Despite using Filament, I have somehow managed to make it still look like crap.

I expect nobody to use this. I expect people to think it looks a mess, and that it doesn’t support enough platforms. That’s fine. I will continue to use Shell for myself, because I believe the pattern is good. Over time I will add more platforms and better admin design. Maybe even better docs design.

If other folks learn the pattern or from the code, or even find it useful to self-host their own instance: that is a bonus. At least I’ll be able to show people the app I keep talking about. Hopefully this is the first of many AI related things I use that I share.

You can see the code on GitHub. You can see the Shell docs at shell.assertchris.dev/docs.