Modelsopenaigpt-6-luna
provideropenai /

gpt-6-luna

35 DZD in 175 DZD out 3.5 DZD cached/ 1M tokens

GPT-6 Luna is the tier OpenAI describe as handling clerical work — summarising, extracting, answering — and it carries the same 1.05-million-token window, the same reasoning range from none through max, and the same caching improvements as the model above it. Two things distinguish it. Its knowledge cutoff is more recent than the more expensive tier's, which inverts the usual assumption. And its output-token reduction over its predecessor exceeded the fifty percent headline, which matters most on exactly the high-volume work it was built for.

PublicJSONStreaming
gpt-6-luna
Capabilities
ToolsVisionReasoningStructured output
ArchitectureProprietary
Context Window1048576

GPT-6 Luna

The tier built for work you do thousands of times a day.


What OpenAI Call It

Clerical work: summarising, extracting, answering.

That is a precise description rather than a dismissive one. Those three verbs cover most of what a production system actually asks a model to do — turning a support thread into a summary, pulling fields out of a document, answering a question from supplied material.

And they share one property: volume. A summarisation endpoint runs thousands of times a day. An extraction pipeline runs once per document across an archive. An answering path runs once per user question.

Which is where the tier makes sense. On work that runs constantly, cost per call decides whether a feature ships at all — not how well it works, but whether it exists.

Where Luna sits

TierStated purpose
AstraThe most demanding and important projects
SolThe tier you can use far more often
LunaClerical work — summarising, extracting, answering

All three were trained with similar methods. OpenAI's framing is that the flagship's training came down the tiers rather than the capability being held back — which is the reason to test this model on work you assumed needed a larger one.

It is also the designated replacement for the previous generation on the free tiers in ChatGPT, which retires on 14 October 2026.


⚠️ It Knows More Than the Tier Above It

The inversion worth knowing before you assume otherwise.

ModelKnowledge cutoff
Sol20 April 2026
Luna18 May 2026

The cheaper model has the more recent knowledge.

Which breaks the usual heuristic. "Higher tier, better informed" does not hold in this release — if a task turns on something between those dates, this model knows about it and the more expensive one does not.

It is a narrow window, about a month, and it is a real one. On anything time-sensitive, the tier is not a proxy for recency here.


The Output Reduction Beat the Headline

OpenAI described the release with a fifty-percent price reduction. For this model, the output-token reduction was larger than that headline.

Why output tokens specifically matter on clerical work. A summarisation call sends a long document and returns a short summary — input-heavy, output-light. But an extraction pipeline running at scale generates a great deal of output in aggregate, and so does an answering endpoint.

And the tier's whole justification is aggregate cost. A disproportionate reduction on the output side is a larger change to the economics of high-volume work than the headline figure suggests.


The Cache Change

Shared with the tier above it, and it applies here too.

Reasoning effort and tool availability can be changed mid-conversation without breaking the cache.

Why that has mattered until now. Prompt caching recognises an unchanged prefix. Any change that alters the prefix invalidates the cache and the whole context is reprocessed at full cost — and reasoning effort and tool definitions were both in that category.

On this tier, the pattern it enables is different from the one above. Not "start cheap, escalate on a hard step" — the whole tier is the cheap configuration. Here it is "stay at none, raise effort only for the document that resists."

An extraction pipeline running at zero reasoning effort across a thousand documents, raising effort for the handful that return ambiguous results, now pays for that escalation without reprocessing what it already sent.

The rest of the caching changes

A 90% discount on cached reads.

Higher default hit rates.

Explicit cache breakpoints, marking where a stable prefix ends.

A prompt caching dashboard with diagnostics, turning cache behaviour into something you inspect rather than deduce.

On a high-volume tier these compound. A fixed system prompt and a fixed schema sent on every one of ten thousand calls is exactly the shape caching was built for.


⚠️ 1.05M Total, 922K Input

The same split as the tier above, and the same trap.

Total context1.05M tokens
Maximum input922K tokens
Maximum output128K tokens

Two separate caps that happen to sum to the headline figure. 922K is a hard ceiling on input, not the remainder after output; 128K is a hard ceiling on output, not a share you enlarge by sending less.

A request of 950,000 input tokens and 50,000 output tokens sums to under 1.05M and still fails.

And a million-token window on a clerical tier is unusual. Summarising a whole archive in one call, or extracting across a full document set rather than page by page, is a workload this tier would not normally support.


Reasoning: None Through Max

Reasoning runs from none through max, the same range as the tier above.

none is the default position for most work on this tier. Classification, extraction, and formatting have one correct answer and no reasoning to do — a deliberation pass adds latency and nothing else.

And having max available on the cheap tier is the interesting part. A document that resists extraction, a summary that keeps missing the point, an answer that needs the material reconciled rather than read — those can be handled here rather than routed to a different model.

The cache change is what makes that practical. Raising effort mid-run costs the tokens of the harder pass, not the tokens of the entire context again.


A Shorter Communication Style

Inherited from the flagship's revision, and described concretely: less jargon, fewer odd turns of phrase, slightly shorter answers, fewer preambles, less repetition of the prompt.

On this tier that is a direct cost saving rather than a stylistic preference. A summarisation endpoint that stops writing "Here is a summary of the document you provided:" before every summary saves those tokens ten thousand times a day.

And a model that repeats less of the prompt back produces output that is more nearly all content — which is what an extraction pipeline wanted in the first place.


Specifications

Model IDopenai/gpt-6-luna
Total context1.05M tokens
Maximum input922K tokens
Maximum output128K tokens
Reasoningnone through max
Knowledge cutoff18 May 2026
Input → outputText → text
WeightsClosed
DeveloperOpenAI

Tool support through the Responses API includes web search, file search, image generation, code execution, computer use, and MCP connections.


Capabilities

CapabilityValue
input_typestext
output_typestext
context_window1048576
max_input_tokens~922,000
max_output_tokens~128,000
reasoningnone through max
streamingSupported
tool_callingSupported
structured_outputSupported
prompt_cachingCache survives mid-conversation effort and tool changes
requires_promptYes — text prompt required

Using GPT-6 Luna on DEVUP AI

Base URL: https://api.devupai.com/v1 · Model ID: openai/gpt-6-luna

Python

PYTHON
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["DEVUP_API_KEY"],
    base_url="https://api.devupai.com/v1",
)

response = client.chat.completions.create(
    model="openai/gpt-6-luna",
    messages=[
        {"role": "user", "content": "Hello world!"}
    ],
    max_tokens=1024,
)

print(response.choices[0].message.content)

Node.js

JAVASCRIPT
import DevupAI from "devupai";

const client = new DevupAI({
  apiKey: process.env.DEVUP_API_KEY,
});

async function main() {
  const response = await client.chat.completions.create({
    model: "openai/gpt-6-luna",
    messages: [{ role: "user", content: "Hello world!" }],
    max_tokens: 1024,
  });

  console.log(response.choices[0].message.content);
}

main();

cURL

BASH
curl -X POST "https://api.devupai.com/v1/chat/completions" \
  -H "Authorization: Bearer $DEVUP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-6-luna",
    "messages": [
      { "role": "user", "content": "Hello world!" }
    ],
    "max_tokens": 1024
  }'

⚠️ The reasoning effort parameter and cache controls are configured differently across platforms. Confirm the shape your path accepts with a test request before building escalation logic around them.


Extraction at Volume

The workload this tier exists for, structured so the cache does the work.

PYTHON
import json
from pathlib import Path

# Everything fixed goes first, so the cacheable prefix is as long as possible.
SYSTEM = """You extract structured data from support tickets.

Return a single JSON object with these keys:
  order_id       string or null
  issue_type     one of: billing, delivery, damaged, wrong_item, other
  amount         number or null
  currency       string or null, exactly as written
  confidence     "high" or "low"

Rules:
- Use null for anything the ticket does not state. Never infer a value.
- Set confidence to "low" when the ticket is ambiguous about the issue type, or when a value is
  present but unclear.
- Reply with JSON only. No prose, no preamble, no explanation."""


def extract(ticket: str, *, effort: str = "none") -> dict:
    """Extract fields from one ticket."""
    response = client.chat.completions.create(
        model="openai/gpt-6-luna",
        messages=[
            {"role": "system", "content": SYSTEM},
            {"role": "user", "content": ticket},
        ],
        max_tokens=512,
        temperature=0,
        extra_body={"reasoning_effort": effort},
    )

    raw = response.choices[0].message.content

    try:
        return json.loads(raw)
    except json.JSONDecodeError as exc:
        raise ValueError(f"model did not return parseable JSON: {raw[:200]}") from exc


TICKETS = Path("tickets")
OUTPUT = Path("extracted")
OUTPUT.mkdir(exist_ok=True)

escalated = 0

for path in sorted(TICKETS.glob("*.txt")):
    target = OUTPUT / f"{path.stem}.json"
    if target.exists():
        continue

    ticket = path.read_text(encoding="utf-8")

    try:
        result = extract(ticket)

        # The one case worth spending on: the model says it is unsure.
        if result.get("confidence") == "low":
            result = extract(ticket, effort="high")
            result["_escalated"] = True
            escalated += 1

    except Exception as exc:
        print(f"{path.name}: {type(exc).__name__} — {exc}")
        continue

    target.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")

print(f"escalated {escalated} tickets")

Four decisions carry the weight here.

The system prompt is identical on every call, which makes it a cacheable prefix. On ten thousand tickets, that prefix is sent ten thousand times and processed once.

reasoning_effort="none" by default. Extraction against a fixed schema has one correct answer; deliberation adds latency and nothing else.

The confidence field is the escalation signal, and it is the only thing that triggers a second, more expensive pass. Without it you either escalate everything or nothing.

And the escalation is cheap because the cache survives the effort change. On a model where it did not, re-running a ticket at higher effort meant reprocessing the system prompt too.

Skip-if-exists and catch-and-continue are what let a ten-thousand-document run survive a failure at document eight thousand.


Summarisation Across a Long Input

Where 922,000 tokens of input on a clerical tier becomes unusual.

PYTHON
from pathlib import Path

thread = "\n\n".join(
    f"--- {path.name} ---\n{path.read_text(encoding='utf-8')}"
    for path in sorted(Path("correspondence").glob("*.txt"))
)

response = client.chat.completions.create(
    model="openai/gpt-6-luna",
    messages=[
        {
            "role": "system",
            "content": (
                "Summarise this correspondence for a colleague taking it over. Cover: what was "
                "agreed, what remains open, who owes what to whom, and any deadline mentioned. "
                "Attribute every point to the message it came from. Report nothing you cannot "
                "attribute."
            ),
        },
        {"role": "user", "content": thread},
    ],
    max_tokens=8192,
    temperature=0.2,
    extra_body={"reasoning_effort": "none"},
)

print(f"input: {response.usage.prompt_tokens:,} of ~922,000")

The whole correspondence in one call rather than message by message with a merge step afterwards. That removes the class of error where a summary of summaries loses something the individual summaries kept.

Requiring attribution is what makes the summary checkable. A point traced to its message can be verified in seconds; a synthesised one cannot.

reasoning_effort="none" even here. Summarisation is a reading task, not a reasoning one — and this is exactly the sort of call where a default effort setting quietly costs you tokens on every request.


Grounded Answering

The third verb in OpenAI's own description.

PYTHON
from datetime import date

GROUNDED = f"""Answer only from the material provided below. Quote the passage supporting each
statement. Where the material does not contain the answer, say so plainly and stop — do not fill the
gap from general knowledge.

Your training data ends in May 2026. The current date is {date.today().isoformat()}."""


def answer(question: str, documents: str) -> str:
    response = client.chat.completions.create(
        model="openai/gpt-6-luna",
        messages=[
            {"role": "system", "content": GROUNDED},
            {"role": "user", "content": f"{documents}\n\nQuestion: {question}"},
        ],
        max_tokens=2048,
        temperature=0.2,
        extra_body={"reasoning_effort": "none"},
    )
    return response.choices[0].message.content

Grounded answering is where a cheaper tier performs closest to an expensive one, because reading is a much easier task than recalling — and the gap between tiers narrows considerably when the answer is in front of both.

Put the grounding instruction in the system prompt and keep it fixed. Same text on every call means a cacheable prefix, and on an answering endpoint that runs constantly, that prefix is most of what you would otherwise pay to reprocess.


Measuring Whether You Need the Tier Above

The comparison worth running before routing work upward by assumption.

PYTHON
LUNA = "openai/gpt-6-luna"
SOL = "openai/gpt-6-sol"


def compare(prompt: str, system: str) -> None:
    """Run the same task on both tiers and report tokens and agreement."""
    results = {}

    for model in (LUNA, SOL):
        response = client.chat.completions.create(
            model=model,
            messages=[
                {"role": "system", "content": system},
                {"role": "user", "content": prompt},
            ],
            max_tokens=4096,
            temperature=0,
            extra_body={"reasoning_effort": "none"},
        )
        results[model] = {
            "answer": response.choices[0].message.content,
            "tokens": response.usage.completion_tokens,
        }

    for model, r in results.items():
        print(f"{model:<22} {r['tokens']:>6,} tokens")

    print(f"identical: {results[LUNA]['answer'] == results[SOL]['answer']}")

Run it across twenty of your real tasks. OpenAI's own framing is that all three tiers were trained with similar methods — which makes "does the cheaper one actually differ on my work" an empirical question rather than a settled one.

On clerical tasks it frequently will not differ, and that is the finding worth having before building a routing rule on an assumption.


Watching the Input Cap

PYTHON
MAX_INPUT = 922_000
MAX_OUTPUT = 128_000


def check_request(estimated_input: int, want_output: int) -> int:
    """Validate against both caps separately, not against their sum."""
    if estimated_input > MAX_INPUT:
        raise ValueError(
            f"input of ~{estimated_input:,} tokens exceeds the {MAX_INPUT:,} input cap"
        )

    return min(want_output, MAX_OUTPUT)

Two caps, checked separately. The headline figure is their sum, and satisfying the sum is not sufficient.


Where It Fits

Extraction pipelines, at any volume — with a confidence signal and cheap escalation for the hard cases.

Summarisation at scale, including across very long inputs the tier would not normally support.

Grounded answering, where reading beats recalling and the tier gap narrows.

Classification, routing, and tagging, at none effort with a fixed cacheable prefix.

High-frequency features where cost per call decides whether the feature exists.

Anything time-sensitive between April and May 2026, where this tier is better informed than the one above it.

Not for the most demanding work. That is the flagship's stated role, two tiers up.

Not for complex agent orchestration, where the tier above is positioned.

Not for images. Text in, text out.


Practical Notes

Default to reasoning_effort="none" and escalate on a signal rather than a guess.

Put everything fixed at the front — the system prompt, the schema, the instructions — so the cacheable prefix is as long as possible.

Add a confidence field to extraction output and use it to route.

Build batch runs with skip-if-exists and catch-and-continue from the start.

Check input and output against their own caps, not against the total.

Log your cached-read proportion — it is what tells you whether the structure is working.

Measure against the tier above on your own tasks before assuming you need it.

Remember this tier has the more recent knowledge cutoff.


Limitations

Released today. Production behaviour, tooling support, and independent evaluation are all ahead of it.

Positioned for clerical work. OpenAI's own framing — summarising, extracting, answering — and the tiers above exist for what falls outside that.

Two separate caps, not one shared budget: 922K input and 128K output, each enforced on its own.

Knowledge ends 18 May 2026 — more recent than the tier above, and still a fixed point.

Closed weights. API access only, with no architecture published and no self-hosted option.

Text only. No image, audio, or video input.

Cache behaviour depends on your serving path. The mid-conversation preservation is a property of OpenAI's platform; whether it survives an intermediary is worth confirming rather than assuming.

Vendor-reported figures on a model hours old. Measure your own workload.

Coding deception is reduced across this release, not eliminated. On any path where the model reports its own success, verify against the system rather than the transcript.