Structured output data grid

Structured output data grid for internal AI assistants

Structured output is valuable when the assistant answer needs to become an inspectable, editable, auditable grid.

Open AI Schema docs See AI table output

Create a stable grid response

Start with the Ace Grid schema version and result kind. Give every column a stable key, every row a stable ID, and every value an explicit type. Keep citations, validation issues, metadata, and allowed actions beside the data they describe. Application-specific fields such as a result ID or generation timestamp belong in an outer wrapper, not inside the Ace Grid contract.

Return errors people can act on

When validation fails, return the exact field path, a machine-readable error code, and a plain-language message. Keep the original response in protected diagnostics so developers can investigate without exposing sensitive data to users. Schema validation confirms structure; the application must still check source accuracy, freshness, permissions, and business rules.

Keep generated actions constrained

An AI result may suggest an allowed operation and reference stable row IDs, but it must never contain executable code. Before changing data, the server checks the current user, record version, and operation policy again. It then applies the change, records an audit event, and returns a result for each affected row.

Recover safely from partial or old results

Decide in advance what happens when a result uses an older schema, includes an unsupported action, omits citations, or contains malformed rows. Reject unsafe portions instead of guessing what the model intended. When possible, show a readable text fallback and preserve enough diagnostic context for support teams to identify the failure.

Set practical payload limits

Set maximum counts for rows, columns, citations, commands, text length, and nested values. Validate those limits before creating expensive cell renderers or restoring grid state. A payload can be structurally valid and still consume too much memory or produce an unusable response, so large results should use a server-backed query or paged reference.

Test every supported schema version

Keep fixtures for the current schema, each supported older version, an unknown future version, malformed documents, and deprecated fields. Define whether older results are migrated, shown read-only, or rejected. Compatibility rules should be deterministic and covered by tests rather than inferred at runtime.

Reject unsafe shape before rendering

Validate before rendering expensive cells, applying view state, or showing privileged actions. Reject unknown commands, excessive payloads, duplicate IDs, missing row identity, and unsafe metadata, or downgrade the result to a safe fallback. A valid-looking JSON object remains untrusted external input until it passes policy checks.

Use fixtures for every schema state

Create fixtures for valid view, valid AI result, missing version, unsupported kind, duplicate row IDs, invalid columns, unsafe commands, oversized payload, missing provenance, and deprecated fields. Fixtures make the schema contract testable and help prevent regressions.

Separate provenance from truth

Provenance tells users where a value came from. It does not prove the value is correct, current, or authorized. Verify sensitive facts and permissions against authoritative systems before allowing changes that affect business data.

Separate provenance, validation, and authorization

Provenance records where a value originated. Schema validation confirms the result shape. Authorization determines whether the current user may view or change the referenced records. These checks answer different questions and should produce separate UI states and audit events. Passing one check must never be treated as proof that the others passed.

A versioned grid result with provenance and validation

import {
  createGridAiResultSchema,
  validateGridSchemaDocument,
} from "@ace-grid/schema-ai";

const result = createGridAiResultSchema({
  kind: "render_table",
  title: "Accounts requiring review",
  view: {
    version: 1,
    kind: "view",
    data: {
      columnDefs: [
        { key: "account", title: "Account" },
        { key: "risk", title: "Risk", type: "number" },
      ],
      rows: assistantRows,
    },
  },
  provenance: {
    source: "ai",
    provider: "internal-assistant",
    generatedAt: new Date().toISOString(),
    citations: sourceRecords.map((record) => ({
      label: record.title,
      url: record.url,
    })),
  },
});

const validation = validateGridSchemaDocument(result);

if (!validation.valid) {
  return { status: "rejected", issues: validation.issues };
}

return { status: "ready", result: validation.value };

Sources