Building with AI

The engineering of putting a model inside your own software: a chat interface that fits on one screen, tool calls that are typed rather than parsed, and an agent held to a build that has to pass.

16 posts

Start here

Why a CLI is already most of the way to being an agent tool, and why you do not need a framework to talk to a model.

  1. Your CLI is already an AI toolA well-built CLI already has what an agent needs: named operations, descriptions and typed parameters. Exposing one over MCP takes no AI code. Pioneering
  2. An AI interface that fits on one screenYou do not need LangChain in a command-line tool. A four-method chat interface can hide five providers, tool calling and structured output. Pioneering

Making the model useful

Tool calling, structured output, and refusing to parse prose with regular expressions.

  1. Letting the AI call your Go functionsTool calling and the reason-act-observe loop explained, and how to define a tool in Go so the schema comes from the type rather than by hand. Pioneering
  2. Stop regex-ing the LLM's proseStop parsing an LLM's prose with regular expressions. Derive a JSON schema from your Go or Rust type so the schema and the type cannot drift. Pioneering
  3. AI conversations you can resumePersisting an AI conversation in Go: snapshot the messages, prompt and tool metadata, and deliberately never the handlers or the API token. Pioneering
  4. Nobody reads the manualDocumentation loses to --help on location, so embed the docs in the binary: a terminal browser and an assistant grounded only in your own pages. Pioneering

Providers, and their differences

Five behind one interface, including one that is not an API at all.

  1. The AI provider that isn't an APIFive AI providers behind one Go interface, including one that shells out to a locally authenticated CLI for networks that allow no API calls. Pioneering
  2. Supporting a provider, or actually using itA lowest-common-denominator AI interface throws away what each provider is good at. When to route through an abstraction and when to drop below it. Pioneering
  3. A configurable AI endpoint is an attack surfaceA user-settable AI base URL decides where your API key gets sent. Validating it to reject userinfo, non-HTTPS schemes and redirects. Pioneering

Agents that have to prove it

Generate-and-hope does not survive contact with a compiler.

  1. An AI agent that has to make the build passGenerate-and-hope does not work for codegen. Handing the draft to a repair agent with a fixed toolset that has to make build, test and lint pass. Pioneering
  2. The agent said SUCCESS. The linter disagreed.An AI repair agent declared success the moment the code compiled. The linter disagreed, and the gap between those two is the whole story. Pioneering
  3. The afternoon the agent earned its keepAdding stream-copy remux to a WebAssembly FFmpeg build, where writing Matroska hung forever and the identical MP4 path did not. Pioneering
  4. I filed a feature request into my own frameworkBuilding on your own framework means finding its gaps as a user rather than an author, and having to file the request against yourself. Pioneering

Testing it, and playing with it

You cannot test the model, but you can test everything around it.

  1. Testing code that calls an LLM: yes, you actually canYou cannot test the model, but you can test your code: snapshot the prompt as a golden file and mock the response to cover the ugly cases. Pioneering
  2. The goblin that wouldn't stay deadBuilding an AI dungeon master to test a Go chat client, and the bug that kept resurrecting a goblin the player had definitively killed. Pioneering
  3. Generate a command from a script or a sentence with go-tool-baseGenerating a Go command from a shell script or a plain sentence, and the repair agent that has to make the result build before you see it. Orienteering

Where to next

Everything, newest first →