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.
How to
Establish a baseline
Measure quality, latency, tool use, and total cost on one evaluation set; the tutorial starts from an intentionally inefficient support agent.
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).
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.
Context hygiene
Evaluate compaction or truncation carefully on long conversations — removing earlier context can discard facts the next decision needs.
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.
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.
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.
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.
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:
| Knob | Inefficient baseline | Optimized pattern | Primary metric |
|---|---|---|---|
| Prompt and output | Broad "be thorough" instructions and long answers | Specific task rules, concise response contract, lower text.verbosity, capped output | Output tokens, concision, quality |
| Reasoning effort | High reasoning for every ticket | Low for routine work, higher only for high-risk decisions | Reasoning tokens, latency |
| Tool surface | All tools exposed for every request | Full stable tool list plus tool_choice.allowed_tools per task | Tool calls, cacheability |
| Tool schemas | Verbose descriptions and broad payload expectations | Small schemas with only decision-critical arguments | Input tokens |
| Tool payloads | Raw CRM, carrier, audit, and appendix blobs | Slim fields needed for the next decision | Tool output tokens |
| Model routing | One large model for all steps | Nano for triage/tags, mini for routine resolution, full model for high-risk cases | Cost, latency, escalation accuracy |
| Prompt caching | Volatile ticket data mixed into the prefix | Stable instructions, tools, policy framing, and schema first; ticket data last | Cached input tokens, cost |
| Workflow split | QA, analytics, summaries, and audits in the customer path | Customer resolution sync; QA/tags/reporting async via background, flex, or Batch | p50 latency, synchronous cost |
| Guardrails and evals | Informal spot checks | Deterministic checks plus judge schema for live traces | Regression 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:
| Tier | Model | Fits | What to measure |
|---|---|---|---|
| Classification / extraction / low-risk routing | gpt-5.4-nano | Ticket classification, entity extraction, simple tags | Intent accuracy, high-risk false negatives, structured-output reliability, latency, cost per correctly classified ticket |
| Routine support | gpt-5.4-mini | Order status, damaged delivery, straightforward refund-eligibility checks, other repeatable tasks | Resolution correctness, tool-call accuracy, policy compliance, p50/p95, cost per successfully resolved ticket |
| Complex / high-risk | gpt-5.4 | Account-access problems, duplicate-charge escalations, refund disputes | Resolution 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:
- 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;
- 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;
- 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:
| Constraint | Pushes you toward | Watch out for |
|---|---|---|
| High policy or account-security risk | Larger model on high-risk paths, stricter escalation, judge evals | Over-escalation can hurt customer experience and support capacity |
| High ticket volume with repeated workflows | Stable prefixes, prompt caching, smaller models, Batch for follow-up work | Cache misses on large prefixes can add latency |
| Strict cost target | Nano/mini for triage and routine paths, output caps, flex or Batch for offline work | Cost-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
- The Agents API appears in the OpenAI SDK (beta): /agents CRUD, environments, sessions, and vaults — the API surface behind what this tutorial optimizes;
- openai-python 3.15/3.16 and openai-node 7.18/7.19: Cache Prewarming, Webhook Management, connector_id Deprecation — prewarm, another member of the prompt_cache_options family alongside section 6;
- openai-python 3.9/3.10 and openai-node 7.11/7.12: Prompt Cache Diagnostics, API Key Expiry, GPT Image 2.5 — diagnosing cache hits with comparison_response_id, a good companion to the cached_tokens observability in this article.
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
Official references
- DocsOptimizing customer support agents for cost and quality (the cookbook tutorial, primary source for this article)
- Docsopenai-cookbook examples/agent_optimization directory (companion scripts: simulation, evaluation, support, and more)
- Docsevaluation.py (offline answer grading and comparison, openai-cookbook)
Related articles
Bilingual Content Production: zh Master Drafts, en Rewrites, and Consistency Checks
In a bilingual knowledge base the en version is a rewrite for English readers, not a translation: shared vs independent frontmatter fields, target-language link titles, and a two-round tightening method for over-length fields.
Read articleWorld-State Consistency for Multi-Author Knowledge Bases
The deadliest failure in a multi-author, AI-assisted knowledge base is contradictory facts. GPTMap's world-state pattern: a dated shared-facts snapshot, three-step change propagation, and build-time consistency assertions.
Read articleSource Verification and Review-Until-Clean: A Fact-Checking Workflow for AI Content
The costliest failure in AI-assisted content is the factual error. GPTMap's workflow: three writing rules plus a five-step review loop, with a real verification case from a launch announcement.
Read articleSubscribe 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.