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.formatin 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:
- what it provides
- 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:
- Field count (number of schema properties)
- Field verbosity (freeform text vs constrained lists)
- 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_tokenslike 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!