Skip to main content
Advanced/compatible programmatic examples. Fragments illustrate mechanisms; HostEnv or workspace does not provide isolation. New projects start with Quickstart, Session and explicit resource configuration.
The Engine provides two complementary mechanisms for controlling the run lifecycle:
  • Critics (step-level validators) validate each step after reduce() runs. They can allow the run to continue, force a stop, or trigger a retry of the current step.
  • Stop criteria (loop-termination rules) are checked after critics pass. They evaluate state and runtime metrics to decide whether to end the loop.

Critics

A critic receives the current state, the decision (the model’s structured output for a step) taken, and the action (the tool call dispatched based on the decision) results, then returns a structured verdict dict.

The Critic contract

Illustrative fragment (not a standalone program; use the complete example linked on this page).

Supported critic actions

Any action value other than "stop" or "retry" is treated as "continue".

Adding critics to a run

Pass a list of Critic instances to agent.run(): Illustrative fragment (not a standalone program; use the complete example linked on this page).
Or pass them when constructing the Engine directly: Illustrative fragment (not a standalone program; use the complete example linked on this page).

Writing a custom critic

Illustrative fragment (not a standalone program; use the complete example linked on this page).
The critic outputs are recorded in the trace (the structured run log) as step.critic_outputs and visible in the qita board Critic section for each step.

Stop criteria

Stop criteria are evaluated after every step’s critic pass. Each criterion receives the current state, the step count, and a runtime info dict (with elapsed_seconds).

The StopCriteria contract

Illustrative fragment (not a standalone program; use the complete example linked on this page).

Built-in criteria

QitOS ships four built-in criteria in qitos.engine.stop_criteria: FinalResultCriteria (default) Stops when state.final_result is set to a non-empty string. It is the only criterion used when you do not pass stop_criteria to the Engine. Illustrative fragment (not a standalone program; use the complete example linked on this page).
MaxStepsCriteria Stops when the step count reaches max_steps. The Engine applies this automatically from the RuntimeBudget — you rarely need to instantiate it manually. Illustrative fragment (not a standalone program; use the complete example linked on this page).
MaxRuntimeCriteria Stops when wall-clock time exceeds a threshold. Illustrative fragment (not a standalone program; use the complete example linked on this page).
StagnationCriteria Stops when state has not changed for max_stagnant_steps consecutive steps. Uses a signature function to detect change (defaults to checking final_result and phase). Illustrative fragment (not a standalone program; use the complete example linked on this page).
MaxTokensCriteria Stops when cumulative token usage exceeds a budget. The Engine passes total_tokens in runtime_info on each step, so this criterion tracks real token consumption across the entire run. Illustrative fragment (not a standalone program; use the complete example linked on this page).
Use this when you need a hard token budget independent of step count or wall-clock time. Pair it with gold preset advisory values: Illustrative fragment (not a standalone program; use the complete example linked on this page).
Illustrative fragment (not a standalone program; use the complete example linked on this page).

Passing criteria to a run

Illustrative fragment (not a standalone program; use the complete example linked on this page).
When you pass stop_criteria, you replace the default FinalResultCriteria. If you still want the run to stop when final_result is set, include FinalResultCriteria() in your list.

Writing a custom criterion

Illustrative fragment (not a standalone program; use the complete example linked on this page).

Budget-based stopping with TaskBudget

For structured task definitions, use TaskBudget to express all three budget dimensions together: Illustrative fragment (not a standalone program; use the complete example linked on this page).
The Engine applies TaskBudget values to its internal RuntimeBudget before the run starts, overriding any constructor defaults.

StopReason values

StopReason is a string enum in qitos.core.errors. The value is written to state.stop_reason at the end of every run. Check result.state.stop_reason after a run to distinguish a successful completion from a budget exhaustion: Illustrative fragment (not a standalone program; use the complete example linked on this page).