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.

21 posts

Start here

Why a CLI is already most of the way to being an agent tool, why you do not need a framework to talk to a model, and what fifty-four tool schemas cost before anyone types a word.

  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
  3. Fifty-four tools before a word was typedgo/mcp puts a Go CLI, HTTP service or gRPC service on the Model Context Protocol with three discovery tools instead of one per command, so a model carries a lantern rather than the whole catalogue. First Light

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

Ten behind one interface, including one that is not an API at all, and a client that still works when one capability is missing.

  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
  4. A client you can still use when you configured it wrongGo says a constructor either works or it doesn't. That contract stops making sense the moment a client has a dozen optional parts, so I broke it on purpose. Pioneering

Agents that have to prove it

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

  1. An agent is a loop with real tools and a fenceAn agent is a model in a loop with tools it can really call and results it can really see. Taking the ReAct pattern apart in go-tool-base. Pioneering
  2. 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
  3. 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
  4. 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
  5. 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

A bot that answers from the docs

phpbotscout answers questions from the estate's own documentation. Deciding what it may read, and finding out its scores meant nothing.

  1. The most tempting corpus in any repositoryThe issue tracker is full of answers, which is exactly why my support bot isn't allowed to quote it. An issue can point at the docs, but it never gets to be the answer. Pioneering
  2. The bot couldn't answer it. Neither could I.I read the question my support bot had fluffed, gave the correct answer off the top of my head, and was wrong. The docs had fooled the person who wrote them. Campfire

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 → Follow this guide by RSS