#3794:Provocateur Agentique

Like many people, AI is now a significant part of my job as a Tech Lead. I’m using it for most things, which is easy because LLMs like Claude and Codex are biased towards software engineering.

I don’t consider myself bullish on AI, or AI-pilled, or a tech bro or anything like that. I started off skeptical and my opinion has shifted when I’ve seen successful (and not sloppy) results. It doesn’t change my opinions on the leaders of these companies but I take a dim view of big tech and Silicon Valley’s techno-capitalist-becoming-fascist general attitude to life, humanity, and the world. Lots and lots of engineering talent but not much in the way of legitimate tech for good, unless your version of good includes mass surveillance, social manipulation, advertising, anti-inclusive politics, and so on. I do feel like a hypocrite saying this given that I benefit from a lot of the tech produced out there that I use day to day, but in some ways it is inescapable.

The one thing I don’t and won’t use AI for creative pursuits out of work: writing, in particular, because it’s my thing. My words will always be my own.

Anyways, that’s my little disclaimer over. Let me now trash that principled stance by talking about some things that I’ve done with AI that I’ve either really enjoyed or found a decent amount of success with.

This Blog’s Admin Panel

I migrated my projects over to Cloudflare recently to save some money on hosting. There are various posts about me using NixOS here and while I still use it for my local environments, I didn’t really want to maintain my own server still. The active trade-off is that all my eggs are in Cloudflare’s basket but nothing here is so high stakes that downtime would bother me.

The second part of that is that I didn’t want to depend on emacs and a terminal to write, which is where AI came in: now I have a simple hosted editor setup plus an authenticated micropub endpoint that I can integrate with other apps. I haven’t gone the whole way with indieweb standards, though.

Overall this was fairly effortless and Codex did a better job of it than Claude without much context. This was a surprise but, to be honest, Claude seems to have disappointed since Fable and the whole drama around that.

Building a new harness

You might have heard of Pi[^0], which is a really lightweight agentic harness that is designed to be extensible. You do what you want with it, basically, and so I did.

It first started off with a prototype that I called pibarm[^1] (pie barm, a local delicacy popular in Wigan and Bolton in the north west of England), which bundled pi with a few extensions I thought came in handy. Don’t bother using it, it’s just there for show.

I decided to take this further and pivot into building an internal harness for work, which would then have the benefit of integrating easily into various internal resources. This has since expanded into:

  • PowerPoint presentation generation following branding guidelines, with asset creation
  • A native application that has a mode for engineers and one for non-technical people (i.e. a code/desktop split)
  • A skills marketplace with npx skills compatibility
  • A homebrew tap with a CLI wrapper as an installation path
  • A mechanism to contribute skills without knowing about github
  • Deep integrations with internal tools where possible (e.g. JIRA ticket for github branch, CI status)
  • Editor and syntax themes that use the company colour palette (just for fun)
  • An onboarding/setup wizard for first-time users

Early days but this has been quite an adventure and the hope is that colleagues enjoy using it and feel like it gives them features that rawdogging Codex or Claude doesn’t, at least not without setup.

Tailored Swift

Probably the most interesting bit was the development of the native app, because it’s not enough to just vibe code something in Swift and unleash it onto unsuspecting victims. There was the code signing, notarisation, and so on, that had to be handled so people could even open the thing in the first place. To be honest this would have been a massive faff before AI given that the app bundle embeds a NodeJS runtime and some other things, and all of those have to be signed as well for the app to run without Gatekeeper flagging it.

Given that I’ve been releasing quite quickly I also decided to set up Sparkle, which is an auto-updating framework that has been around for a long time in the world of MacOS (or OS X, given how far it goes back). Pretty much everybody would use this if they don’t want to deal with the app store and, for an internal tool, app store distribution is overkill.

Probably the most challenging aspect of this work was to build an interface and UX that implemented Liquid Glass and followed whatever remains of Apple’s Human Interface Guidelines (HIG). It’s far from perfect but I’m impressed with what I’ve got so far.

There will always be more polish required but the main focus has been rich UI/UX and state management. This is pertinent because, if you’re not using the app to write code (which will typically be tied to a git repo), you’re probably not connected to a specific location on disk at all. So, ‘work’ mode holds all that state in memory as a way to group connected conversations, with the option to export or backup to disk if necessary.

Very exciting. Especially because it’s not an Electron wrapper around a web interface even if it does eventually boil down to IPC with a NodeJS process. I’ve been able to iterate on this while working on other things, as part of eating my own dog food.

leppa.io[^2]

I tried my hand at creating a side-project too, most of which I did while Fable was available and not nerfed and also not locked behind usage credits. If I can’t use AI on a fairly strict budget then I won’t bother, and I’m not interested in tokenmaxxing or spinning up entire teams worth of agents. I like to stay in the loop that way.

This is just a small-ish app that manages temporary channels in Slack. It’ll spin them up, either ad-hoc or using a template or schedule, and then close them down when the timer runs out. It throws in some light AI summarisation as well.

I built this end-to-end as a theoretical SaaS app, and even though it’s public it has a waitlist, because there is no pricing and I don’t want to burn money on serving and supporting users when I’ve not even looked into business viability. Maybe if it has interest I would rethink that. At the bare minimum it solved a problem at work and I’m happy with that.

Structured planning

The last one, and probably the most sloppy, is Marionette[^3]. I wanted to experiment with a form of structured planning without veering right into workflow or agent orchestration, and to do that I used the narrative scripting language called Ink[^4] as inspiration.

Ink, in a nutshell, is a language that allows you to easily create complex, non-linear, branching narratives. It’ll produce something like a graph without really requiring you to structure your script that way. This is unlike, say, Twine, which doesn’t abstract the graph away at all, or Inform7, which solves for a different problem.

The compiler for Ink will tell you if your story has loose ends or other faults that would essentially make your game unplayable or lead the player into a soft lock. This is the exact concept I wanted to apply to agent planning.

So far I have a DSL and a planning engine more than a language. Under the hood the language is parsed in Typescript and the result is fed into an engine built in Prolog, which is the perfect language to apply rules and logic to something that is trying very hard to not look like a workflow. It understands loops, conditions, unknown variables (i.e. “do this until there are no open issues” means there is a counter for open issues but we don’t know what it is until runtime), and marionette will complain loudly if the workflow never terminates or has steps that lead nowhere.

I intend to spend more time on this but I’d also like to just rebuild it by hand to keep myself honest, using the prototype as a guide. Then focus on making it less annoying to use because it is extremely inflexible.

[^0]https://pi.dev

[^1]https://pibarm.lmchn.xyz

[^2]https://leppa.io

[^3]https://marionette.lmchn.xyz

[^4]https://www.inklestudios.com/ink