Writing prompts
There is no wrong way to ask Misata for data, but there are three styles it recognizes, and each comes with a different guarantee. This page defines all of them, plus every edge case we know about and exactly what happens in each. If your prompt ever produces something you did not ask for, that is a bug; tell us.
The three prompt styles
1. A plain-English story
A SaaS company with 1,000 users and monthly subscriptions. MRR rises from $50k in January to $200k in December.
The guarantee: numbers you name are honored exactly. Row counts ("1,000 users"), trends ("rises from $50k to $200k"), and rates ("a 2% fraud rate") become enforced targets, not suggestions. Everything you did not specify gets realistic defaults: table structure, distributions, value pools, all of which you can refine on the canvas afterwards.
What helps: name the numbers you care about. "An ecommerce store" works, but "an ecommerce store with 12,000 customers and a December peak" gives the engine something to be exact about.
2. A structured spec
Write the schema out in prose, the way you would hand it to a colleague:
Table 1: customers
Rows: exactly 500
Columns:
customer_id
company_name
plan_tier
Table 2: orders
Rows: exactly 3000
Columns:
order_id
customer_id
amount
status
Rules:
customer_id must match values from customers table.
Status must only be:
Paid
Pending
Refunded
The guarantee: the spec is a contract, parsed by code, not interpreted by a model. Exactly the tables you listed and no others. Exactly 500 means exactly 500. Foreign key rules ("must match values from") produce zero orphans, verified on every run. "Must only be" lists are the complete value pool. "Must be 1 to 5" is a hard bound.
Both FK syntaxes work: customer_id must match values from customers table
and customers.customer_id -> orders.customer_id.
When you use an AI provider, the model still contributes, but only inside the contract: it picks realistic distributions for unspecified columns and translates couplings like "sentiment must match rating" into row-level rules. It cannot change your tables, counts, keys, or value lists no matter what it answers.
3. Your own text templates
For description or notes columns, give templates with {placeholder} slots
and the pools to fill them from:
Generate ticket_description using template-based text with variables:
connector: Salesforce, Snowflake, HubSpot
error_code: AUTH-403, TIMEOUT-001, E-4001
team: analytics, engineering, sales
Example format:
"Salesforce integration stopped syncing data. Error AUTH-403 appears in
logs. Analytics team cannot access customer data."
The guarantee: your templates and pools are used verbatim. Each row's slots are filled from your pools, deterministically from the seed. When templates are grouped by category, each row draws from its own category's templates, so an Integration sentence never lands on a Bug ticket.
One authoring tip: keep pool values grammatically interchangeable. A
timeframe pool should hold durations only ("2 hours", "3 days"), because
a point like "yesterday" renders as "about yesterday ago" inside a
"{timeframe} ago" template.
Every edge case, defined
| You give it | What happens |
|---|---|
| A very short prompt ("a bookshop") | Works. A known domain gets its curated schema; an unknown one is composed structurally. You refine on the canvas. |
| A very long prompt | Works. Long structured specs are parsed by code, so there is no length limit and no model truncation. No character cap exists or is needed. |
| Exact row counts ("exactly 500") | Exact. Not approximately, not "about". |
| FK rules, either syntax | Enforced with zero orphans, verified each run. |
| "Must only be" value lists | The complete pool. Nothing outside it appears. |
| Numeric ranges ("1 to 5") | Hard bounds. |
| Templates with {placeholders} | Filled per row from your pools, verbatim. A placeholder with no declared pool is left visible and warned about, never silently guessed. |
| A rule the engine cannot enforce | Reported by name in "what Misata understood", never silently approximated. Most can then be wired on the canvas. |
| An impossible declaration (a 2% rate over 4,824 rows) | The engine warns and tells you what it sacrificed, or drops the artifact rather than shipping a wrong one. See When Misata refuses. |
A pasted schema.prisma or dbt schema.yml | Use the CLI instead: misata prisma-seed and misata dbt-seed --from-project translate them natively. |
| A question, or a non-data request | The parser will do its best to find a dataset in it; if the canvas comes back odd, that is why. Describe data, not tasks. |
| No AI key configured | Everything above still works. The keyless parser handles stories and specs; the model only ever adds refinement, never correctness. |
What the model does and does not do
When an AI provider is configured, the model designs and refines schemas. It never generates the data itself. Generation is a deterministic engine, which is why counts can be exact, keys can be guaranteed, and the same seed returns the same bytes forever. If the model is down, times out, or answers badly, the deterministic path ships alone; you lose polish, never correctness.
Reading "what Misata understood"
After you submit a prompt with contractual instructions, the studio shows a summary before opening the canvas: which tables and row counts were locked, how many FK and value-list rules were enforced, and, in a separate list, any rules that could not be translated. That last list is deliberate. We would rather tell you "this rule was not applied" than hand you data that quietly pretends it was.