Graham Knapp

AI design patterns django e57 feature flags pointcloud python Rhino 3D talks TypeScript wind engineering

Testing GitHub Copilot agent mode 🔗

written by Graham Knapp on 2025-08-23

I tested GitHub Copilot agent mode in July 2025, setting Copilot to work online on different sized features - the workflow looks like this:

  1. Chat with Copilot online - ask it to open a PR to work on a specific feature. Copilot starts working in its own virtual machine on GitHub.
  2. 30 minutes later I get an email saying the PR is ready for review - I read it online and ask for any corrections via github.com
  3. If and when I am happy with it I pull the branch to my PC, review, modify, fix, change.
  4. I push from my machine and merge to trunk

Some stats:

  • 19 Pull requests opened against our main monorepo in 5 weeks.
  • 7 merged
  • 8 still open on the 31st of July (3 of those created on the final day)
  • 3 closed unmerged because they clearly didn't work or were not worth finishing
  • 1 closed because I reimplemented it more successfully on my dev PC

For example, I tasked Copilot with refactoring 3 instances of near-duplicate code into a common service and make some improvements to error handling on the refactored service. My experience of code review from the last 4 years definitely helps with this workflow - reviewing code from an agent is similar to reviewing colleagues' code except that I don't feel guilty about leaving a PR unread for more than a day. Those PRs still become stale however and merge conflicts are a pain if the agent changes overlap with other PRs.

One challenge is that this makes it very easy to set Copilot working on easy to define low-impact work but that work still takes to review. It would be easy to get into the habit of doing lots of unimportant busy work with this workflow. I now want to explore how to use coding agents to achieve more ambitious changes, perhaps changes I would not take on individually because they lie near the limits of my current knowledge.


Playing "In my bag..." with LLM agent templates 🔗

written by Graham Knapp on 2025-08-10

There's a memory game "In my bag..." where you pretend you have a list of things in your bag "In my bag I have a comb and a cat". The next person in the circle has to list all the same things and add one more at the end "In my bag I have a comb, a cat and a clock". The game ends when someone makes a mistake or gives up.

It occurred to me that this is a great analogy for the templates used in LLM chatbots! Every time you chat with an LLM the LLM re-reads the whole history of the conversation before responding. This is why they get slower over time, particularly if they are making web searches, viewing images, using MCPs or other tools which add a lot of hidden tokens to the chat history.

The ollama docs describe a simple template here ... https://github.com/ollama/ollama/blob/main/docs/template.md


Feature flags Pt 3: Deploy to some of the people all of the time, and all of the people some of the time! 🔗

written by Graham Knapp on 2025-04-25

My talk from DjangoCon Europe 2025 - I discuss:

  1. What are Feature Flags ?
  2. Why use Feature Flags ?
  3. How Acernis uses Feature Flags
  4. Getting started with Feature Flags in Python and Django

Preview image from the talk

Read Full Post


AI coding - stone soup 🔗

written by Graham Knapp on 2025-03-01

There's an old European folk tale of a man going into a village and asking for a pot and some water so he can make stone soup. Intrigued, the villagers give him a pot and some water and he boils it up. After a while he tastes it and says "not bad but it could use some onion - do you have some leftovers". The villagers give him a bit of onion and a few herbs whilst they are at it. It carries on like this until he has a delicious soup and the villagers are amazed that he did all that with just a pot of water and a stone.

I love Copilot, Claude and all the good things but the iterations of GitHub issues, suggested actions, debugging and fixing in the newer tool previews often taste suspiciously like stone soup 😅 🪨🍲 .


TIL: Django caching doesn't cross versions 🔗

written by Graham Knapp on 2025-02-11

Reading into this issue on Django-waffle I learned that Django uses pickle to store objects in its cache but does not guarantee that these objects will remain valid between versions, so it raises a RuntimeWarning when you access potentially stale objects.

The Django docs recommend clearing the cache on upgrade, and this Stackoverflow post discusses ways of doing that.


AI coding patterns: Language bridging 🔗

written by Graham Knapp on 2025-02-10

A pattern I enjoy with Copilot or other AI coding tools is something I'm calling "Language bridging":

Language bridging : Write code to solve a problem in a language you know well, then use an AI to translate the code into the language you want or need to use.

Read Full Post


Real developers 🔗

written by Graham Knapp on 2025-02-08

There's this myth we tell ourselves about "Real developers" and especially "this is why I am not a Real developer". It got me thinking - is there actually a useful definition out there?

Here is my best try:

*A 'Real Developer' is someone who writes code or other instructions for a computer which run successfully and get something useful or delightful done in the real world

Read Full Post


2024 - My year in Open Source 🔗

written by Graham Knapp on 2025-02-07

Looking back on 2024 here are some personal highlights:

Maintaining an established pypi package 📦

Early in 2024 I took over maintenance of the very useful Python package pye57 for reading and writing e57 format pointcloud files. I have been using it at work for several years and was worried that it was not being maintained, blocking upgrade of our project to Python 3.11. I had already started working on an alternative library, cleverly titled e57 - essentially I got in touch with the project maintainer, providing some evidence that I was a real human being not a sham account, many thanks to David Caron for creating the library and maintaining it for so many years, and for trusting me to carry it on.

Read Full Post


E57 file xml extractor 🔗

written by Graham Knapp on 2025-01-26

See the xml portion from the end of an .e57 pointcloud file. This contains information like the bounding box of the pointcloud, the number of points and how the points and other information are organised in the file.

I wrote it with a bit of help from Claude ai by describing what I wanted and pasting a description of the e57 file format before doing a lot of debugging to get the entire xml section and then integrating it with my blog.

I find the e57 file format a bit wierd - it starts with a header including a file version number and an offset to the XML portion, which comes at the end of the file so you need to read both ends of the file before you can understand the middle bit. So if you download the file you have to wait for it to finish downloading - you can't start to interpret or display the points and other data whilst streaming data.

This tool is written in JavaScript and runs in your browser - no files are uploaded to any server (in fact this blog has no backend server - it is a static web site - it is downloaded and runs entirely in your browser).


        

Two's company, three's a crowd 🔗

written by Graham Knapp on 2025-01-20

My version of YAGNI - "You Ain't Gonna Need It" - is a rule of three: only spend time refactoring your code when you have repeated yourself 3 times. Don't aim for truly DRY code devoid of all repetition.

I'm not saying not to apply SOLID design principles from the start - I definitely try to separate concerns, giving a single responsibility to a class or function and avoid, for instance, a single method handling file reading, data transformation and reporting. This simplicity will make it much easier to refactor the code later.

I am saying to avoid using sophisticated design patterns, architecture or abstractions before you have used of your code enough to know what is likely to change (and require encapsulation) and what will stay constant (creating a useful abstraction).

Read Full Post