Build a local AI feature
Define the feature boundary
Add local AI as one narrow transformation with explicit input, output, timeout, and fallback behavior.
We will build a local activity summarizer. One narrow transformation, not “add AI everywhere.”
Its input is factual application data:
const activity = {
focusMinutes: 52,
completedTasks: 3,
interrupted: false,
}
Its output is one sentence plus a confidence label:
{
summary: 'You focused for 52 minutes and completed 3 tasks.',
confidence: 'high',
}
The original activity record remains the source of truth. The generated sentence is a convenience layer on top of fields you already store.
Define failure before writing the request. If Ollama is missing, the model is unavailable, the request times out, or the response fails validation, the application will create a deterministic sentence from the original fields. The user still gets a useful screen.
This boundary keeps the product useful without AI. It also gives us an exact contract to test. Unit tests can assert the fallback without starting Ollama.
Notice what we did not promise. The model will not delete data, send email, or rewrite history. It returns one summary object. Small scope makes security and testing tractable.
Write the contract in one file near the adapter: input shape, output shape, max length, timeout budget, and fallback trigger list. When someone asks to “just add one more field the model can change,” point at that file and decide deliberately.
My advice is to ship the deterministic path first. Once that works in the UI, swap in the model path behind the same interface. You can demo the feature on a plane with Ollama stopped.
Try this on your own project: implement the fallback sentence before you call /api/chat. If the UI already looks correct without the model, you picked the right boundary.
Lesson completed