Request runner, field by field
Understand step mappings, model-selection precedence, context reserves, timeouts, and external instruction files in ABot 1.8.1.
On this page
The request-runner file controls how ABot invokes its registered model steps. It chooses step targets, reserves input headroom, sets step timeouts, and attaches Markdown guidance. It does not define providers, install tools, or choose the Supervisor versus Execution Agent route. Those belong in the main configuration and model configuration.
This reference follows the published 1.8.1 implementation. Keep your generated configuration as the starting point; examples below explain edits rather than replacing your installation wholesale. For a reproducible tuning exercise, continue with model calibration.
Locate the file and identify its version
The main runtime.config.json points to the runner. This is a main-file fragment:
{
"requestRunner": {
"configRef": "./request-runner.config.json"
}
}
This path resolves relative to the main configuration file. Instruction paths inside the runner then resolve relative to the runner file. Neither uses your terminal’s current directory.
The published version-2 starter is a complete runner document:
{
"schemaVersion": 2,
"models": {
"defaults": {
"profileId": "default",
"steps": {
"supervisor.response": "default",
"worker.result": "default",
"execution.response": "default",
"tool_payload.raw": "toolPayload.raw"
}
}
},
"context": {
"outputReserveTokens": 4096,
"safetyReserveTokens": 1200,
"attachmentReserveTokens": 1024
},
"stepDefaults": {
"timeoutMs": 90000
},
"steps": {
"supervisor.response": {
"instructionRefs": [
"../methodologies/response-ux.md",
"../methodologies/memory-informed-response.md"
]
},
"execution.response": {
"instructionRefs": [
"../methodologies/response-ux.md",
"../methodologies/memory-informed-response.md"
]
}
}
}
Here, default must be a registered model profile and both Markdown files must exist at the resolved paths. The ../methodologies/ paths fit the starter layout with the runner inside local/; onboarding can generate another layout and rebase them. Preserve the paths generated for your installation.
Version 2 requires exactly the five top-level keys shown. models contains only defaults; its defaults contain only profileId and steps. Each reserve and timeout must be a positive integer, not a string, fraction, or zero. The displayed numbers are shipped values—not fallback values you get by omitting required fields.
Existing legacy files
No schemaVersion means legacy v1; explicitly writing "schemaVersion": 1 is invalid. Legacy files have only models, context, and steps, with explicit mappings and timeouts for the original 13 steps. The later capability.controls and learning.batch steps may be absent and receive identity mappings and 90,000 ms timeouts during normalization.
Version 2 makes both step maps sparse: omitted mappings become the step’s own name; omitted timeout entries inherit stepDefaults.timeoutMs. When migrating, retain existing nonidentity mappings, custom timeouts, and instruction references. Add schemaVersion: 2 and stepDefaults; remove redundant entries only after comparing their values. Upgrading the package is not permission to overwrite your working configuration.
Two different maps named steps
They operate at different layers:
| Path | Purpose |
|---|---|
models.defaults.profileId |
Default concrete model-profile ID for request execution. Required and nonempty. |
models.defaults.steps |
Maps each registered step to a model profile, invocation profile, or calibration-slot name. Values are nonempty strings. |
Top-level steps |
Per-step timeoutMs and/or instructionRefs. No generation settings or model IDs here. |
stepDefaults.timeoutMs |
Required version-2 timeout inherited by steps without their own timeout. |
Both maps accept only registered step IDs. In 1.8.1 these are:
| Area | Exact step IDs |
|---|---|
| Supervisor | supervisor.decision, supervisor.response |
| Worker | worker.decision, worker.result |
| Planning and review | planner.decision, planner.graph, reviewer.decision |
| Execution Agent | execution.decision, execution.response, auditor.decision |
| Supporting work | capability.controls, degraded.finalization, context.compact, tool_payload.raw, learning.batch |
This is a registry, not a promise that every request calls every step. Adding an invented name does not create a new role or workflow stage.
Preserve the starter’s four nonidentity mappings
The three response/result steps explicitly target the model profile default. tool_payload.raw explicitly targets the calibration slot toolPayload.raw. The underscore on the left and camel case on the right are intentional.
All omitted mappings normalize to their own name. For example, worker.decision targets worker.decision. Unless that name is also a concrete profile, it means: select the effective model, then look for that model’s calibration["worker.decision"].
If the selected model lacks the slot, its base configuration remains in use. Explicit custom slot names must exist in at least one registered model, but validation does not guarantee that every selectable model implements them. Avoid naming model profiles after semantic slots: a target matching an invocation profile or model profile is treated as direct selection, not as calibration.
Which model actually runs?
Ordinary requests build a policy from the main model catalog plus this runner. The runner replaces the catalog’s default profile and step map; catalog defaults.roles is not copied into that request policy. The main catalog’s defaults.context and defaults.overrideClientPreference remain relevant.
Selection proceeds as follows:
- Resolve a configured step target as an invocation profile or concrete model. If it is a calibration-slot name instead, use the runner’s default model as the configured candidate.
- Resolve any applicable client model preference, such as a UI selection. A preference scoped to
maindoes not apply to utility-lane steps (context.compact,tool_payload.raw,learning.batch); scopealldoes. Lane and role are different:capability.controlsandexecution.responseuse the main lane even though their role is utility. - Normally the client preference wins. With main-config
models.defaults.overrideClientPreference: true, the configured candidate wins instead. - If the step targets a calibration slot, apply that slot from the selected model. The model-file reference explains its generation/context overrides and optional explicit model redirection.
A worked selection example
Assume the main catalog already contains model profiles local, hosted, and review-model. Merge this runner fragment, retaining your other mappings:
{
"models": {
"defaults": {
"profileId": "local",
"steps": {
"worker.decision": "worker.decision"
}
}
}
}
| Request state | Effective Worker configuration |
|---|---|
| No client preference | local plus its worker.decision calibration, if present. |
Client selects hosted, ordinary precedence |
hosted plus its own worker.decision calibration—not the local model’s slot. |
Client selects hosted, main overrideClientPreference: true |
local plus its slot. |
Now change that one mapping to "worker.decision": "review-model". With ordinary precedence, an applicable client preference can still win. With overrideClientPreference: true, the configured review-model wins. Direct profile selection also bypasses semantic worker.decision calibration for this mapping; use an invocation profile when you intentionally need a named profile with invocation overrides.
The override flag belongs in the main config, not this runner, and affects configured selection across requests—not just one Worker call. Do not enable it merely to hide an unexplained model-selection mismatch.
Context headroom: what the three numbers do
| Field | Shipped value | Actual role |
|---|---|---|
outputReserveTokens |
4096 |
Leaves room for generated output by reducing the admissible input. Does not set a provider output-token limit. |
safetyReserveTokens |
1200 |
Further reduces admissible input to leave estimation headroom. |
attachmentReserveTokens |
1024 |
Adds this estimate per attachment to estimated input. It is not one flat reserve for the request. |
Physical capacity comes from the effective model’s contextWindowTokens. Ollama’s configured options.num_ctx can reduce the effective window; a larger runner reserve or model declaration cannot allocate unavailable capacity. Token estimation and structured-format accounting belong in model context, not runner context.
At admission, the implementation calculates:
available input = effective window − output reserve − safety reserve
− early configured-instruction reserve, when applicable
estimated input = estimated messages
+ attachment count × attachment reserve
+ structured-format reserve
fits = available input > 0 AND assessed input ≤ available input
For a 32,768-token effective window, the starter leaves 27,472 tokens before any early instruction reserve. As an illustrative estimate, 20,000 message tokens, two attachments, and 500 format tokens total 20,000 + 2 × 1,024 + 500 = 22,548. This fits; it is arithmetic, not a measured model benchmark.
When a structured format is present and accounting mode is not none, its reserve is the estimated JSON schema plus fixedOverheadTokens. Without a format, that reserve is zero. A valid provider-measured input count, when available, replaces the estimated count for the comparison; it is not added to it.
Configured Markdown guidance is reserved early, before history selection. Once appended to the actual messages, final admission counts it there rather than subtracting the early reserve again. A large methodology still consumes context even though it lives outside the model file.
There is also an earlier configuration check: each model’s effective capacity must exceed output + safety + one attachment reserve + the larger of its profile/default fixed format overhead. With the starter reserves and no fixed overhead, that total is 6,320. Passing this check does not prove a real prompt fits; actual prompts, schemas and multiple attachments still require admission checks.
Eligible reducible context has a separate compaction trigger at ceil(window × 0.7). It does not mean all input is disposable: exact-context calls and context.compact itself are excluded, and compaction depends on the available controller. Irreducible content can still exceed the budget. Do not treat lower reserves as a substitute for realistic capacity or shorter instructions.
Timeouts: three layers, different meanings
To give graph generation longer, merge this runner fragment into top-level steps, preserving existing entries:
{
"steps": {
"planner.graph": {
"timeoutMs": 180000
}
}
}
The ordinary step timeout resolves in this order:
timeoutMsin the selected model’s matching calibration slot, if present.- This runner’s explicit step timeout.
- Version-2
stepDefaults.timeoutMsfor a step without an override.
Thus a 60,000 ms planner.graph calibration timeout can still win over the 180,000 ms runner value. Direct model/invocation-profile targets do not resolve a semantic calibration timeout.
These are not the same as the whole-request deadline or stream-inactivity watchdog. In 1.8.1, the request lifecycle reads LLM_RUNTIME_REQUEST_TIMEOUT_MS and LLM_RUNTIME_REQUEST_INACTIVITY_TIMEOUT_MS from the process environment; absent, both are disabled. The default model client separately has a 90,000 ms stream-inactivity timeout, overridable through its wired main-config setting. Extending a step does not disable those outer limits. The main-file reference distinguishes these consumers from timeout fields that are loaded but not wired into ordinary request execution.
Attach operating guidance with instructionRefs
Use model calibration.instructions for a model-specific correction; use runner instructionRefs for a methodology attached to a particular step. They supplement existing contracts, not replace them or grant new tool permissions.
Suppose your layout is:
my-abot/
local/request-runner.config.json
methodologies/response-ux.md
methodologies/memory-informed-response.md
methodologies/source-reporting.md
An intentionally short source-reporting.md might contain:
When reporting research, distinguish retrieved evidence from inference.
Include source URLs that were actually retrieved.
If sources disagree, state the disagreement instead of inventing consensus.
Add it to a response step with this runner fragment. Keep the existing references because replacing a JSON array does not automatically merge its previous contents:
{
"steps": {
"supervisor.response": {
"instructionRefs": [
"../methodologies/response-ux.md",
"../methodologies/memory-informed-response.md",
"../methodologies/source-reporting.md"
]
}
}
}
This affects supervisor.response only. If you want the same guidance for execution.response, configure that step separately. planner.decision and planner.graph are similarly distinct.
The loader accepts relative or absolute local .md paths, reads UTF-8, trims content, and removes repeated reference strings while preserving their first order. Each configured list must contain 1–8 unique references; each trimmed file must contain 1–32,000 characters; combined file content must not exceed 48,000 characters per step. These are character limits, not token budgets. Missing, unreadable, empty, oversized or non-Markdown files fail loading.
The files are joined in order with separators and appended once to the first existing system message under “Configured operating methodology.” The accompanying contract explicitly preserves the runtime’s available actions, roles, capabilities and output schema. Use trusted guidance, not copied external text that could contain conflicting instructions.
To remove guidance, omit instructionRefs; an empty array is invalid. If a version-2 step then has neither a timeout nor references, remove the whole step entry. Top-level "steps": {} is valid; "steps": { "worker.decision": {} } is not.
Apply, verify, and troubleshoot
Runner files and instruction contents are cached for the running process. Editing a Markdown file or refreshing the browser is not sufficient. Use the configuration workspace’s apply/restart flow when idle, or restart your local runtime through its normal launch procedure, then make a fresh test request.
| Symptom | Check first |
|---|---|
| “Must contain exactly…” | Missing required version-2 keys, extra model settings in the runner, or a legacy/v2 mixture. |
| Unknown model/slot target | The target ID, registered profiles, and whether a custom slot exists in any model. Identity mappings are allowed without explicit slots. |
| Valid slot, but tuning has no effect | The UI selected another model, that model lacks the slot, or the target collides with a profile name. |
| Timeout change appears ignored | Selected model calibration, request environment limits, then stream inactivity. |
| Instruction file cannot be read | Resolve its path from the runner directory; check extension, permissions and content limits. |
| Context-capacity validation fails | Actual effective model capacity, Ollama allocation, and all reserves—not just the visible chat length. |
Change one concern at a time. Confirm the selected model and step, use a small representative task, inspect the actual result, and retain a working configuration to return to. For tuning temperature, reasoning and short model-specific instructions, use the calibration walkthrough.