All workshops

Workshop 06

Wiring an AI Feature That Behaves

Add an AI feature that is useful, bounded and does not embarrass you in public.

2.5 hrsLevel Advanced6 steps4 milestones
01

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
02

Resources

Open these in a second tab before you begin.

03

Instructions

Work through these in order. Where there is a prompt, copy it and fill in the parts in angle brackets.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 06

    Test with hostile input

    Paste nonsense, an empty string, a very long document and an attempt to override the instructions. Fix whatever leaks.

04

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.

05

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 build

Other workshops