Building an AI-first project
The hard part of building an AI product is no longer the model. Anyone can call an LLM in three lines. The hard part is everything around it: the tools the model can call, the knowledge it loads, the parts of its work you can see, and the moments where a human stays in control. That surrounding system is the harness, and in an AI-first product the harness is the product.
This is how I think about building one, and the smallest real version you can run today with Distri.
The hard part moved
For years the scarce skill was writing the code. Now writing code and calling the model are both cheap. What stays hard is direction, meaning what the thing should do and whether it is correct, and verification, meaning proof that it actually did that. An AI-first project is one you organize around those two problems instead of around the model call.
In practice, AI-first means the agent is a first-class part of the product. It reasons over your own functions, it carries just enough knowledge to act, and you can inspect and gate what it did. Not a chatbot bolted onto the side. A component with judgment, wired into the real system.
An agent is a markdown file
In Distri you do not start with a framework and a graph of nodes. You start with a markdown file. The frontmatter sets behavior, the body is the prompt.
---
name = "assistant"
description = "A helpful assistant with web search"
max_iterations = 15
[tools]
builtin = ["final", "search"]
[model_settings]
model = "gpt-4.1-mini"
---
You are a helpful assistant. Use search to find current information, then answer.
{{task}}
Run it:
distri run --agent assistant --task "What shipped in Rust 1.90?"
That is a working agent. It plans, calls the search tool, reads the results, and answers. The entire definition is one file you can read, diff, and review like any other piece of code.
Give it your product's functions
An assistant that can only search is a demo. A product agent needs to call your functions: create the invoice, move the drone, grade the essay. Distri gives you four ways to wire tools in, and you will use all of them:
- Built-ins: search, shell, browser.
- HTTP tools: point the agent at your existing API.
- MCP: connect any Model Context Protocol server.
- Client-side tools: functions that run in the user's browser or app.
The agent does not care where a tool runs. It sees a name, a description, and a schema, and it decides when to call it. Your product's real capabilities become the agent's action space.
Give it knowledge, on demand
Prompts get long and go stale. Distri has skills: knowledge documents the agent loads at runtime with load_skill, and that get re-injected after the context is compacted so the agent does not forget them mid-task. You keep the base prompt small and let the agent pull in the grading rubric, the rules of engagement, or the house style only when it needs them.
Split the work
When a task is large, one agent holding everything in context degrades. Distri lets an agent delegate to sub-agents, each with its own isolated context and token budget. That is how you do more at once without quality slipping, and it is the foundation of what I have been calling loop engineering.
Make it observable
This is the part most teams skip and then regret. You cannot trust what you cannot see. Every Distri run produces a trace: the steps the agent took, the tools it called, the tokens it spent. The React developer mode renders it inline. Before you ship an agent you should be able to answer, straight from the trace, why it did that and what it cost. I will go deep on reading traces in the next post.
Put it where users already are
An agent nobody reaches is not a product. Distri runs the same agent three ways:
- The CLI and TUI, for you and for developer tools:
distri tui assistant. - An API server, for your backend:
distri serve. - React, with the drop-in
<Chat />component: streaming, tool renderers, voice, and the developer mode above.
Same markdown file, three surfaces.
The through-line
Clamp the what, free the how, verify. Pin down what the agent is for and the functions it may call, let the model work out the how, and check every run against the trace. Do that, and the harness rather than the raw model becomes the thing that is hard to copy. That is the whole bet behind Distri, and behind the products I am building on top of it.
Try it
curl -fsSL https://distri.dev/install.sh | sh
distri run search --task "What are the top programming languages in 2026?"
Then read the docs and define your own agent. It is one file.
