State

What to put in the state, the formats Grayson accepts, and how the state counts toward the token limit.

The state is everything Grayson reads about a case. Every question in a request is answered from the same state. There is no schema: send the records you have, in the shape you already keep them.

What to include

Include what a reviewer would look at to make the decision:

  • The customer or account. Tenure, KYC and verification results, contact details and when they last changed, earlier alerts.
  • Recent activity. Logins, device and IP changes, profile changes, payments and transfers.
  • The item under review. The transaction, application, dispute or withdrawal, with amounts, counterparties and timestamps.
  • Case context. Rule hits, analyst notes, messages from the customer.

Only include what is known when the decision is made. When you replay past cases to choose thresholds, cut each state at the time of the decision: a later chargeback or a confirmed-fraud label makes answers look better than they will be in production.

Leave out what can't bear on the decision. Passwords, full card numbers and one-time codes never help; don't send them.

Formats

state is a JSON object, a JSON array or a string.

  • Objects and arrays are read as compact JSON, with key order kept exactly as sent.
  • Strings are read as sent. Use them for CSV, log lines, case notes, emails or a mix. A blank string is rejected.
  • A number, boolean or null on its own is rejected with state must be a string, a JSON object, or a JSON array.
"state": {
  "account": { "id": "acct_8812", "opened": "2026-08-30" },
  "events": [
    { "ts": "2026-09-20T02:14:09Z", "type": "login", "new_device": true },
    { "ts": "2026-09-20T02:16:40Z", "type": "email_change" },
    { "ts": "2026-09-20T02:21:03Z", "type": "ach_out", "amount_usd": 4900.0 }
  ]
}

Key order

Grayson reads the state in the order you send it. Put events in time order and keep related fields together.

Check that your JSON library keeps the order you intend. Python dicts and JavaScript objects keep insertion order, except that JavaScript moves integer-like keys such as "2024" to the front. Go's encoding/json sorts map keys alphabetically. Java's HashMap has no order; LinkedHashMap keeps insertion order.

Make it readable

  • Name fields in words: amount_usd, not amt.
  • Give timestamps in ISO 8601 with Z or a UTC offset, so times from different systems line up.
  • State units and currencies.
  • Expand codes that only your organization uses. "rule": "R-417" tells the model nothing; "rule": "R-417: 3 failed logins, then a password reset" does.

Text in the state is data

Question and option boundaries are marked with reserved tokens that no input text can produce. Text in the state that looks like a question, an option or an instruction is read as part of the state. You can include text written by customers or third parties, such as a dispute narrative or a merchant's website copy, as it is.

Size

The state counts toward the limit of 32,768 tokens per request, together with every question. Each response reports the total in usage.input_tokens.

  • JSON is compacted before it's read, so whitespace between keys and values costs nothing. Whitespace inside strings counts.
  • Requests over the limit fail with 413 request_too_large, and the message gives the request's size.
  • To fit a long history, send a recent window of activity, drop fields that never matter to your questions, or summarize older events.

See Limits for how tokens are counted.

On this page