Model contract¶
Purpose¶
This page specifies what the agent requires of a model, how it is asked, and how the answer is constrained.
It is deliberately written against capabilities rather than against one model, so that a different model can be substituted by meeting the contract. The concrete choice is a decision record, not a specification.
Required capabilities¶
A model satisfies this contract when it provides all of the following.
| Capability | Requirement | Why |
|---|---|---|
| Image input | At least one image per request, at a resolution where interface text is legible | The agent's only sensor |
| Adjustable image cost | The number of tokens an image consumes is selectable per request | The main latency dial (FR-MODEL-002) |
| Context length | Enough for the layout below plus a multi-hour session's compacted history | Long-horizon goals |
| Constrained output | Output restricted to a supplied grammar | FR-MODEL-003; the reliability mechanism |
| Prefix reuse | A previously computed prompt prefix is reused when unchanged | Otherwise every tick re-reads the whole prompt |
| Concurrent contexts | Two independent conversations against one set of weights | The two cadences differ in every respect |
| Selectable reasoning depth | Extended reasoning can be turned off | The tactical cadence cannot afford it |
The selected model family provides all of these. Its measured latency is not yet known — see open question 1.
One model, two cadences¶
The reasoning loop runs a fast cadence and a slow one. The intuitive arrangement is two models, a small one for speed and a large one for quality.
That is not what this specification does, for a measurable reason: within a model family, the small variants are substantially weaker at vision than the large ones, and the cadence that inspects the screen several times a second cannot be the one that sees worst.
Instead, one set of weights serves both cadences, differentiated by how it is asked:
| Tactical | Deliberative | |
|---|---|---|
| Rate | 1–4 Hz | Every 10–60 s |
| Image cost | Small | Large |
| Extended reasoning | Off | On |
| Context | Short, pinned | Longer, pinned |
| Output | One action | A plan revision |
Adjustable image cost and selectable reasoning depth exist precisely to support this. One set of weights in memory, two behaviours, no second model to load or to keep resident alongside the game.
Each cadence holds its own pinned context so that neither evicts the other. They have entirely different prefixes, and re-reading a long invariant prefix on every deliberation would consume the deliberative budget by itself.
Prompt layout¶
FR-CTX-001, FR-CTX-002, FR-CTX-003.
Ordered so that everything stable is on the left:
[1] System prompt, tool schemas, safety framing invariant for the session
[2] Goal, and the note block changes rarely
[3] Current plan and subgoal changes on replan
[4] Recent action history, as text changes per tick
[5] Current observation, as text changes per tick
[6] The annotated image LAST, always
Three rules, each load-bearing.
The image goes last. Everything to the right of a change must be recomputed. An image is the most expensive single element in the prompt, so placing it at the end means a changed image invalidates the least.
Old images are never resent.
FR-CTX-003.
Historical observations appear as their textual element digest, never as retained pictures.
This is what makes a multi-turn visual loop affordable at all: an agent that carried ten past frames would spend its entire context on them and still see less than the digests convey.
Blocks 1 and 2 are byte-identical between calls.
FR-CTX-002.
No timestamps, no tick counters, no reordered object keys, no elapsed-time strings.
A single changed byte discards the whole cached prefix, and since block 1 is the largest invariant part of the prompt, that is the difference between a cheap tick and an expensive one.
This is easy to violate by accident. Putting the current time into the system prompt is the classic version, and it costs the prefix on every single call.
Constrained output¶
FR-MODEL-003.
The grammar is regenerated every tactical tick and describes exactly what is valid right now:
- The tool names currently available.
- Their parameter types.
- The enumerated marks present in this observation.
- The enumerated grid cells, if the grid is in use.
So a reference to a mark that is not on screen is not merely unlikely — it cannot be produced. The same applies to an unknown tool name or a malformed parameter.
This converts a large class of runtime failure into a class of output that cannot be expressed, and it is the reason the contract requires grammar support rather than treating it as an optimisation.
When output nevertheless fails validation — a semantically invalid combination that the grammar cannot express — the agent issues one structured repair request naming the problem, and on a second failure records a no-op and advances the no-progress counters. It does not retry blindly, because a model that produced invalid output once under the same conditions will produce it again.
Sampling¶
| Cadence | Temperature | Notes |
|---|---|---|
| Tactical | Low | Consistency matters more than variety; the grammar already bounds the space |
| Deliberative | Moderate | Planning benefits from considering alternatives |
| Repair request | Lowest available | The task is to produce one specific correct form |
Every request records its sampling parameters and seed in the session recording, because replay determinism depends on them.
Memory management¶
FR-MODEL-004.
The model and the game share one graphics device, and the game was there first.
Available memory is polled, and when the game's headroom shrinks the agent degrades in a fixed order:
- Reduce the context length.
- Reduce the image cost for the tactical cadence.
- Move the deliberative cadence off the graphics device entirely.
- Pause and tell the user.
Step 3 is viable because of the shape of the chosen model: only a fraction of its parameters are active for any token, so processor-only execution reads a few gigabytes per token rather than the whole model. That yields single-digit to low-double-digit tokens per second on the reference processor — an estimate, not a measurement — which is acceptable for a call that fires twice a minute and whose result is applied asynchronously.
The model was chosen partly for that property: it degrades onto the processor gracefully, and the alternative to graceful degradation is a stuttering game.
Weight handling¶
FR-MODEL-005, INV-MODEL-001.
Weights are downloaded by the user, verified by digest before loading, and never modified.
The runtime version used to load them is pinned and recorded, because model file formats change and a mismatch between the version that produced a file and the version that reads it can fail silently — the file loads and the results are wrong.
Substituting a model¶
A different model is supported when it meets the capability table and passes the evaluation harness at no worse than the incumbent on grounding accuracy and action validity.
The agent must not contain anything that only works with one model. Where a model-specific detail is unavoidable — a chat template, a token budget encoding — it lives in one adapter and nowhere else.
Open questions¶
- Every latency figure on this page is missing, and the tactical cadence's rate follows directly from them. Measuring requires the model running on the reference hardware with a game in memory, since the figure without one is not the figure that matters. This blocks
NFR-MODEL-001and performance budgets. - Whether the vision encoder loads at all on the required compute backend for the intended variant. There is a known defect in this area on a different backend. Until checked, the tactical cadence has no confirmed implementation.
- Whether prefix reuse behaves as assumed with two pinned contexts at different image costs. If the runtime shares one cache between them, the two cadences evict each other and the layout above buys nothing.
- Whether image cost is selectable per request or only per session. The two-stage refinement in grounding needs per-request.
- Whether extended reasoning can be capped rather than merely switched off. Uncapped reasoning on the deliberative path is an unbounded pause.
- What the agent does when the model host reports a context overflow mid-session. Compaction should prevent it; "should" is not a mechanism.
Related decisions¶
ADR-0013 records constrained decoding, which this page turns into a hard requirement on the model host, and is accepted.
ADR-0006, the inference host and compute backend, and ADR-0007, the model selection, are not written and are blocked on the measurements above.