DEV Community

Cover image for GPT-5.6 Ultra Mode Means Agent Budgets Need to Handle Subagents
Assili Salim
Assili Salim

Posted on

GPT-5.6 Ultra Mode Means Agent Budgets Need to Handle Subagents

OpenAI released GPT-5.6 across ChatGPT, Codex, and the API on July 9.

The model family has three tiers: Sol, Terra, and Luna. OpenAI lists API pricing at $5 input / $30 output per million tokens for Sol, $2.50 / $15 for Terra, and $1 / $6 for Luna.

The pricing matters.

But if you build AI agents, the bigger detail is this:

GPT-5.6 adds max reasoning effort and an ultra mode that uses subagents to accelerate complex work. In the API, OpenAI says multi-agent support can run concurrent subagents and synthesize their work in a single request.

That changes how runtime budgets should work.

A single-call budget is not enough when the task can fan out.

The naive budget

A simple budget guard might look like this:

const estimatedCost =
inputTokens * inputPrice +
maxOutputTokens * outputPrice;

if (estimatedCost > budgetRemaining) {
throw new Error("Budget exceeded");
}

This is a decent start.

But it assumes the next call is the whole unit of risk.

That assumption breaks down when an agent can create subagents.

A parent agent may start several branches.

Each branch may call a model.

Each branch may use tools.

Each branch may retry.

The parent may then call the model again to synthesize results.

The real budget is not only the next call.

It is the execution tree.

Think in execution trees

A multi-agent workflow can be modeled like this:

type AgentNode = {
id: string;
parentId?: string;
model: string;
effort: "low" | "medium" | "high" | "max" | "ultra";
stepCount: number;
retryCount: number;
budgetRemaining: number;
};

The parent task needs a shared budget.

Each subagent needs a local budget.

type WorkflowBudget = {
workflowId: string;
totalRemaining: number;
perAgentLimit: number;
perCallLimit: number;
};

This gives you three useful boundaries:

per-call budget

per-subagent budget

whole-workflow budget

You need all three.

A call can be safe locally while the subagent is wasting work.

A subagent can be safe locally while the whole workflow is burning too much in parallel.

Add a pre-call decision

Before every provider call, make the runtime decide whether the call should happen.

type BeforeCallInput = {
workflowId: string;
agentId: string;
parentAgentId?: string;
model: string;
effort: string;
prompt: string;
estimatedInputTokens: number;
maxOutputTokens: number;
stepCount: number;
retryCount: number;
budgetRemainingForAgent: number;
budgetRemainingForWorkflow: number;
previousPrompts: string[];
progressState: {
filesChanged?: boolean;
testsImproved?: boolean;
errorsChanged?: boolean;
objectiveCompleted?: boolean;
};
};

type GuardDecision =
| { allowed: true }
| {
allowed: false;
reason:
| "unknown_model_pricing"
| "call_budget_exceeded"
| "agent_budget_exceeded"
| "workflow_budget_exceeded"
| "max_steps_exceeded"
| "retry_storm"
| "prompt_loop"
| "no_progress";
};

Then use it before the provider call:

const decision = guard.beforeCall({
workflowId,
agentId,
parentAgentId,
model,
effort,
prompt,
estimatedInputTokens,
maxOutputTokens,
stepCount,
retryCount,
budgetRemainingForAgent,
budgetRemainingForWorkflow,
previousPrompts,
progressState,
});

if (!decision.allowed) {
return {
status: "stopped",
reason: decision.reason,
};
}

const result = await provider.call({
model,
prompt,
});

The exact API is not the point.

The placement is the point.

The decision happens before the provider call.

Check model pricing

GPT-5.6 has multiple model tiers with different prices.

That means the runtime should not treat model names as harmless strings.

if (!pricingCatalog.has(model)) {
return {
allowed: false,
reason: "unknown_model_pricing",
};
}

Do not guess.

Unknown pricing should fail closed.

This matters even more when agents can escalate, fallback, or fan out.

Check effort level

Effort level is not only a quality setting.

It is an execution-policy setting.

if (effort === "ultra" && !taskPolicy.allowUltra) {
return {
allowed: false,
reason: "effort_not_allowed",
};
}

A small task should not silently use the most expensive execution shape.

A high-value task might deserve it.

The runtime should know the difference.

Check workflow budget

For subagents, local checks are not enough.

if (estimatedNextCallCost > budgetRemainingForWorkflow) {
return {
allowed: false,
reason: "workflow_budget_exceeded",
};
}

This prevents many individually reasonable branches from consuming the shared ceiling.

Parallel waste is still waste.

Check subagent budget

Each branch also needs a local ceiling.

if (estimatedNextCallCost > budgetRemainingForAgent) {
return {
allowed: false,
reason: "agent_budget_exceeded",
};
}

If one subagent is stuck, it should stop without consuming the parent workflow.

Check max steps

Subagents need step limits too.

if (stepCount >= maxSteps) {
return {
allowed: false,
reason: "max_steps_exceeded",
};
}

A branch that cannot produce useful work in a reasonable number of steps should stop cleanly.

Check prompt loops

If a subagent keeps asking nearly the same thing, the runtime should treat that as a loop.

if (similarToRecentPrompt(prompt, previousPrompts)) {
return {
allowed: false,
reason: "prompt_loop",
};
}

This is especially useful in coding agents.

A stuck agent often rephrases the same failing approach.

Check no progress

A subagent can be active without being useful.

Track signals like:

tests improved
error changed
relevant files changed
objective completed
retrieved context changed
final answer got closer

If none of those move, stop.

if (!madeProgress(progressState, recentSteps)) {
return {
allowed: false,
reason: "no_progress",
};
}

A stopped branch is better than a branch that looks busy while wasting calls.

Where AI CostGuard fits

AI CostGuard is the local-first TypeScript/Node.js runtime safety layer I’m building for AI-agent projects.

It focuses on pre-call checks for:

retry storms
prompt loops
max-step explosions
runaway agent execution
unknown model pricing
budget overruns
uncontrolled provider calls
invisible AI-agent cost risk

It is not a billing ledger.

It is not a hard security boundary.

It does not replace provider dashboards.

The goal is narrow:

help the runtime decide whether the next provider call should execute.

Takeaway

Multi-agent execution changes the cost-control problem.

You are no longer guarding one prompt.

You are guarding an execution tree.

That means budgets need to exist at three levels:

per call

per subagent

per workflow

Once agents can fan out, the invoice is even later than it used to be.
https://github.com/salimassili62-afk/ai-costguard

Top comments (0)