Skip to main content
A customer can describe an order in one sentence, but an application needs a structured cart with separate items and fields.
The TypeSafe part of that demo builds the cart out of several Choice questions, each of which returns one value. Here it runs on a small cafe menu and one hard-coded order.

How the cart builder works

The input is one sentence:
The application builds this cart:
A Choice question returns one option, not a whole cart. The application therefore uses two stages:
  1. Find the items. Repeatedly ask which remaining menu item the order mentions. Remove each selected item from the next request. Stop when Jev selects nothing_else.
  2. Fill the fields. For each found item, send one request with a Choice question per known field. Your code assembles the returned values into the cart.

Finding an unknown number of items with a loop

The number of ordered items is not known in advance. Each request asks which remaining menu item appears first in the order. The loop in your code then:
  1. saves the selected item;
  2. removes it from the next request’s options; and
  3. sends the full order again with the shorter option list.
A Choice question must select an option, so every request also includes nothing_else. That option tells the loop to stop when the order contains no remaining menu item.

Filling the known fields

After the item loop, the application knows which schema applies to each item. The latte schema has size and milk fields. The application sends both field questions to Jev in one request. The muffin has no fields, so it needs no field request.

Setup

then set TYPESAFE_API_KEY. Every API call is cached in json_cache.json. Download it into the folder you run this code from to replay the published numbers instead of calling the API, or leave it out to run everything live. Numbers below came from jev-1.14.0 on 2026-10-29.

Creating the menu

The menu has four items, and only the latte has fields. Each item’s description carries the words a customer would use to order it. Jev matches the order against these descriptions. fields is the item’s own schema. Each field is a list of allowed values, and those values are the options of that field’s Choice question.

Finding the items in the order

Before each request, the loop builds a fresh option set from the items not yet found and adds the nothing_else sentinel. The order is the request’s state, and the question changes from one request to the next. The loop stops when nothing_else is selected. The loop also caps its requests, so a bad answer can never make it loop forever. It ends when the sentinel is selected, the menu runs out, or the cap is reached.
On this order, the first two item requests each found an item. The third selected the sentinel and ended the loop. Because each found item leaves the option list, the loop finds each menu item at most once. The cart also has no quantity field, so an order for “two flat whites” still produces one latte. To handle quantities, add a quantity field to each item’s schema, with values such as one, two and three.

Filling in a found item’s fields

For each found item, we build one Choice question per known field and send them together in one system_one call against the same order. This is the fan-out pattern. Each field question also includes unspecified, so a field the customer did not mention gets that option instead of a forced concrete value. An item with no fields skips the call entirely.

The assembled cart

This step makes no TypeSafe calls. It prints the cart assembled from the single-value answers collected above.

Try it in the playground

The link below holds the first item-finding request: the full order as the state, and one Choice question over the four menu items plus nothing_else. The loop above repeats that request, each time without the item it just found. Edit the order there and the answer changes with it.
Open the first item-finding request in the TypeSafe playground →

What’s next

  • Primitives is the reference for the question types and the fields each answer carries.
  • The parallel questions cookbook measures what sending the field questions in one request saves against asking them one at a time.
  • The function calling cookbook turns a sentence into a call to one of your own functions the same way: one Choice question picks the function, and one per argument fills its values. It handles an argument the user didn’t mention with a separate yes/no question instead of an unspecified option.
  • Confidence covers reading a confidence value as a signal.