Beehive: Putting AI Agents to Work Without Leaving the Couch

Local AI agent has been working unattended for weeks now. This blog has been unattended since 2020.

Hello again! It has been a while. My previous post, about building a Xamarin iOS app in the cloud, dates from December 2020. Before that I managed 5 posts in 2011, 3 in 2012, 3 in 2014, 6 in 2017, 3 in 2018, one in 2019 and one in 2020. Statistically, my posting cadence is best described as “best described as ‘TODO: write post'”. Xamarin has since been retired, and the cloud built that app without me.

Don’t mistake the silence for idleness: I have been very busy, just not very vocal about it here. This post is about one of the things I have been working on: Beehive.

The itch

I pay for GitHub Copilot, and its premium requests are metered: use more AI than your plan allows and you buy extra credits. Meanwhile, I have a desktop at home (64 GB RAM and an RTX 4060 Ti) that is good enough to run local models through Ollama, and that sits idle most of the day.

Plenty of programming tasks are not time-pressured: “add this endpoint”, “fix that test”, “write the docs”. They can run in the background while I work on something else, or overnight while I sleep. Local models are free to use, so these tasks cost no extra credits, and I get to use a lot more AI in a month for the same money. (I have not calculated the power consumption yet; the savings may be smaller than I like to think.)

What I wanted was this:

Open a web page on my laptop, pick a repository, pick a model, type a task, and go do something else. When I come back, there is a branch waiting for me with the result.

That is Beehive: a small local-network tool that hands tasks to GitHub Copilot CLI, backed by local Ollama models, against git repositories that are checked out on the machine.

The rules of the hive

A few design decisions shape everything else:

  1. Agents never touch my working copy. Every session gets its own git worktree, so the agent can make a mess without me noticing, or caring.
  2. Always a branch, always pushed. Every task ends up on an agent/{task} branch that is committed and pushed. Nothing lands on main unreviewed; the pull request is where I come in.
  3. Everything is remembered. Each session is stored: the prompt, the whole conversation, tool calls, the “thoughts” of the model, the files it changed, and the commits it made. A session can be resumed later with a follow-up prompt, continuing on the same branch.
  4. One at a time. There is only one GPU, so a queue runs one session at a time. Parallelism is a problem for future me.
  5. No accounts, no auth. Beehive never handles logins; it assumes Copilot CLI is already signed in. It is meant for my trusted home network only. (Yes, I wrote that in the docs in bold. Please do not put it on the internet.)

The architecture

Software architecture of Beehive

The whole thing is started by a single command: a dotNET Aspire AppHost spins up the API, the PostgreSQL container (with a persistent volume, lesson learned the hard way) and the Vite frontend, and wires the URLs together.

The life of a task

  1. The dashboard lists repositories (git repos under one configured root folder), models (straight from Ollama) and agents (custom *.agent.md files in the repo or my Copilot home, plus the built-in default).
  2. I type a task and hit Run. The API stores a Pending session and puts it on the queue.
  3. The runner creates a worktree and a branch named agent/{task-slug}, then starts Copilot CLI inside it with --output-format json.
  4. The JSONL events stream back and are stored as they come in. The frontend polls and shows the conversation live, with thoughts collapsed, tool calls as cards, and a Stop button if the model starts going in circles (it does, sometimes; small models love repeating the same thought twenty times).
  5. When Copilot finishes, everything is committed and pushed. The session view then shows the files changed with diffs, and a git log for the branch.
  6. Not quite right? Type a follow-up and the same session is resumed in the same branch.

Built the way I would build anything

The project is a fairly strict .NET 10 codebase: controllers with one endpoint each, in REPR-style feature folders (POST /api/<area>/<feature>), Mediator (the source-generated one, not MediatR), an interface for every service, one IEntityTypeConfiguration<T> per EF Core entity, and tests with NUnit, Moq and AwesomeAssertions, all written in Arrange-Act-Assert style.

The fun part is that these conventions are written down in an AGENTS.md file, and a good chunk of Beehive was itself built by an AI agent following those rules. Every task also leaves a devlog entry (prompt, plan, changes), so there is a diary of the project, which is more than my blog can say. The docs folder holds the ideas list, the implementation plan, and a plan per larger feature, and I review each plan before anything is implemented.

What works today

  • Repository, model and agent discovery
  • Running Copilot CLI on a local Ollama model, in an isolated worktree, always ending on a pushed agent/{task} branch
  • Persistent sessions with the full conversation, tool calls, thoughts, changed files, diffs and the branch’s git log
  • Resume and stop for sessions
  • A GitHub-flavored dashboard with resizable panels, markdown rendering, a backend health indicator and an Update & restart button (hidden behind a cog) that does a git pull and restarts the whole app, so I can ship Beehive improvements to the machine under the desk without walking over to it

What is next

  • Telemetry: Copilot CLI can export OpenTelemetry data. I want tokens, tool calls, durations and lines changed per session, perhaps with Prometheus for long-term trends. I already researched this, and the answer is “yes, but it is a complement to the raw JSONL, not a replacement”.
  • Changing model and agent when resuming a session.
  • Custom models from Hugging Face, so I’m not limited to what is in the Ollama library.
  • Parallel sessions, once I figure out what to do with a single GPU.

Why bother?

Mostly because I wanted to see how far you can get when the agent does the typing and I do the thinking, reviewing and deciding. Beehive turns that into a workflow: small tasks go in, branches come out, and I stay in charge of what actually gets merged. Also, a name like Beehive makes the whole thing sound far busier than it is.

I will try to write more about it as it grows. Given my track record, you may want to set a reminder for 2032.

Allium ‘Google Analytics v3 Tracker in C#’

Lately I’ve been looking into NuGet packages and libraries on GitHub to add Google Analytics tracking in .NET WPF applications. There are quite some that offer ways to do this, see the links at the end. They all however have their limitations; either they lack support for WPF (and it’s hard to add) or they use older versions of the Google Measurements Protocol. It’s a shame that Google hasn’t released a tracking library itself! Their Analytics Reporting API is quite good!

So I’ve decided to create my own solution, Allium. As of right now, it is still WIP and untested.

Here is however an extremely simple usage example, which will not change much during development;


using (var session = new AnalyticsSession("UA-XXXXX-YY"))
{
  session.TrackScreenViewHit("ThisWindow");
}

Inspired by;

Update on 2012 resolutions…

Ok, I must confess it has been a while since I last posted. In my last post I talked about resolutions for 2012 and now I would like to give that an update. In some way I’ve worked on all of them.

In September I switched jobs, to a much smaller company; Soltegro. It gives me much more ways to grow and improve myself and bond with my colleagues. It is also a tad bit closer to home, and I can safely work from home so the commute is a lot better, giving me more time off. Instead of using that time for working on personal projects as I promised I’ve taken a second job working on mobile-, media- and games-applications. During that job I have however developed my first android app that went online in the Google Play store; MMH Calculator.

I’ve spent the spare time between my two jobs working on my prototype. It isn’t as far as I had hoped, but I’ve got 3 more weeks with some days off until the end of the year, so who knows?

2012

Happy new year!

I guess 2011 wasn’t the year I would pick-up blogging! And 2012 won’t be it either…

So what will I do then with this site you might ask?

Well below are some new-years resolutions and I hope that by the end of 2012 I’ve completed all of them! Whenever I complete any of my resolution or the plans change I’ll post an update back here.

In 2011 I developed for several personal projects, found support for one project and tested out several idea’s. I had a great year with my friends playing board games and hanging out, I made quite some new friends and even went to Mexico to visit one! At the end of the year I visited my sister in Berlin and finished the year at my place with some close friends. Not bad at all!

In 2012 I will…

  1. No matter what, this year is going to be the year I will introduce my first game for a mobile platform. It looks like it is going to be Windows Phone, as development is easier and my product close to being finished! (Could start investigating PhoneGap afterwards to go multi-platform!)
  2. In late January there’s a SuperStijl event in the 013! After that event I will decide how to continue, but my voting-system for pubs and events has made a huge leap last year! If my version has enough changes with the original I will finish it for a prototype in early summer!
  3. After gaining more interest in board-games this last year I’ve come up with an idea for a Facebook/Social-media game that can be easily done with Windows Azure and Node.js. It would be good to get some prototyping off the ground and introduce it to some people to find support and help.
  4. Since November 2010 I’ve been travelling almost 2 hours a day from home to work and back and this has cost me a lot of spare-time, which could have been used to develop some of my projects! Thus another resolution will be to find either a project that can be done with less travel time or find a new job outside detachment agencies.
  5. If finding another project or job doesn’t prove fruitful there’s always another option available: do a 3 or 6 month term at a Swedish University!
  6. Something a lot more personal is losing weight, it’s not that I’m super fat but I could look a little more healthier!

I’m off, going to Breda: Limewax vs Bong-Ra vs Thrasher @ Mezz!

Bitcoin Club

Since a month or two I got into reading about and trading with Bitcoin, a peer-to-peer currency. A few weeks down the road I joined the Bitcoin IRC-channels and made some connections with other Dutch people interested in Bitcoin. At the time it seemed there was no website out there keeping track of all the Dutch Bitcoin news in the media. So I registered a new domain and setup a WordPress blog at [discontinued].

The Bitcoin Club site will be updated with news and articles related to Bitcoin in the Dutch media. We’ll also try to write some articles ourselves about the background of Bitcoin, or the current market or any other interesting news. If you’re interested in Bitcoin watch the Youtube video below.