An answer, as returned · chart · chartjs

“A line chart of monthly active users in 2025, months Jan to Dec in calendar order on x (not alphabetical), users in thousands on y: 12.4, 13.1, 14.8, 15.2, 16.9, 18.3, 17.6, 18.9, 21.2, 22.8, 24.1, 26.5. Title: Monthly active users, 2025.”

Line chart of monthly active users through 2025, in thousands, rising from 12.4 in January to 26.5 in December

valid · chart@6baf09f0 · 1 credit · drawn by Chart.js from the returned config

{
  "type": "line",
  "data": {
    "labels": [
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "May",
      "Jun",
      "Jul",
      "Aug",
      "Sep",
      "Oct",
      "Nov",
      "Dec"
    ],
    "datasets": [
      {
        "type": "line",
        "fill": false,
        "pointRadius": 0,
        "data": [
          12.4,
          13.1,
          14.8,
          15.2,
          16.9,
          18.3,
          17.6,
          18.9,
          21.2,
          22.8,
          24.1,
          26.5
        ]
      }
    ]
  },
  "options": {
    "plugins": {
      "title": {
        "display": true,
        "text": "Monthly active users, 2025"
      },
      "legend": {
        "display": false
      }
    },
    "scales": {
      "x": {
        "type": "category",
        "title": {
          "display": true,
          "text": "date (month)"
        }
      },
      "y": {
        "type": "linear",
        "title": {
          "display": true,
          "text": "Users (thousands)"
        },
        "beginAtZero": true
      }
    }
  }
}

Technology

What you can count on.

You describe what you need. Forma hands it back only after it has passed a separate, versioned set of rules, or tells you why it could not.

01 Two halves, one verdict

Neuro-symbolic

Neural models are good with language and poor at guarantees; rules are the reverse. Forma gives each its half: neural models make sense of what you ask, and versioned symbolic rules, separate from whatever produced the answer, decide whether it stands. That is LLM output validation: a verdict on the output itself, not a score for how likely it is to be right.

How it's built

  1. 01
    Neural: understanding

    What you ask, in your own words: a chart of these numbers, a figure of this construction.

  2. 02
    Symbolic: deciding

    Versioned rules check the answer itself, and verified_by names the version it passed.

  3. 03
    Guardrails that refuse

    A request that cannot be met comes back invalid, with the reason. Over the API and MCP, a chart request without its values is refused with DATA_REQUIRED and not billed, by default.

02 You describe it

Ask

Describe what you want in plain language to one oracle, and optionally name an output format. You never send rules: deciding what satisfies a request is our side of the line.

How it's built

  1. 01
    Plain language

    Up to 4,000 characters, to the chart, vector-graphics or coverage-policy oracle.

  2. 02
    A format

    vega-lite, plotly, echarts, chartjs or gnuplot; tikz, metapost or pictex; lookup. Ask for one an oracle cannot produce and the refusal names the ones it can.

  3. 03
    Describe, don't place

    For figures: a midpoint, an intersection, a point along a ray, a tree from its structure. The coordinates are worked out for you.

03 The rules decide

Checked

A versioned set of rules, separate from whatever produced the answer, decides whether it passes. For figures, every property the figure states is verified, and a figure that fails one is refused. Each format refuses what it cannot express instead of approximating it.

How it's built

  1. 01
    Versioned rules

    The answer has to satisfy the version of the rules verified_by identifies.

  2. 02
    Stated checks

    Collinear, equidistant, and the rest, verified on the figure you receive.

04 A commitment, not a score

Verdict

valid with the artifact, invalid with the reason, or error if we failed, unbilled. Not a confidence number: a score lets every caller pick a different threshold, and then "verified" means something different in every integration.

How it's built

  1. 01
    valid

    Billed. result holds the artifact.

  2. 02
    invalid

    Billed. reason says what could not be met, and detail what to change.

  3. 03
    error

    Never billed, and still in your usage log.

05 Store it with the artifact

Citation

verified_by identifies the version of the rules the output was checked against, for example chart@6baf09f0. Store it with the artifact, and you can tell later which version of the rules each valid answer passed.

How it's built

  1. 01
    On every valid answer

    In the verified_by field, next to the result.

  2. 02
    A version, not the rules

    An identifier you can store and compare; the rules themselves stay ours.

06 Where you call it

Served

The same two calls, list the oracles and ask one, from an agent over MCP, from code over HTTP, and from CI.

How it's built

  1. 01
    MCP

    mcp.formalogic.io/mcp, OAuth sign-in, figures drawn inline.

  2. 02
    HTTP

    api.formalogic.io/v1 with an API key.

  3. 03
    CI

    A verdict is an exit code: invalid fails the build; after an error, run it again.