Workshop 06
Wiring an AI Feature That Behaves
Add an AI feature that is useful, bounded and does not embarrass you in public.
Overview
What you will build
A production-shaped AI feature with guardrails, graceful failure and cost control.
Who it is for
Builders adding AI to a real product who care what happens on a bad day.
Before you start
- — A working app with real data or real users
- — A specific job you want AI to do
- — Comfort with reading server-side logic
What you will walk away with
- Scope an AI feature to one job with a clear success test
- Handle slow, wrong and empty responses without breaking the UI
- Keep keys server-side and costs predictable
Resources
Open these in a second tab before you begin.
Instructions
Work through these in order. Where there is a prompt, copy it and fill in the parts in angle brackets.
- 01
Define the one job and its success test
Write the feature as: given this input, produce this output, and it is correct when this is true. If you cannot write the test, the feature is not ready to build.
- 02
Keep the key on the server
Any API key visible in the browser is a public key. The call belongs in server-side code, always.
Add an AI feature with the model call running server-side only. The API key must be read from server environment variables and never reach the browser. The client sends only the user's input and receives only the finished result.
- 03
Constrain the output shape
Free-form text is hard to render and easy to break. Ask for a fixed structure and validate it before it touches the UI.
Constrain the model output to this exact structure: <describe fields and types>. Validate the response server-side and reject anything that does not match, returning a clear error instead of passing bad data to the interface.
- 04
Design the bad day
Slow, empty, wrong and rate-limited are all normal. Each needs a visible, calm state.
Handle these cases explicitly in the interface: request still running, empty result, invalid result, rate limited, and service unavailable. Each gets a short human message and a way forward. Never leave a spinner running forever.
- 05
Cap the cost
Add a ceiling before you add users. Limit per-request size and per-user frequency so a single bad actor cannot drain the budget.
Add limits: a maximum input length, a maximum output length, and a per-user rate limit of <n> requests per hour enforced server-side. Show a clear message when a limit is hit.
- 06
Test with hostile input
Paste nonsense, an empty string, a very long document and an attempt to override the instructions. Fix whatever leaks.
Build-along
The same journey as milestones, so you can stop at any point and pick it up later. Do not move on until the checkpoint is true.
Milestone 1 — One job, one test
A written success test for the feature.
Checkpoint — You can judge any output as pass or fail.
Milestone 2 — Server-side call
The model call runs on the server with the key hidden.
Checkpoint — No key appears in browser network requests.
Milestone 3 — Bounded output
Structured, validated responses.
Checkpoint — A malformed response shows an error, not a broken screen.
Milestone 4 — Survives a bad day
Limits and failure states in place.
Checkpoint — Hostile input produces a calm message, not a crash.
Build Submission
Send your success test, a screenshot of a failure state, and the limits you set.
Submissions are sent by message — nothing is stored on this site.
Submit your buildOther workshops