Let’s clear up a common misconception first: the OpenAI API doesn’t expose a built-in switch for “narrative type = executive summary / table / bullets / etc.” What it does give you is a reliable way to force the model to return structured JSON (and therefore predictable narrative shapes) using Structured Outputs (JSON Schema). In the Responses API, you do this with text.format set to json_schema.

That means “narrative types” are effectively contracts you define—and then your Salesforce UI (LWC) can render each section exactly how you want, every time.


The foundation: one request pattern, many narrative shapes

Below is a minimal Responses API pattern you can reuse. The only thing you’ll typically change is the schema (and the instruction inside your prompt telling the model what each field means).

{
  "model": "gpt-5",
  "input": [
    {
      "role": "system",
      "content": [
        { "type": "text", "text": "You are a precise enterprise analyst. Return only JSON that matches the schema." }
      ]
    },
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "Analyze the dataset and return the requested narrative fields." }
      ]
    }
  ],
  "text": {
    "format": {
      "type": "json_schema",
      "name": "NarrativeEnvelope",
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "narrative": { "type": "string" }
        },
        "required": ["narrative"]
      }
    }
  }
}

Why this matters:

  • text.format in Responses is the supported way to request structured JSON output.
  • JSON Schema Structured Outputs is explicitly documented as the modern, schema-adherent evolution beyond “JSON mode”.

Narrative types you can (and should) standardize

There are multiple types of narrative structures that you can request in your transactions. Here are some of the more popular and predictable ones. Each “type” below includes:

  1. what it provides
  2. a JSON Schema snippet showing the fields you’d add to your envelope

You can combine multiple types in one schema if you want a single call to return several formats at once.


1) Freeform narrative

What it provides: A readable paragraph-style explanation intended for humans (best for emails, chatter posts, case notes).

{
  "properties": {
    "narrative": { "type": "string", "description": "Human-readable narrative summary." }
  },
  "required": ["narrative"]
}


2) Executive summary

What it provides: A tight, leadership-friendly summary that cuts out implementation detail.

{
  "properties": {
    "executiveSummary": { "type": "string", "description": "High-level summary for executives (short)." }
  },
  "required": ["executiveSummary"]
}


3) TL;DR

What it provides: Ultra-short “top line” output (great for list views, mobile, or preview cards).

{
  "properties": {
    "tldr": { "type": "string", "description": "1–2 sentence TL;DR." }
  },
  "required": ["tldr"]
}


4) Key points (bullets)

What it provides: Scannable bullet list (perfect for Salesforce UI sections).

{
  "properties": {
    "keyPoints": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Bullet key points (each item should stand alone)."
    }
  },
  "required": ["keyPoints"]
}


5) Action items

What it provides: Operational next steps—what someone should do.

{
  "properties": {
    "actionItems": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "action": { "type": "string" },
          "ownerRole": { "type": "string" },
          "priority": { "type": "string", "enum": ["Low", "Medium", "High", "Critical"] }
        },
        "required": ["action", "priority"]
      }
    }
  },
  "required": ["actionItems"]
}


6) Risks & assumptions

What it provides: Explicit risk callouts and what the model is assuming (useful for “strict execution” patterns).

{
  "properties": {
    "risks": { "type": "array", "items": { "type": "string" } },
    "assumptions": { "type": "array", "items": { "type": "string" } }
  },
  "required": ["risks", "assumptions"]
}


7) Recommendation with rationale

What it provides: Clear recommendation plus the reasoning, without burying it in prose.

{
  "properties": {
    "recommendation": { "type": "string" },
    "rationale": { "type": "array", "items": { "type": "string" } }
  },
  "required": ["recommendation", "rationale"]
}


8) Tabular narrative (rows/columns)

What it provides: A UI-ready table structure—ideal for LWC datatables.

{
  "properties": {
    "table": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "columns": { "type": "array", "items": { "type": "string" } },
        "rows": {
          "type": "array",
          "items": {
            "type": "object",
            "description": "Each row is a map of column name -> value.",
            "additionalProperties": { "type": "string" }
          }
        }
      },
      "required": ["columns", "rows"]
    }
  },
  "required": ["table"]
}

(You can also lock row shape harder by defining explicit properties per column, but the above is flexible when columns vary by prompt.)


9) Comparison/decision matrix

What it provides: Options compared on consistent criteria—great for architecture choices (Named Credentials patterns, integration styles, etc.).

{
  "properties": {
    "decisionMatrix": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "option": { "type": "string" },
          "pros": { "type": "array", "items": { "type": "string" } },
          "cons": { "type": "array", "items": { "type": "string" } },
          "score": { "type": "number", "minimum": 0, "maximum": 10 }
        },
        "required": ["option", "pros", "cons"]
      }
    }
  },
  "required": ["decisionMatrix"]
}


10) FAQ output

What it provides: Pre-formatted Q&A—excellent for Knowledge Articles, enablement docs, or help text in your managed package.

{
  "properties": {
    "faq": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "q": { "type": "string" },
          "a": { "type": "string" }
        },
        "required": ["q", "a"]
      }
    }
  },
  "required": ["faq"]
}


11) Timeline / sequence

What it provides: Ordered steps with dates or relative sequencing (useful for project execution narratives).

{
  "properties": {
    "timeline": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "step": { "type": "integer", "minimum": 1 },
          "label": { "type": "string" },
          "when": { "type": "string", "description": "Date or relative timing (e.g., 'Week 2')." }
        },
        "required": ["step", "label"]
      }
    }
  },
  "required": ["timeline"]
}


12) Sources / citations

What it provides: A structured place to put citations when you’re using web-enabled retrieval in your own app flow (or when you’re feeding sources to the model yourself).

{
  "properties": {
    "sources": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": { "type": "string" },
          "url": { "type": "string" },
          "note": { "type": "string" }
        },
        "required": ["title", "url"]
      }
    }
  },
  "required": ["sources"]
}

(If your workflow supports a “CANNOT BE VERIFIED” discipline, this is where you keep your receipts.)


A practical “all-in-one” envelope (what I recommend for Salesforce UIs)

If you want one call to drive multiple UI panels (Summary tab, Key Points tab, Table tab, Sources tab), define one schema that includes multiple narrative shapes:

{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "tldr": { "type": "string" },
    "executiveSummary": { "type": "string" },
    "narrative": { "type": "string" },
    "keyPoints": { "type": "array", "items": { "type": "string" } },
    "table": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "columns": { "type": "array", "items": { "type": "string" } },
        "rows": { "type": "array", "items": { "type": "object", "additionalProperties": { "type": "string" } } }
      },
      "required": ["columns", "rows"]
    },
    "actionItems": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "action": { "type": "string" },
          "priority": { "type": "string", "enum": ["Low", "Medium", "High", "Critical"] }
        },
        "required": ["action", "priority"]
      }
    },
    "sources": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": { "type": "string" },
          "url": { "type": "string" }
        },
        "required": ["title", "url"]
      }
    }
  },
  "required": ["tldr", "executiveSummary", "narrative", "keyPoints"]
}

This is the pattern that plays nicest with:

  • a single persisted “AI_Response__c” record per run
  • multiple LWC renderers
  • deterministic parsing (no brittle regex on prose)
  • clean email templates (choose which fields you include)

Narrative types, token usage, and why max_tokens should never be optional

Here’s the part that bites people in production: every narrative type has a very different token profile, and if you don’t explicitly control max_tokens. The model will happily burn your quota trying to be helpful.

The OpenAI API does exactly what you ask—not what you intend.


How narrative shape impacts token consumption

At a high level, token usage is driven by three things:

  1. Field count (number of schema properties)
  2. Field verbosity (freeform text vs constrained lists)
  3. Row cardinality (tables, timelines, comparisons)

Below is how each narrative type typically behaves.


Freeform narrative

Token impact: High
Why: Long, natural language paragraphs expand quickly—especially when the model explains reasoning or context.

  • Easy to overrun limits if the prompt is open-ended
  • Highly sensitive to vague instructions (“explain”, “describe”, “analyze”)

Guidance:

  • Always pair with a hard max_tokens
  • Add length constraints in the prompt (“2–3 paragraphs max”)

Executive summary

Token impact: Medium
Why: Still prose, but constrained by intent.

Guidance:

  • Safe when explicitly scoped (“5–7 sentences”)
  • Cheap relative to full narrative, expensive relative to bullets

TL;DR

Token impact: Low
Why: One or two sentences, minimal expansion risk.

Guidance:

  • Ideal for list views, previews, and mobile
  • Almost impossible to blow token budgets unless bundled with other types

Key points (bullets)

Token impact: Low–Medium
Why: Arrays of short strings are token-efficient if you cap the count.

Risk:

  • “List all key points” + large datasets = silent token creep

Guidance:

  • Explicitly limit bullet count (“max 5 bullets”)

Action items

Token impact: Medium
Why: Structured objects help, but each item still contains prose.

Guidance:

  • Limit number of actions
  • Keep enums tight (priority, status) to prevent verbose wording

Risks & assumptions

Token impact: Medium
Why: Models tend to enumerate aggressively unless told otherwise.

Guidance:

  • Specify max entries (“no more than 3 risks”)
  • This is especially important in “strict execution” modes

Recommendation + rationale

Token impact: High
Why: The rationale is where tokens explode—models love explaining themselves.

Guidance:

  • Cap rationale bullets
  • Consider separating recommendation (short) from rationale (optional)

Tabular narrative

Token impact: Very High (dataset dependent)
Why: Rows × columns × string values adds up fast.

This is the number one source of runaway token usage in Salesforce + OpenAI integrations.

Guidance:

  • Always chunk datasets before calling the API
  • Enforce row limits in the prompt (“top 10 rows only”)
  • Use tables only when the UI truly needs them

Comparison / decision matrix

Token impact: Medium–High
Why: Each option carries multiple arrays (pros, cons, score).

Guidance:

  • Limit option count
  • Avoid nested explanations inside pros/cons

FAQ

Token impact: Medium
Why: Q&A pairs double the prose surface area.

Guidance:

  • Cap number of questions
  • Keep answers short and factual

Timeline / sequence

Token impact: Low–Medium
Why: Ordered, repeatable structure keeps verbosity down.

Guidance:

  • Prefer this over prose when describing process flows or execution steps

Sources / citations

Token impact: Low (usually)
Why: URLs and titles are token-light.

Caveat:

  • If you ask the model to explain each source, costs climb quickly

Why max_tokens must be explicitly set

In the Responses API, output tokens are not implicitly capped in a way that protects you from poorly scoped prompts. If your schema allows it—and your prompt invites it—the model will generate until it hits internal limits.

That’s how you get:

  • Partial JSON (cut off mid-object)
  • Incomplete tables
  • Salesforce callout timeouts
  • Unexpected cost spikes

Hard rule for production systems

Every OpenAI call must specify max_tokens, no exceptions.

Example:

{
  "model": "gpt-5",
  "max_tokens": 1200,
  "input": [...],
  "text": { "format": { "type": "json_schema", "schema": { /* … */ } } }
}


Practical guidance for architects

  • One call, many narratives is fine — only if you budget tokens intentionally
  • Use short narratives for UI, long narratives for offline artifacts (email, PDFs)
  • Tables and rationales should be opt-in, not default
  • Treat max_tokens like a governor limit, not a suggestion

In short:
Narrative design is cost design.
If you don’t control shape, size, and limits, OpenAI will control your bill—and your timeout logs will show it.

Closing take

If you’re building Salesforce + OpenAI features, stop thinking in “prompt returns text” and start thinking in “prompt returns a schema contract.” Once you do that, “narrative types” become composable UI building blocks—consistent across workflows, steps, and personas—without sacrificing flexibility.

We would love to hear your comments!

Trending