Skip to main content
Every calculation is submitted as a prompt in one input format, chosen per request. TrueMath accepts three input formats:
  • Natural language — prose describing what you want.
  • Structured text — explicit key: value lines.
  • JSON — a structured object carrying the same values as structured text. Available over the API only.
Natural language and structured text apply the same way in the Playground and over the API — only the surface differs. JSON is accepted over the API only. For how natural language fits into TrueMath’s use of language models, see How TrueMath fits with LLMs. A completed calculation returns its full result, and a structured-text request also gets that result serialized back as structured text, so it round-trips: capture a result, change a value, and resubmit it. See Round-trip.

Natural language

Natural language is free-form prose. TrueMath uses a language model to parse your intent into the variables to set and the variable to solve for, then executes the calculation deterministically. Use it for exploration, or when you do not know a domain’s exact keys.
Because natural language must be interpreted, a request may be processed asynchronously — see In progress.

Structured text

Structured text is one instruction per line, in key: value form. It is precise and fast: there is no language to interpret, so the same input always produces the same request. Use it when you know the variables you want to set and the target you want to solve for.

Lines

Each line is one instruction:
  • <key>: <value> — set a variable. <key> is the variable’s key.
  • calculate: <key> [<unit>] — name the variable to solve for, optionally with the unit you want the result in (calculate: monthly_payment USD).
  • scenario: <selector> — choose the scenario to calculate against (see Scenarios).
  • # ... — a comment; the whole line is ignored.
calculate: and scenario: are optional. When omitted, they are inferred from the prior request in the conversation.

Values

Write a value the way you would by hand; the unit is part of the value (see Units and precision).
  • Numbers3000.54 or 3,000.54; thousands separators are optional.
  • Units inline30 yr, 5.2 m, 1500 USD; abbreviations or full names both work (yr or years, m or meters). See Units.
  • Currency — a leading $ is shorthand for USD: $1,000.00 is the same as 1000.00 USD.
  • Percent — a trailing % is converted to a rate: 6.5% becomes 0.065.
  • Dates, times, and durations7/21/2026, 2:30 PM, 90 min, today. See Dates, times, and durations.
Units are written plainly here — no backticks. Backticks are only needed when a unit appears in an activity equation, where it could otherwise be read as a variable name.

Dates, times, and durations

A variable typed as a duration, date, datetime, or time takes its value the way people write one, and TrueMath converts it to the count of seconds the variable stores. You never type seconds yourself. See Authoring dates and durations for what each kind holds. Month and weekday names are English. A named weekday is checked against the date rather than taken on trust, so Monday, July 21, 2026 is an error: that day is a Tuesday. Numeric dates are read month-first, matching how they render: 10/5/2026 is October 5th and 5/10/2026 is May 10th. A two-digit year reads 0049 as this century and 5099 as the last, so 1/1/49 is 2049 and 1/1/50 is 1950. Write the year in full for a value near that boundary — a birth date especially. A date with the year left out takes the current year, read in the same time zone as today (see Time zones). Feb 29 is a date in 2028 and an error in 2026. A value that names its own time unit is read as written. 90 min, 1.5 hr, and the compound 1 hr 30 min are quantities of time already, and are taken as they stand. These spellings work in natural language too. A date written the way you would say it — “what is the payoff if I close on July 21st?” — is read the same way as one typed into a field.

today and now

today and now name a moment rather than describing one. Either can be given as a value, and the moment used is the one the calculation runs at, in the caller’s own time zone:
Both are accepted wherever the variable can hold one: a date or datetime takes either, a time takes now, and a duration takes neither. For what each kind keeps, see today and now as defaults — the same rules apply to a value you supply and to a default an author sets. Nothing else is read this way. tomorrow and next Friday are not keywords.

One genuine ambiguity: the colon

22:47 is either 22 minutes 47 seconds or 22 hours 47 minutes, and the text alone does not distinguish them. The variable’s kind and format are what separate the two readings, so the same string lands on a different number:
A clock always fills hours-first, so 9:59 on a time or datetime is 9:59 AM whatever its format. For a duration, a third group states the reading outright — 0:22:47 is 22 minutes 47 seconds under any format — and a meridiem removes the ambiguity entirely. Because only the variable separates the two readings, a colon value given to an ordinary number variable is an error rather than a guess.

A value written as a date is read as one or refused

A value written as a date — three numeric groups on one separator, or a month name — is either read as a date or returned as input.invalid_prompt. This applies on any variable, not only one typed as a date or a duration, so a domain that predates those display types and holds its dates as plain numbers is covered too.

A table cell follows its column

Every rule above applies one level down inside a table. A table variable’s own display type is always table, so the kind and the format come from the cell’s column:
Two consequences are worth knowing:
  • A refused cell is named by its column'Date' cell '2/45/26' is not a valid date — because there is otherwise no way to identify which of forty values is wrong.
  • A flat table is one column of many rows, so every cell in it is read against the first column. Rows need their own brackets.

Tables

A table value uses semicolons to separate cells — never commas, which collide with decimal and thousands separators. A one-dimensional table is a list on a single line; brackets are optional:
Each cell may carry its own unit; an outer unit after the table fills only the cells that lack one — a cell’s own unit always wins:
Cells follow the same value conventions as scalars — [$3; $4] is two currency amounts, and [5%; 10%] becomes [0.05; 0.1]. A two-dimensional table is written as bracketed rows. Put the rows on one line, or one row per line:
See Tables for the underlying model and how tables are returned.

Scenarios

scenario: selects which scenario the calculation runs against:
  • scenario: new — start a new scenario.
  • scenario: last — the most recent scenario.
  • scenario: first — the first scenario in the conversation.
  • scenario: <index> — a specific scenario by its index.
When scenario: is omitted, the calculation continues the conversation’s current scenario.

Persistence

Values persist within a conversation. A variable you set but do not use in the current calculation is retained and stays available until a later calculation needs it. Likewise, when you omit calculate:, the prior target is retained. You can build up inputs across several requests and solve for different targets without restating values.

JSON

JSON expresses the same request as structured text, but as a structured object rather than key: value lines. It is available over the API only — set input_format to json and pass the object as a JSON string in prompt. Like structured text, it is precise and deterministic: there is no language to interpret, so the same input always produces the same request, and the calculation runs synchronously. The object has three fields:
  • inputs — an array of { "key", "value" } objects, one per variable to set. key is the variable’s key.
  • calculate{ "key", "unit" } naming the variable to solve for, with the optional unit you want the result in (null for the variable’s own unit). Set calculate to null to infer the target from the prior request in the conversation.
  • scenario — the scenario selector as a string: "new", "first", "last", or an index such as "2". Set it to null to continue the conversation’s current scenario.

Values in JSON

Each value is a string, following the same conventions as a structured-text value — the unit is included in the string:
  • Scalars and units"3000.54", "30 yr", "1500 USD". A leading $ is shorthand for USD ("$1,000.00"), and a trailing % becomes a rate ("6.5%"0.065).
  • A 1-D table — an array of cell strings: ["1500 USD", "1600 USD", "1700 USD"].
  • A 2-D table — an array of row arrays: [["1500", "12"], ["1600", "12"]].
Table cells are separate array elements, so JSON uses no semicolons or brackets within a value. Each cell carries its own unit; there is no outer unit that fills cells lacking one.

Nothing recognized

A request that resolves to no inputs and no calculation target — { "inputs": [], "calculate": null, "scenario": null } — is treated as “nothing recognized” and returns the input.llm_no_parsed_data error. This is the same signal used across every input format.

Round-trip

A completed calculation always returns its full result in the results object. A structured-text request additionally gets that result serialized back as a structured_text string, so you can capture it, change a value, and resubmit. See Calculate for the response fields each input format returns.