GPTMap

OpenAI's Agents Optimization cookbook: a four-round playbook for cheaper support agents

A new official cookbook tutorial on agent optimization: measure a baseline, change one thing per round, and accept savings only after quality holds. Four optimization rounds and a nine-step tuning order, item by item.

TL;DR
openai-cookbook's agent-optimization tutorial (2026-09-18, PR #3073): measure a baseline, change one thing per round, gate savings on quality. The order: prompt/output controls, tool narrowing, routing (GPT-5.4 nano/mini/full; GPT-5.6 luna/terra/sol match those tiers), prompt caching (cache writes bill 1.25x input on GPT-5.6), then async QA/tagging. Simulation numbers are not a benchmark.
Agent cost optimization is the practice of tightening an agent workflow's cost structure in a fixed order without breaching quality gates: establish a measurable baseline, then apply prompt and output controls, tool-surface narrowing, context hygiene, model routing, prompt caching, and a sync/async workflow split — judged by cost per verified resolution rather than raw token cost. The openai-cookbook's optimizing_agents_for_cost_and_quality tutorial turns this loop into a runnable open-source example for an e-commerce support scenario.

How to

  1. Establish a baseline

    Measure quality, latency, tool use, and total cost on one evaluation set; the tutorial starts from an intentionally inefficient support agent.

  2. Apply prompt and output controls

    Replace broad be-thorough instructions with specific task rules and a concise response contract; lower text.verbosity and reasoning effort; cap output (the cap covers visible and reasoning tokens, so check for incomplete responses).

  3. Narrow the tool surface

    Keep one stable tool list and authorize per-task subsets with tool_choice.allowed_tools; shrink schemas to decision-critical arguments and slim payloads to the fields the next decision needs.

  4. Context hygiene

    Evaluate compaction or truncation carefully on long conversations — removing earlier context can discard facts the next decision needs.

  5. Route models per step

    Use the nano tier for classification, extraction, and low-risk routing; mini for routine tickets; the full model for high-risk cases. Start from the existing effort setting, then evaluate one level lower on the same labeled tickets.

  6. Configure prompt caching

    Put stable prefixes (instructions, tools, policy, schema) first and volatile ticket data last; on GPT-5.6 use an explicit breakpoint with a stable prompt_cache_key and watch cached_tokens and cache_write_tokens.

  7. Tune context for cache locality

    Check whether the longest cached prefix actually matches — the default breakpoint sits after the latest message, so per-ticket details can shift it.

  8. Split the workflow

    Keep classification, necessary lookups, the resolution or escalation decision, and the customer response synchronous; move QA, tags, internal summaries, and audits to follow-up work.

  9. Pick the processing tier

    Default or priority for latency-sensitive requests; Batch for offline jobs with a 24h window; flex trades lower cost for slower responses and occasional unavailability; background mode is async only, with no discount.

An official answer to "our agent is too expensive": on 2026-09-18, openai-cookbook merged an optimization tutorial (Optimizing customer support agents for cost and quality, PR #3073) that turns "measure a baseline, change one part of the workflow, and check quality before accepting savings" into a runnable example, built on synthetic e-commerce support tickets and a deterministic simulation. Following this site's practice, we re-fetched the repo sources and verified them item by item on 2026-09-22 before writing: the methodology, the nine optimization knobs, the GPT-5.6 caching changes, and — first of all — the simulation's own stated limitations. Any number that comes from the simulation keeps its "illustrative" status here; none are restated as benchmarks.

1. What the tutorial covers

One sentence: a repeatable optimization sprint for a tool-using agent — measure a baseline, change one part of the workflow, and check quality before accepting savings. The scenario is e-commerce support: synthetic tickets, customer queries, order and policy tools, refund and escalation decisions. The tutorial's own outline has eight steps: define success criteria and a small eval set, build an intentionally inefficient baseline agent, measure baseline cost/tokens/quality/latency/tool calls, apply prompt, output, tool, and context controls, route simple steps to smaller models, restructure requests for prompt caching, split real-time and follow-up work, then add monitoring, evals, and guardrails.

The code defaults to dry-run mode and spends nothing; the optional live helpers require OPENAI_API_KEY and RUN_LIVE_API_CALLS=true. The optional LLM judge needs RUN_LLM_JUDGE=true and uses gpt-5.4-mini (defined in live_api.py). Dependencies are five packages: openai, pandas, matplotlib, jinja2, ipykernel.

2. First, the tutorial's own disclaimer: simulation numbers are not a benchmark

This is the most teachable passage in the whole notebook. The Simulation contract section opens by saying the default path uses mock data and modeled metrics, and its numbers are not a production benchmark. Specifically:

  • The harness measures serialized text lengths, and token counts are estimated from those lengths;
  • Reasoning tokens, latency, cache hits, and the aggregate quality score follow illustrative formulas;
  • Cost does apply the verified price table to the estimated usage;
  • Routing and optimized actions come from the fixture labels — so the simulation does not measure a model's ability to choose them;
  • Response checks are case-insensitive literal phrase matches, which can reject valid paraphrases and cannot establish factual correctness.

The tutorial's conclusion: for deployment decisions, replace these traces with real usage, timings, tool results, routing decisions, and calibrated judge or human evaluations. We put this section before the methodology because it is where readers are most likely to misuse the tutorial.

3. The nine optimization knobs

One table covers every knob, the inefficient baseline, and the optimized pattern:

KnobInefficient baselineOptimized patternPrimary metric
Prompt and outputBroad "be thorough" instructions and long answersSpecific task rules, concise response contract, lower text.verbosity, capped outputOutput tokens, concision, quality
Reasoning effortHigh reasoning for every ticketLow for routine work, higher only for high-risk decisionsReasoning tokens, latency
Tool surfaceAll tools exposed for every requestFull stable tool list plus tool_choice.allowed_tools per taskTool calls, cacheability
Tool schemasVerbose descriptions and broad payload expectationsSmall schemas with only decision-critical argumentsInput tokens
Tool payloadsRaw CRM, carrier, audit, and appendix blobsSlim fields needed for the next decisionTool output tokens
Model routingOne large model for all stepsNano for triage/tags, mini for routine resolution, full model for high-risk casesCost, latency, escalation accuracy
Prompt cachingVolatile ticket data mixed into the prefixStable instructions, tools, policy framing, and schema first; ticket data lastCached input tokens, cost
Workflow splitQA, analytics, summaries, and audits in the customer pathCustomer resolution sync; QA/tags/reporting async via background, flex, or Batchp50 latency, synchronous cost
Guardrails and evalsInformal spot checksDeterministic checks plus judge schema for live tracesRegression rate, safety pass rate

4. Round 1: prompt, tool, and context controls

Set rules before switching models. The tutorial's combination: lower text.verbosity and reasoning effort, add an output cap, and restrict tools with an allowed_tools subset. Three easy-to-miss reminders:

  • The output cap includes both visible and reasoning tokens — check for incomplete responses when tuning it;
  • The helper also limits tool rounds and returns slim payloads;
  • For long conversations, evaluate compaction or truncation carefully: removing earlier context can discard facts needed for the next decision.

One more piece of engineering honesty: the demo restricts tools using known ticket metadata; a production router needs separate evaluation and a fallback for low-confidence routing. If you use prompt optimization, target a specific observed failure and rerun the same evals.

5. Round 2: right-size the model per step, not one global model

The tutorial's tiers, on a GPT-5.4 baseline:

TierModelFitsWhat to measure
Classification / extraction / low-risk routinggpt-5.4-nanoTicket classification, entity extraction, simple tagsIntent accuracy, high-risk false negatives, structured-output reliability, latency, cost per correctly classified ticket
Routine supportgpt-5.4-miniOrder status, damaged delivery, straightforward refund-eligibility checks, other repeatable tasksResolution correctness, tool-call accuracy, policy compliance, p50/p95, cost per successfully resolved ticket
Complex / high-riskgpt-5.4Account-access problems, duplicate-charge escalations, refund disputesResolution quality, policy adherence, latency, end-to-end cost; keep deterministic authorization and refund checks and human review

The same-tier GPT-5.6 comparisons: gpt-5.6-luna maps to the nano tier (classification and high-volume tasks), gpt-5.6-terra to the mini tier (routine support workflows), and gpt-5.6-sol to the full-model tier (complex or high-risk cases) — each evaluable against its GPT-5.4 baseline on the same tickets and quality criteria. Two methodological details worth stealing: start with the existing reasoning-effort setting and then evaluate one level lower; and a newer model can be more economical at the task level if it resolves tickets with fewer retries, unnecessary tool calls, or escalations. Consider fine-tuning only if a selected model explicitly supports it.

6. Round 3: prompt caching — three GPT-5.6 changes

Every support request shares the same core instructions, policy rules, tool definitions, and response schema; caching reuses that context across tickets, with customer-specific details (order IDs, account information, retrieved records) placed after the shared prefix.

On gpt-5.4-mini, the API automatically identifies repeated prefixes and reuses the shared context even when customer-specific details change, and writing a new prefix carries no separate cache-write charge. The tutorial's request shape (from a tutorial code cell, line-wrapped for readability):

cache_friendly_request = {
    "model": "gpt-5.4-mini",
    "instructions": CACHE_FRIENDLY_PROMPT,
    "tools": SLIM_TOOLS,
    "tool_choice": allowed_tool_choice(["lookup_order"], mode="auto"),
    "prompt_cache_key": "support_order_status_v1",
    "reasoning": {"effort": "low"},
    "text": {"verbosity": "low"},
    "max_output_tokens": 300,
    "input": [
        {"role": "user", "content": json.dumps({
            "ticket_id": "T-001", "customer_id": "C-100",
            "message": "Where is order O-1001?", "order_id": "O-1001",
        })},
    ],
}

The GPT-5.6 family (luna / terra / sol) differs in three ways:

  1. Cache writes are billed: writing content to cache costs 1.25 times the normal input-token price — repeatedly caching messages that are unique per ticket can increase cost without creating useful reuse;
  2. The default cache breakpoint sits after the latest message: if that message changes between tickets, the longest cached prefix may not match; implicit mode can still reuse earlier eligible message endings, including the initial developer-message block;
  3. Explicit breakpoints: put the shared playbook in a developer-message input_text block and mark the end of that block with prompt_cache_breakpoint in explicit mode, before the order-specific details; top-level instructions cannot contain a breakpoint.

The supporting settings: prompt_cache_options in explicit mode with a 30m ttl, and the same prompt_cache_key across requests (the tutorial's example: support_order_status_v1). Metrics to compare: cached_tokens and cache_write_tokens, alongside latency and cost per resolved ticket.

7. Round 4: move non-customer work out of the synchronous path

Four things stay synchronous: classification, necessary lookups, the resolution or escalation decision, and the customer response. QA, tags, internal summaries, audits, and reporting move to follow-up work whenever they do not change the immediate outcome. Tier choices: default or priority for latency-sensitive requests; flex trades lower cost for slower responses and occasional resource unavailability (confirm model support and handle timeouts); Batch suits offline jobs with a 24h completion window; background mode makes a request asynchronous but does not itself provide a pricing discount.

8. Tradeoffs: there is no universal best configuration

The tutorial says it outright: the sweet spot depends on traffic shape, customer promise, policy risk, cache hit rate, tool latency, observability maturity, and how much work can move out of the synchronous path. Three of the seven constraint rows it tabulates:

ConstraintPushes you towardWatch out for
High policy or account-security riskLarger model on high-risk paths, stricter escalation, judge evalsOver-escalation can hurt customer experience and support capacity
High ticket volume with repeated workflowsStable prefixes, prompt caching, smaller models, Batch for follow-up workCache misses on large prefixes can add latency
Strict cost targetNano/mini for triage and routine paths, output caps, flex or Batch for offline workCost-only tuning can remove safeguards if quality gates are weak

For one mocked scenario (Low-repeat long tail), the tutorial maps every architecture combination rather than hiding them behind the single best pick — its stated point is that cache-heavy designs are less attractive when cache locality is low.

9. Monitoring: measure cost per verified resolution

Once in production, keep a recurring eval loop; the objective is not minimizing tokens in isolation but resolving customer issues correctly, safely, and quickly at the lowest total cost per successful outcome. The tutorial's formula:

blended cost per verified resolution = total model, tool, infrastructure, retry, human-review, escalation, and rework costs / verified customer issues resolved

Three companion disciplines: the numerator must include spending on unsuccessful attempts, not only the traces that eventually passed; track autonomous resolutions separately from human-assisted ones, or an apparent reduction in agent cost can hide a transfer of work to the support team; and the tutorial's own worked example is illustrative — $0.02 per ticket at 50% resolution costs $0.04 per successful resolution, while $0.03 at 90% costs about $0.033. The second workflow costs more per attempt but less per successful outcome (illustrative figures, excluding human-support costs).

The production tracking list: quality score, policy compliance, action accuracy, escalation accuracy, tool-call count, token usage, cached-token volume, p50 and p95 latency, synchronous cost, async follow-up cost, and total cost per ticket. A configuration is only better if it lowers cost while preserving the support quality bar.

10. The nine-step tuning order (official recommendation)

The tutorial's closing sequence — also embedded as this article's howTo — reads: Baseline, Prompt/output controls, Tool control, Context hygiene, Model routing, Prompt caching, Cache-aware context, Split workflow, Processing tier. The strongest result comes not from a single trick but from applying levers in a safe order; the key engineering habit is to optimize per step, not globally — a routine classifier, a high-risk refund dispute, a customer-facing response, and an offline QA tagger should not share the same model, context, tools, latency target, or service tier.

11. Running it, and common mistakes

Running it: install the requirements (openai, pandas, matplotlib, jinja2, ipykernel) and run the notebook — dry-run by default, zero spend. The live path needs OPENAI_API_KEY and RUN_LIVE_API_CALLS=true. The optional judge needs RUN_LLM_JUDGE=true (model gpt-5.4-mini; a failed judge request marks that grade as an error with a reason and does not block the rest of the evaluation).

Common mistakes:

  • Reporting simulation numbers as benchmarks — reread section 2: the simulation contract states the numbers are not a production benchmark; tokens are length-estimated and routing comes from fixture labels;
  • Counting tokens but not resolutions — reread section 9: a cheaper model with more retries can cost more per verified resolution;
  • Putting a breakpoint in top-level instructions — the tutorial states top-level instructions cannot contain a breakpoint; mark it at the end of the developer-message input_text block instead;
  • Changing prompt_cache_key per ticket — one stable key per workflow (tutorial example: support_order_status_v1); the tradeoff table likewise flags that routing keys fragmented too finely reduce cache effectiveness;
  • Lowering the output cap without checking for incomplete responses — the cap includes visible and reasoning tokens.

12. Next steps

Key points

  • Source and scope: the openai-cookbook repo's examples/agent_optimization directory (PR #3073, merged 2026-09-18) demonstrates the optimization loop on synthetic e-commerce support tickets with a deterministic simulation; the notebook self-labels last verified 2026-09-14, uses GPT-5.4 models in examples, and describes GPT-5.6 considerations in the model-selection and caching sections
  • Zero-spend by default: the code defaults to dry-run, and the simulation runs without API spend; optional live helpers require OPENAI_API_KEY plus RUN_LIVE_API_CALLS=true; the optional LLM judge needs RUN_LLM_JUDGE=true and uses gpt-5.4-mini (live_api.py)
  • The built-in honesty statement: simulation numbers are not a production benchmark — tokens are estimated from serialized lengths, reasoning tokens and latency follow illustrative formulas, routing comes from fixture labels (so the simulation does not measure the model's ability to route), and response checks are case-insensitive literal phrase matches; deployment decisions need real traces and calibrated judges
  • Three routing tiers: gpt-5.4-nano for classification/extraction/low-risk routing, gpt-5.4-mini for routine support and order workflows, gpt-5.4 for high-risk cases (account access, duplicate-charge escalations, refund disputes); on the GPT-5.6 side luna/terra/sol map to the same tiers — evaluate with the existing effort setting first, then one level lower
  • Three GPT-5.6 caching changes: cache writes are billed (1.25x the normal input-token price), the default cache breakpoint sits after the latest message (so per-ticket variation can shift the longest matching prefix), and explicit breakpoints are available — put the shared playbook in a developer-message input_text block and mark prompt_cache_breakpoint as explicit mode at its end; top-level instructions cannot contain a breakpoint; pair with prompt_cache_options in explicit mode, ttl 30m, and a stable prompt_cache_key
  • Measure cost per outcome: blended cost per verified resolution — the numerator must include failed attempts, retries, human review, escalations, and rework; track autonomous vs human-assisted resolutions separately; the tutorial's illustrative example: $0.02 per ticket at 50% resolution equals $0.04 per success, while $0.03 at 90% is about $0.033 (illustrative figures, excluding human-support costs)

Frequently asked questions

No. The Simulation contract section is blunt: the default path uses mock data and modeled metrics, and its numbers are not a production benchmark. Token counts are estimated from serialized text lengths; reasoning tokens, latency, cache hits, and the quality score follow illustrative formulas; routing and optimized actions come from fixture labels, so the simulation does not measure a model's ability to route; response checks are case-insensitive literal phrase matches. For deployment decisions, replace them with real usage, timings, tool results, routing decisions, and calibrated judges or human evaluations.

Official references

Related articles

Subscribe to GPTMap Weekly

One email every Monday: curated OpenAI updates, deep dives, and best practices. No ads, unsubscribe anytime.

Submitting opens Buttondown in a new tab to confirm your subscription.

GPTMap EditorialPublished 2026-09-22 11 min read
Test environment (EEAT)
Last tested: 2026-09-22
Model used: gpt-5.6