Evidence & Optimization · Steps 12–18Chapter 16 of 45

Where Should an Agent Spend Its Compute? Build a Dynamic Budget Scheduler

Page content

Where Should an Agent Spend Its Compute?

A production agent has a budget whether you designed one or not.

Every model call costs something.

Every search node costs something.

Every tool invocation costs something.

Every verifier costs something.

Every retry adds latency.

Every escalation to a stronger model spends money and time that could have been used somewhere else.

The naive architecture gives every subsystem its own fixed limit:

MAX_STEPS = 20
MAX_SEARCH_NODES = 32
MAX_CRITIC_CALLS = 3
MAX_RETRIES = 4
MAX_VERIFIER_CALLS = 2

That looks safe.

It is also usually wasteful.

An easy task may consume far more computation than it needs.

A hard task may spend its entire budget on generation and reach verification with nothing left.

A search agent may keep expanding branches even after one branch is already strongly verified.

A router may escalate to a frontier model because a threshold fired even though one cheap diagnostic tool call would have resolved the uncertainty.

The deeper problem is this:

Fixed limits control maximum spend. They do not decide where computation has the highest expected value.

That is what this post is about.

We are going to turn the agent budget into a first-class scheduling problem.

The agent will no longer ask only:

What should I do next?

It will also ask:

Where should the next unit of computation go?


The Control Problem

By this point in the series, an advanced agent may contain:

  • a router,
  • one or more generators,
  • search,
  • critics,
  • memory,
  • specialist models,
  • tool execution,
  • escalation,
  • and external verification.

Each of those mechanisms competes for the same resources.

A simplified runtime might look like this:

                         task
                          |
                       scheduler
               ___________|____________
              /      /      |      \    \
         generate  search  tools  critic verify
              \      \      |      /    /
               \______\_____|_____/____/
                          |
                       outcome

The scheduler does not produce the answer.

It decides how much computation each part of the system receives.

That distinction matters.

In Step 15 we separated the execution plane from the control plane.

The budget scheduler belongs in the control plane.

Its job is to allocate resources while preserving hard constraints such as:

  • safety,
  • authorization,
  • maximum monetary spend,
  • maximum wall-clock latency,
  • required verification,
  • and external service limits.

Start With a Shared Budget

Do not let every subsystem pretend it owns an independent budget.

Start with one shared resource envelope.

For example:

from dataclasses import dataclass

@dataclass
class Budget:
    max_model_calls: int
    max_tool_calls: int
    max_search_nodes: int
    max_verifier_calls: int
    max_cost_usd: float
    max_latency_ms: int

    used_model_calls: int = 0
    used_tool_calls: int = 0
    used_search_nodes: int = 0
    used_verifier_calls: int = 0
    used_cost_usd: float = 0.0
    used_latency_ms: int = 0

That gives us accounting.

It does not yet give us scheduling.

The scheduler still needs to choose between competing actions.


A Budget Is Multi-Dimensional

One of the easiest mistakes is to reduce everything to dollars.

Cost matters.

But a production runtime often has several simultaneous constraints:

money
latency
model calls
tool calls
search nodes
context tokens
rate limits
verification capacity

A cheap action can be slow.

A fast action can be expensive.

A tool call can cost almost nothing in model tokens while being operationally risky.

A verifier may be expensive but mandatory.

A local model may cost little money but consume scarce GPU capacity.

So instead of one scalar budget, think in terms of a resource vector.

@dataclass(frozen=True)
class ResourceCost:
    model_calls: int = 0
    tool_calls: int = 0
    search_nodes: int = 0
    verifier_calls: int = 0
    dollars: float = 0.0
    latency_ms: int = 0

The scheduler asks whether an action fits inside the remaining envelope.


Some Budget Must Never Be Spent Elsewhere

Suppose the system has a total budget of ten model calls.

A naive search policy may spend all ten generating and scoring branches.

Then the runtime reaches its best candidate and says:

Great. Now verify it.

But there is no budget left.

That architecture is broken.

Verification is not optional cleanup.

If a verified outcome is required, the scheduler should reserve enough capacity for verification before speculative work begins.

total budget
   |
   +-- mandatory reserve
   |      |
   |      +-- verification
   |      +-- safety checks
   |      +-- required persistence
   |
   +-- adaptive budget
          |
          +-- generation
          +-- search
          +-- tools
          +-- critique
          +-- escalation

This gives us a critical rule:

Never let speculative reasoning consume resources required for mandatory acceptance checks.

A simple implementation might expose:

@dataclass
class BudgetReserve:
    verifier_calls: int = 1
    dollars: float = 0.02
    latency_ms: int = 500

The scheduler allocates from the adaptive portion while protecting the reserve.


The Wrong Question: How Many Steps Should the Agent Get?

A fixed-step architecture asks:

max_steps = 20

A better architecture asks:

Is the expected value of another step greater than its cost?

That is a very different control problem.

Suppose the agent has already:

  • generated two strong candidates,
  • run the relevant tests,
  • obtained a high-confidence external verifier PASS,
  • and found no unresolved required criteria.

Why spend another ten steps because max_steps=20?

The maximum should be a ceiling, not a target.

Similarly, suppose the agent is at step 19 and has strong evidence that one more diagnostic action is likely to resolve the task.

A rigid fixed-step scheduler may stop exactly when spending one more cheap action has high expected value.

This is why production scheduling needs both:

  • hard ceilings, and
  • adaptive allocation below those ceilings.

Expected Value of Computation

A useful way to reason about the scheduler is expected value of computation.

For a candidate action a, estimate:

expected gain from action
-------------------------
expected resource cost

We do not need perfect economics.

We need something better than blind fixed allocation.

A conceptual score might be:

def value_score(
    expected_success_gain: float,
    expected_information_gain: float,
    dollars: float,
    latency_ms: int,
    risk_penalty: float,
) -> float:
    denominator = 1.0 + dollars * 100 + latency_ms / 1000

    return (
        expected_success_gain
        + 0.3 * expected_information_gain
        - risk_penalty
    ) / denominator

The exact formula is not the point.

The point is that the scheduler should distinguish actions that are likely to change the decision from actions that merely consume compute.


Information Can Be More Valuable Than Generation

Advanced agents often overspend on generation.

The task looks uncertain, so the system produces more answers.

But uncertainty does not always mean we need another candidate.

Sometimes we need information.

For example, a coding agent is unsure whether a bug comes from:

  • parsing,
  • database state,
  • configuration,
  • or business logic.

It could generate four patches.

Or it could run one cheap diagnostic test that reveals the failing subsystem.

The diagnostic action may have much higher expected value.

uncertainty
    |
    +-- generate another candidate
    |
    +-- inspect state
    |
    +-- run diagnostic
    |
    +-- retrieve evidence
    |
    +-- verify assumption

This leads to another important rule:

Allocate compute to uncertainty reduction, not just answer production.


Search Budget Is Not Beam Width

A fixed beam search might use:

beam_width = 4
max_depth = 6

That implies a roughly fixed search shape.

But the useful shape of search is task-dependent.

One task may benefit from wide exploration near the root:

          root
       / / | \ \
      A B  C  D E
          |
          C1
          |
          C2

Another may have one obvious root decision but require deep exploration later:

root
 |
 A
 |
 A1
 |
 A2
/|\
... alternatives appear here

So the scheduler should allocate nodes, not blindly enforce a geometric pattern.

It can ask:

  • Is branch uncertainty high?
  • Are current branches meaningfully different?
  • Is the verifier separating them?
  • Has the best score plateaued?
  • Are new nodes duplicates?
  • Is search regret historically high at this state type?

Then choose whether to:

  • expand breadth,
  • deepen one branch,
  • stop search,
  • or spend the next unit elsewhere.

A Simple Dynamic Search Scheduler

Here is a deliberately small example:

@dataclass
class SearchState:
    best_score: float
    second_best_score: float
    unique_branch_ratio: float
    no_improvement_rounds: int
    remaining_nodes: int


def choose_search_action(state: SearchState) -> str:
    if state.remaining_nodes <= 0:
        return "stop"

    margin = state.best_score - state.second_best_score

    if state.no_improvement_rounds >= 2:
        return "stop"

    if state.unique_branch_ratio < 0.5:
        return "stop"

    if margin < 0.05:
        return "expand_breadth"

    if margin < 0.15:
        return "deepen_best"

    return "verify_best"

This is not sophisticated.

That is intentional.

A small policy with measurable features is much easier to calibrate than a vague instruction like:

Decide intelligently how much search is needed.


Critics Also Need a Budget

Critique can improve output.

Critique can also become a ritual.

Consider this loop:

draft
critic
revision
critic
revision
critic

If the critic keeps producing minor stylistic objections while external verification is already passing, the scheduler should stop paying for criticism.

Useful features include:

  • historical net correction rate,
  • severity of unresolved issues,
  • verifier failures attributable to the critic’s domain,
  • disagreement between scorer and verifier,
  • and whether previous critic passes changed the output meaningfully.

A critic that often converts wrong → correct deserves budget.

A critic that mostly converts correct → correct while consuming tokens may not.

A critic that sometimes converts correct → wrong needs stronger gating.


Escalation Is a Budget Decision

Suppose you have:

  • a cheap local model,
  • a medium model,
  • and an expensive frontier model.

The naive policy is:

try cheap
if uncertain → medium
if still uncertain → frontier

But uncertainty alone is not enough.

The scheduler should ask:

  1. Is the task currently unresolved?
  2. Is another cheap diagnostic likely to help first?
  3. Is the stronger model historically better for this failure mode?
  4. Does enough budget remain for verification after escalation?
  5. Is the expected rescue value larger than the added cost?

One useful metric from Step 15 is cost per rescue.

incremental escalation cost
---------------------------
number of failures rescued

If frontier escalation costs $50 across a benchmark and rescues one additional task, that may be acceptable in one domain and absurd in another.

The scheduler needs the application’s actual constraints.


Verification Should Receive More Budget When Stakes Rise

Not all tasks deserve the same verification spend.

For a low-consequence summarization task, one lightweight check may be enough.

For a deployment agent modifying production infrastructure, the scheduler should spend far more on verification.

We can model a crude risk score:

@dataclass(frozen=True)
class RiskProfile:
    reversibility: float
    blast_radius: float
    financial_impact: float
    external_side_effects: float

Higher risk can reserve more verification budget.

low-risk task
  generation  ███████
  search      ███
  verify      ██

high-risk task
  generation  ████
  search      ███
  verify      ███████

That is often more rational than giving every request the same verifier pipeline.


Budget Scheduling Is Constrained Optimization

The scheduler should not simply maximize success probability.

A production objective might be:

minimize expected cost
and minimize latency
subject to:
    verified success >= target
    false success <= limit
    safety violations = 0
    budget ceilings respected

That is a much healthier formulation than:

maximize reward

It keeps hard boundaries hard.

For example:

@dataclass(frozen=True)
class SchedulerConstraints:
    min_verified_success: float
    max_false_success: float
    max_cost_usd: float
    max_latency_ms: int

The scheduler can optimize below those constraints.

It cannot decide that skipping mandatory verification is worthwhile because it saves money.


Hard Limits Still Matter

Adaptive scheduling does not mean removing ceilings.

You still want hard bounds such as:

maximum spend
maximum wall time
maximum external side effects
maximum retry count
maximum search nodes

Adaptive scheduling operates inside those bounds.

hard safety envelope
┌─────────────────────────────────┐
│                                 │
│   adaptive budget scheduler     │
│                                 │
│   generation / search / tools   │
│   critics / escalation / verify │
│                                 │
└─────────────────────────────────┘

The envelope protects the system from pathological behavior.

The scheduler tries to use the allowed resources intelligently.


Stop When the Marginal Value Goes Negative

One of the strongest scheduler decisions is simply:

Stop spending.

Suppose successive search rounds produce:

Round Verified success estimate Added cost
1 0.72 $0.01
2 0.83 $0.01
3 0.87 $0.02
4 0.875 $0.03
5 0.876 $0.04

The first few rounds are valuable.

The last two barely move the outcome.

The runtime should not treat the remaining budget as an invitation to spend it.

This gives us a practical metric:

marginal verified gain per additional dollar

or:

marginal verified gain per additional second

When that value collapses, stop.


But Do Not Stop Before Required Verification

There is an important asymmetry here.

The scheduler may stop speculative computation early.

It may not skip required acceptance criteria merely because more work looks expensive.

That means the runtime often has two stopping concepts:

stop exploration
stop task

They are not the same.

exploration no longer valuable
stop search/generation
run mandatory verification
PASS / FAIL / UNKNOWN

That distinction prevents a common failure where an agent treats “I have a good candidate” as equivalent to “the task is complete.”


A Minimal Scheduler Interface

A clean runtime can represent scheduler decisions explicitly.

from dataclasses import dataclass
from typing import Literal

ActionKind = Literal[
    "generate",
    "search",
    "tool",
    "critic",
    "escalate",
    "verify",
    "stop_exploration",
    "stop_task",
]

@dataclass(frozen=True)
class SchedulerDecision:
    action: ActionKind
    reason: str
    expected_value: float
    expected_cost: ResourceCost
    policy_version: str

This connects naturally to the trajectory observability from Step 13.

Every allocation decision becomes traceable.

state_id
budget_remaining
actions_considered
selected_action
expected_value
expected_cost
actual_cost
actual_outcome
policy_version

Now the budget scheduler itself can be benchmarked and improved.


Use Uncertainty Carefully

A scheduler will often use uncertainty as a feature.

That is useful.

It is also dangerous.

Model confidence is not automatically calibrated.

A model can be confidently wrong.

A critic can be confidently wrong.

A router can produce a very sharp probability distribution and still route incorrectly.

So scheduling features should include external signals where possible:

  • test results,
  • tool outcomes,
  • score margins,
  • branch disagreement,
  • verifier disagreement,
  • retrieval coverage,
  • historical failure rates,
  • task type,
  • and state changes.

Internal confidence is one signal, not truth.


Budget Features Should Be Small and Observable

Do not feed the entire trajectory into another giant LLM and call it a scheduler.

Start with compact features such as:

@dataclass(frozen=True)
class SchedulerFeatures:
    task_risk: float
    best_score: float
    score_margin: float
    branch_diversity: float
    verifier_status: str
    no_progress_steps: int
    recent_tool_failures: int
    estimated_task_difficulty: float
    remaining_cost_fraction: float
    remaining_latency_fraction: float

Then test whether those features actually predict useful allocation decisions.

If a deterministic threshold table works, use it.

If not, try a small calibrated model.

Only add a complex controller if the evidence shows it is necessary.


Scheduler Policy as Data

A production scheduler should be versionable.

For example:

version: scheduler-2026-08-09-a

reserves:
  verifier_calls: 1
  cost_fraction: 0.20

rules:
  - when:
      verifier_status: PASS
      unresolved_required_criteria: 0
    action: stop_task

  - when:
      no_progress_steps_gte: 2
      score_margin_gte: 0.15
    action: verify

  - when:
      branch_diversity_lt: 0.40
    action: stop_exploration

  - when:
      task_risk_gte: 0.8
    verifier_budget_multiplier: 2.0

Now policy changes can be reviewed like code.

You can diff:

scheduler-2026-08-09-a
vs
scheduler-2026-08-20-b

and ask exactly what changed.


Do Not Hide Budget Behind Agent Roles

Multi-agent systems sometimes hide cost by treating each role as conceptually separate.

planner
researcher
critic
reviewer
judge
verifier

But the user pays for all of them.

The scheduler should flatten role boundaries into resource accounting.

planner call      -> 2,400 tokens
researcher call   -> 3,100 tokens
critic call       -> 1,700 tokens
judge call        -> 2,200 tokens
verifier tool     -> 800 ms

Then ask:

Which of these calls actually changed the verified outcome?

If the planner rarely changes the route, reduce its budget.

If the critic mostly confirms already-correct answers, gate it.

If the judge performs no better than a deterministic score, remove it.

Budget scheduling is another way to expose unnecessary architecture.


Coding Agent Example

Consider a coding agent handling a failing test.

A rigid architecture might do this:

plan
retrieve
generate 4 patches
critic each patch
rank
run tests
frontier-model review
verify

The scheduler may instead discover:

1. run failing test
2. inspect stack trace
3. inspect exact function
4. generate one patch
5. run targeted test
6. run regression subset
7. stop

The dynamic path is cheaper because early diagnostics reduce uncertainty.

If the targeted test still fails, the scheduler can spend more:

failure persists
branch into alternatives
critic / search / stronger model

The architecture escalates only when the evidence justifies it.


Research Agent Example

A research agent may initially spend heavily on generation:

search
summarize
search
summarize
search
summarize

But the scheduler should track claim coverage.

Suppose the report has ten required claims.

After the first few searches:

8/10 claims externally supported
2/10 unresolved

The remaining budget should focus on those two unresolved claims, not continue broad retrieval.

A useful scheduler feature is:

expected new verified claim coverage per search

When another broad search returns sources for claims already covered, its marginal value is low.


Browser Agent Example

A browser agent attempting a checkout or form workflow may encounter ambiguity.

It can:

  • re-read the page with a model,
  • inspect the DOM,
  • take another screenshot,
  • retry the action,
  • navigate back,
  • or escalate to a stronger visual model.

The cheapest useful action depends on the state.

If the DOM clearly exposes an error message, another visual model call is wasteful.

If the DOM is inaccessible but the page changed visually, screenshot interpretation may be valuable.

The scheduler should allocate to the cheapest signal that can reduce uncertainty.


DevOps Agent Example

For a production remediation agent, budget scheduling is not just about cost.

It is also about risk.

Suppose the agent believes restarting a service will fix an incident.

Before spending its side-effect budget, the scheduler might allocate to:

read-only metrics
logs
health checks
dependency state
current deployment version

Only after enough evidence supports the hypothesis does it permit the irreversible or disruptive action.

Then it allocates heavily to post-action verification.

observe
diagnose
precondition verify
action
postcondition verify
regression checks

For consequential systems, verification budget should often dominate generation budget.


Mixture-of-Agents Example

A mixture-of-agents runtime may expose several specialists:

local code model
frontier code model
retrieval specialist
planner
critic
verifier

The scheduler is different from the router.

The router asks:

Which expert is appropriate?

The scheduler asks:

How much resource should this task receive, and when should we spend it on that expert?

These can interact.

router: code-local probability = 0.72
scheduler: cheap local model has high expected value
use local model first
verification fails
remaining budget sufficient
frontier escalation now has high rescue value

That is better than always running both models.


Fixed Budgets Are Still the Baseline

Do not assume dynamic scheduling is better.

Benchmark it.

A fair experiment might compare:

Policy A — Fixed cheap

1 generation
1 verifier

Policy B — Fixed medium

4 generations
2 critics
1 verifier

Policy C — Fixed large

8 search nodes
3 critics
strong-model escalation
2 verifiers

Policy D — Dynamic scheduler

same maximum resource envelope
allocation depends on observed state

Measure:

  • verified success,
  • false success,
  • UNKNOWN rate,
  • average cost,
  • p50/p95 latency,
  • model calls,
  • tool calls,
  • verifier calls,
  • search nodes,
  • cost per verified success,
  • rescue rate,
  • and marginal gain per additional unit of compute.

The dynamic scheduler should beat at least one fixed allocation frontier.

If it does not, keep the simpler policy.


Compare at the Same Maximum Envelope

A common experimental mistake is to give the adaptive system more total compute.

Then the result tells you nothing about scheduling quality.

Use the same maximum envelope.

Policy A max = $0.20 / 20 calls / 10 sec
Policy B max = $0.20 / 20 calls / 10 sec

Then compare what each policy does inside that limit.

Also compare average spend.

An adaptive scheduler may achieve equal verified success while using much less compute on easy tasks.

That is a genuine win.


Stratify by Task Difficulty

Average numbers can hide the scheduler’s actual behavior.

Break tasks into buckets:

easy
medium
hard
unresolvable
high-risk

A useful scheduler might show:

Difficulty Avg calls Verified success
Easy 2.1 98%
Medium 5.4 91%
Hard 11.8 74%
Unresolvable 4.0 UNKNOWN

That is healthier than giving every task twelve calls.

Especially notice the unresolvable bucket.

A good scheduler should learn to stop wasting compute when evidence suggests the task cannot currently be verified.


UNKNOWN Can Be a Budget-Saving Outcome

Suppose the system cannot access the external service needed to verify completion.

It has two options.

Bad runtime:

retry
retry
retry
stronger model
critic
retry

Good runtime:

required evidence unavailable
UNKNOWN
stop

UNKNOWN is not failure to be intelligent.

It is often the correct resource decision.


Budget Failures Need Their Own Taxonomy

Step 13 introduced failure-stage classification.

Budget scheduling adds another useful set of labels:

OVERSPEND
UNDERSPEND
VERIFY_STARVATION
PREMATURE_ESCALATION
LATE_ESCALATION
SEARCH_OVEREXPANSION
SEARCH_UNDEREXPANSION
CRITIC_OVERUSE
TOOL_OVERUSE
PREMATURE_STOP

These are not model-quality failures.

They are control-policy failures.

That distinction is essential when improving the system.


Log Expected and Actual Value

For every scheduler decision, capture both the estimate and the result.

{
  "event": "budget_allocation",
  "action": "frontier_escalation",
  "expected_success_gain": 0.18,
  "expected_cost_usd": 0.04,
  "actual_cost_usd": 0.05,
  "outcome_before": "FAIL",
  "outcome_after": "PASS",
  "policy_version": "scheduler-2026-08-09-a"
}

Over many runs, you can ask:

  • Which actions are overvalued?
  • Which are undervalued?
  • Where does predicted rescue probability disagree with observed rescue rate?
  • Which task classes consume budget without improving outcomes?

Now scheduler calibration becomes possible.


Calibration Matters

Suppose the scheduler predicts:

frontier escalation rescue probability = 0.8

But among 100 comparable cases, escalation rescues only 35.

The policy is badly calibrated.

That will cause overspending.

Similarly, if it predicts only 0.2 but rescues 70% of those cases, it may under-escalate.

This is the same calibration discipline from Step 15, now applied directly to resource allocation.

Useful measurements include:

  • reliability curves,
  • Brier score,
  • expected calibration error,
  • predicted vs observed rescue rate,
  • and predicted vs observed marginal gain.

Offline Replay Before Production

Trajectory logs from Step 13 let us test scheduler policies offline.

For each historical decision point:

state
available actions
remaining budget
recorded decision
recorded outcome

A candidate scheduler can propose a different allocation.

Some counterfactuals will be unknowable.

That is fine.

Do not fabricate outcomes.

Classify them as unavailable for exact offline evaluation.

Use:

  • replay where outcomes are known,
  • controlled benchmarks for uncertain cases,
  • shadow mode in production,
  • and then canary deployment.

Shadow the Scheduler

Before allowing a new scheduler to control production, run it in shadow mode.

production scheduler → actual action
candidate scheduler  → logged hypothetical action

Compare:

  • route differences,
  • escalation differences,
  • search-budget differences,
  • predicted cost,
  • expected verifier reserve,
  • and stop decisions.

This catches pathological policies before they spend real resources or change real environments.


Canary and Rollback

The deployment path should be boring:

offline benchmark
shadow
small canary
compare metrics
promote / rollback

Rollback should mean restoring a known scheduler version.

Not asking another model to “behave more conservatively.”

scheduler-2026-08-09-a
scheduler-2026-08-14-b
scheduler-2026-08-27-c

Version the control policy.


Pricing Changes Can Change the Optimal Architecture

This is an underappreciated point.

Suppose the frontier model price falls by 80%.

A routing policy that previously preferred local-model search may no longer be optimal.

Or suppose a local GPU becomes saturated and latency triples.

The scheduler may need to route more requests externally even if token price is higher.

Agent architecture is therefore partly economic.

The optimal policy depends on:

model quality
model price
latency
capacity
verification cost
tool cost
task distribution
risk tolerance

Those quantities change.

That is why the budget scheduler should be policy-driven and observable rather than buried inside prompts.


Use Pareto Frontiers, Not One Magic Score

A single reward number can hide important tradeoffs.

Instead, compare policies on a frontier:

verified success ↑
false success    ↓
cost             ↓
latency          ↓

Policy A may be cheapest.

Policy B may be fastest.

Policy C may provide the highest verified success.

The right deployment depends on product requirements.

There may be no universally best scheduler.


Different Tenants May Need Different Budgets

A low-cost interactive product and a high-value engineering workflow should not necessarily use the same scheduler.

For example:

interactive chat
  max latency: 3 sec
  max cost: $0.02
  moderate verification

code migration
  max latency: 10 min
  max cost: $2.00
  strong verification

production deployment
  max latency: 20 min
  max cost: $5.00
  very strong verification

The scheduler can share the same mechanism while operating under different envelopes.


Do Not Let the Scheduler Rewrite Safety

The budget scheduler may decide:

  • whether to search more,
  • whether to escalate,
  • whether to invoke a critic,
  • how many candidates to generate,
  • which verifier tier to use when several are allowed.

It should not decide:

  • whether authorization is required,
  • whether secrets may be accessed,
  • whether a sandbox can be bypassed,
  • whether a prohibited tool may be called,
  • whether mandatory verification can be skipped.

Those remain outside the optimization layer.

This boundary is worth repeating because “dynamic allocation” can otherwise turn into “the agent can choose which safeguards to spend on.”

No.


Dynamic Scheduling Can Simplify the Runtime

This may sound like another layer of complexity.

It can actually remove complexity.

Suppose your current architecture has:

always plan
always Best-of-N
always critic
always search
always frontier review
always verify twice

A scheduler may discover that most tasks only need:

cheap model
cheap tool evidence
verification

while a small fraction deserve the expensive path.

That means the sophisticated architecture still exists.

But it is sparse in use.

Only difficult tasks pay for difficult machinery.

This is one of the most important production patterns in advanced agents.


The Architecture Becomes Conditional

Instead of:

request
planner
search
critic
frontier
verifier

we get:

request
cheap path
verify
   ├── PASS → stop
   |
   └── unresolved
       scheduler
      /    |     \
 diagnostic search escalate
      \    |     /
       \___|____/
         verify

The architecture is no longer one fixed pipeline.

It is a set of mechanisms activated by evidence.


Metrics for a Production Budget Scheduler

At minimum, track:

Outcome metrics

verified success
false success
FAIL rate
UNKNOWN rate

Resource metrics

cost per task
cost per verified success
model calls
tool calls
search nodes
verifier calls
p50/p95 latency

Allocation metrics

frontier escalation rate
critic invocation rate
search activation rate
average search nodes when activated
verifier budget fraction
reserved budget consumed

Decision-quality metrics

escalation rescue rate
cost per rescue
premature stop rate
unnecessary escalation rate
search regret
verification starvation rate

Calibration metrics

predicted vs observed rescue
predicted vs observed success gain
predicted vs actual action cost

Without these, “adaptive budget” is just another opaque behavior.


A Complete Control Loop

The scheduler now connects the last several posts into one system:

production task
execution state
control policy
budget scheduler
allocate next computation
trajectory observability
external verification
verified outcome
offline benchmark
policy calibration
shadow / canary
new scheduler version

That is no longer a prompt trick.

It is a runtime optimization loop.


The Final Rule

The goal is not to consume the budget efficiently.

The goal is to achieve the required verified outcome with the smallest justified expenditure of resources.

That gives us the central rule for this stage:

Spend the next unit of computation where it has the highest expected value, reserve enough resources to prove success, and stop spending when additional work no longer earns its cost.

A sophisticated agent should not merely know how to think longer.

It should know when not to.

And if a cheap deterministic action can resolve the uncertainty better than another thousand tokens of reasoning, the scheduler should choose the cheap action.

That is what advanced control should look like.