Configure the form
In code
If you would rather keep the form next to the code that uses it, you define it as one plain object shipped with your app — the form object: the form's identity (key, version, language), its fields built with FormField, and optionally prompts and models. Speechineer records it in your workspace the first time a session starts, so it is attributed and limited like any other form.
One object describes the whole form — its identity, its fields, its prompts and its models. Each property has its own section below:
Note
Use the switch to compare an example form as your codebase holds it today with the form object Speechineer expects for it, imported for your framework:
import { FormField } from "@speechineer/react"; const bookingForm = (vehicles: string[]) => ({ source: "inline", key: "service-booking", // your stable identifier version: "1", // bump when the fields change language: "en", // the language the prompts are written in fields: [ FormField.text("customer_name", "Extract the customer's full name."), FormField.email("email", "Extract the email address, spelled out or spoken."), FormField.date("drop_off", "Extract the drop-off date. Resolve relative dates such as 'next Tuesday'."), FormField.select("vehicle", "Extract which of the customer's vehicles this is about.", vehicles), FormField.multiselect("services", "Extract every requested service.", ["oil_change", "brakes", "inspection"]), FormField.slider("urgency", "Rate how urgent this is from 1 to 5.", [1, 5]), FormField.checkbox("loaner_car", "True if they ask for a loaner car."), ], prompts: { // optional, one slot per step transcription: "Garage intake: expect car makes, models and part names.", extraction: "Values are for a service booking; the caller is the vehicle owner.", }, models: { transcription: "fast-en" }, // optional, by the key in your workspace}); const form = bookingForm(await loadVehiclesFromDb()); // options can come from your data at runtime export function BookingForm({ vehicles }: { vehicles: string[] }) { return ( <form onSubmit={save}> <label>Full name <input name="customer_name" /></label> <label>Email <input name="email" type="email" /></label> <label>Drop-off <input name="drop_off" type="date" /></label> <label>Vehicle <select name="vehicle">{vehicles.map((v) => <option key={v}>{v}</option>)}</select> </label> <label>Services <select name="services" multiple> <option>oil_change</option><option>brakes</option><option>inspection</option> </select> </label> <label>Urgency <input name="urgency" type="range" min="1" max="5" /></label> <label>Loaner car <input name="loaner_car" type="checkbox" /></label> </form> );}added · changed — everything else is untouched.
import { FormField } from "@speechineer/angular"; const bookingForm = (vehicles: string[]) => ({ source: "inline", key: "service-booking", // your stable identifier version: "1", // bump when the fields change language: "en", // the language the prompts are written in fields: [ FormField.text("customer_name", "Extract the customer's full name."), FormField.email("email", "Extract the email address, spelled out or spoken."), FormField.date("drop_off", "Extract the drop-off date. Resolve relative dates such as 'next Tuesday'."), FormField.select("vehicle", "Extract which of the customer's vehicles this is about.", vehicles), FormField.multiselect("services", "Extract every requested service.", ["oil_change", "brakes", "inspection"]), FormField.slider("urgency", "Rate how urgent this is from 1 to 5.", [1, 5]), FormField.checkbox("loaner_car", "True if they ask for a loaner car."), ], prompts: { // optional, one slot per step transcription: "Garage intake: expect car makes, models and part names.", extraction: "Values are for a service booking; the caller is the vehicle owner.", }, models: { transcription: "fast-en" }, // optional, by the key in your workspace}); const form = bookingForm(await loadVehiclesFromDb()); // options can come from your data at runtime @Component({ selector: "booking-form", templateUrl: "./booking-form.html" })export class BookingFormComponent { @Input() vehicles: string[] = []; form = new FormGroup({ customer_name: new FormControl(""), email: new FormControl(""), drop_off: new FormControl(""), vehicle: new FormControl(""), services: new FormControl<string[]>([]), urgency: new FormControl(3), loaner_car: new FormControl(false), });}added · changed — everything else is untouched.
<form id="booking"> <label>Full name <input name="customer_name" /></label> <label>Email <input name="email" type="email" /></label> <label>Drop-off <input name="drop_off" type="date" /></label> <label>Vehicle <select name="vehicle"></select></label> <label>Services <select name="services" multiple> <option>oil_change</option><option>brakes</option><option>inspection</option> </select> </label> <label>Urgency <input name="urgency" type="range" min="1" max="5" /></label> <label>Loaner car <input name="loaner_car" type="checkbox" /></label></form> <script type="module"> import { FormField } from "@speechineer/js"; const bookingForm = (vehicles) => ({ source: "inline", key: "service-booking", // your stable identifier version: "1", // bump when the fields change language: "en", // the language the prompts are written in fields: [ FormField.text("customer_name", "Extract the customer's full name."), FormField.email("email", "Extract the email address, spelled out or spoken."), FormField.date("drop_off", "Extract the drop-off date. Resolve relative dates such as 'next Tuesday'."), FormField.select("vehicle", "Extract which of the customer's vehicles this is about.", vehicles), FormField.multiselect("services", "Extract every requested service.", ["oil_change", "brakes", "inspection"]), FormField.slider("urgency", "Rate how urgent this is from 1 to 5.", [1, 5]), FormField.checkbox("loaner_car", "True if they ask for a loaner car."), ], prompts: { // optional, one slot per step transcription: "Garage intake: expect car makes, models and part names.", extraction: "Values are for a service booking; the caller is the vehicle owner.", }, models: { transcription: "fast-en" }, // optional, by the key in your workspace }); const form = bookingForm(await loadVehiclesFromDb()); // options can come from your data at runtime</script>added · changed — everything else is untouched.
source
Always "inline" here: it says the definition lives in your code. With "workspace" the same object would instead name a form configured in your workspace — that path is In the workspace.
key
Your own stable identifier for the form. Speechineer records the form under it the first time a session starts, so it appears in your workspace and its usage is attributed and limited like any workspace form. Choose it once and keep it — a new key is a new form.
version
The version string is what Speechineer records the shape under, and usage is attributed per key + version: bump it when the fields change and the numbers of the old and the new shape stay apart. Pin it in code like any other constant.
language
The language your prompts are written in. To serve several, ship one form object per language — identical field ids, translated prompts — and pick the object by the user's language before creating the session.
Note
spokenLanguage option — optional, and independent of the form's language (Integrate the SDK › Implementation › Wire up the voice session › spokenLanguage).Note
version and what follows the language is the same split as for a workspace form — use it to decide when to bump the version and when to ship another language object:| Differs per version | Differs per language | |
|---|---|---|
| The fields — ids, types, options, ranges | ✓ | ✗ |
| The field prompts | ✓ | ✓ |
| The transcription and extraction system prompts | ✓ | ✓ |
| The model configuration | ✓ | ✗ |
| The list of supported languages | ✓ | ✗ |
| Draft or published | ✓ | ✗ |
fields
The fields to extract, one per input of your form, built with FormField. Each entry is a field object, built with one FormField factory call: the field id, the prompt, and — for choice and range fields — the configuration. The id is the same contract as everywhere: values come back keyed by it, so use the identifiers your form state already has, start with a letter, and keep them unique.
Types
You get the same fourteen types as in the workspace, with one factory per type. The factory validates the configuration, so an empty option list fails at build time rather than at session start.
| Type / factory | Holds | Required configuration |
|---|---|---|
| FormField.text(id, prompt) | a short free-text value — a name, a city | — |
| FormField.textarea(id, prompt) | longer free text — notes, descriptions | — |
| FormField.email(id, prompt) | an email address | — |
| FormField.phone(id, prompt) | a phone number | — |
| FormField.url(id, prompt) | a link | — |
| FormField.integer(id, prompt) | a whole number — age, count, years | — |
| FormField.float(id, prompt) | a decimal — amount, weight, temperature | — |
| FormField.checkbox(id, prompt) | yes or no — consent, an opt-in | — |
| FormField.date(id, prompt) | a calendar date | — |
| FormField.time(id, prompt) | a time of day | — |
| FormField.datetime(id, prompt) | a date with a time | — |
| FormField.select(id, prompt, options) | one value from a fixed list | options — at least one |
| FormField.multiselect(id, prompt, options) | any number of values from a fixed list | options — at least one |
| FormField.slider(id, prompt, [min, max]) | a number on a bounded scale | range — [min, max] |
Note
Field prompts
One prompt per field — what to pull out and how to resolve what a speaker actually says. From the sample form's fields:
full_name— "Ask for the patient's full legal name."date_of_birth— "Capture the date of birth in ISO format."severity— "Rate severity from 1 to 10."consent— "Confirm the patient consents to treatment."
Tip
Note
prompts
Optional form-level guidance, one slot per step — omit a slot to use the default. The two slots are the same system prompts you would write in the workspace:
Transcription system prompt
How speech is written down in the first place: vocabulary, domain, names to expect. When the transcript is right, everything downstream gets easier.
- "Transcribe the patient's speech verbatim in English."
Extraction system prompt
Context that applies to every field: what the form is for, how strict to be, what to leave empty.
- "Extract structured intake fields from the transcript. Be concise and accurate."
In code, both ride in the prompts object — the example at the top of the page carries them in place.
models
Optional model pins per step — transcription and extraction. The codes you can pass are exactly the keys the two model pickers list in the Engineer tab of your workspace (Configure the form › In the workspace › Engineer the extraction › Select the model) — copy a key as it appears there. Omit a step and it runs on the workspace default.
Switching is worth it when something specific matters: accuracy on your domain's vocabulary, latency, price, or where the audio and text are processed — each entry shows who develops the model, who serves it, and where it is hosted.
Additional information in