Context and Budgets
An agent reasons inside a context window, and a run has a budget. This page describes what the model sees on each turn, how large data stays out of the prompt, what a run is allowed to spend, and what happens at the limit.
What the model sees each turn
Every iteration, the model receives one prompt made of:
| Part | What it holds | Bounded by |
|---|---|---|
| The objective | Your words, unchanged for the life of the run | You. It is never trimmed |
| The tools | Each declared tool with its parameters and their descriptions | The tools you declared |
| The history | Earlier thoughts, actions, and results | The context strategy below |
| Evidence | Trusted facts the runtime attaches, such as the counts from a matcher | The runtime |
| Guidance | Warnings, hints from stuck detection, a pending human answer | The runtime |
The model answers with one action, and the runtime executes it. The model's reply itself is capped per turn, so it cannot emit a large document or thousands of rows in one call.
Keeping history bounded
As iterations accumulate, the history is the part that grows. context_window_strategy chooses what to do about it:
| Strategy | Behaviour |
|---|---|
full |
Keep everything. The default, right for short runs |
sliding_window |
Keep the most recent iterations in full and drop the rest |
summarize |
Compact older iterations into a summary and keep the recent ones in full |
hybrid |
A compact list of older steps plus the recent ones in full |
token_aware |
Fit the history into half of max_context_tokens, compacting the oldest first |
{
"context_window_strategy": "token_aware",
"max_context_tokens": 16000
}
Compaction keeps action names and outcomes, so a compacted step still tells the model what was tried and what came back. Prompt compaction is separate from the trace returned with the run.
Keeping tool results bounded
A tool can return more than the model should read. Every result is bounded before it enters the history:
- A result over a fixed size is cut. What remains is a summary of its top-level values, including counts and the lengths of any lists, plus the first part of the result as a preview, and a marker saying how much was cut.
- Results from the matcher and the N-way matcher also reach the model as evidence, separate from anything the model wrote. The model's claims are checked against that evidence: it cannot call a match clean while exceptions exist, or report discrepancies that the evidence does not contain.
The model sees enough to decide what to do next. The complete result stays in the run for the steps and people that follow.
Keeping large data out of the prompt
Rows and documents do not have to pass through the model at all.
- Documents by reference. A tool parameter can take a document reference such as
doc:doc_ā¦instead of the content. The runtime resolves the reference to the document's rows when it runs the tool, so the rows go from storage to the tool and never into the model's context. Name documents by id in the objective and tell the model to pass references; adoc:reference written into the objective itself is expanded there in full, which is right for a short document and wrong for a large one. - Workflows for volume. When the work is deterministic and the data is large, run it as a workflow step and give the agent only the exceptions. A matcher step over thousands of rows, followed by an agent over the handful that did not reconcile, is the shape every reconciliation case in the catalog uses.
- Tables instead of pastes. A tool that reads from a custom table lets the model ask for the slice it needs rather than receive everything.
For a worked example with three 5,000-row documents, see N-way match, end to end.
Memory within a run
The history is what the model is shown; memory is what the model chooses to keep. Two built-in tools, always available, hold key-value pairs for the life of the run:
__store_memory__saves a value under a key.__retrieve_memory__reads it back.
Memory is not in the prompt. It is read on demand, so a value stored on iteration two is still available on iteration forty after the history that produced it has been compacted, and it survives a pause for a person. It ends with the run. Use it for a running tally, a list of ids already handled, or a conclusion the model wants to hold onto without re-deriving it. See Built-in Tools for the call shapes.
For anything that must outlive the run, write it to a custom table through a declared tool. The next run, or a person, reads it there.
Context across runs
A run can start from what an earlier run concluded. Pass previous_run_id when launching, and the runtime injects a condensed account of that run into the new prompt: its objective, its final answer, its confidence, and the key steps. The condensation is fixed and small: a trace longer than five steps is reduced to its first two and last three, the answer is capped, and each step's result is cut to a line. The full trace of the earlier run stays retrievable on that run's record.
{
"objective": "Review the prior audit findings and recommend next steps",
"tools": [{ "type": "action", "name": "reviewer" }],
"previous_run_id": "agent-ā¦"
}
This is also how a run that stopped at a limit continues: launch a new run with the stopped run as previous_run_id and a narrower objective, rather than re-running from nothing. Memory does not carry across; a conclusion the new run needs should be in the earlier run's final answer or in a table.
What a run may spend
Every run carries a durable budget, checked before each model call. The organization's defaults apply unless the run sets its own:
| Limit | Default | Meaning |
|---|---|---|
max_input_tokens |
100,000 | Total prompt tokens across the run |
max_output_tokens |
50,000 | Total reply tokens across the run |
max_total_tokens |
150,000 | Both together |
max_llm_calls |
100 | Model calls in the run |
max_wall_time_ms |
300,000 | Five minutes from the first call |
max_cost_usd |
none | Spend, when you give input_cost_per_million and output_cost_per_million |
{
"llm_budget": {
"max_input_tokens": 60000,
"max_llm_calls": 20,
"max_cost_usd": 0.50,
"input_cost_per_million": 0.15,
"output_cost_per_million": 0.60
}
}
The budget sits beside the older limits, which still apply: max_iterations (default 10), timeout_ms (default five minutes), and stuck detection. A run that reaches its iteration limit ends as max_iterations, or, with max_iterations_policy: "accept_partial", completes with its latest successful result and partial_output: true.
When these settings are chosen
Everything on this page is fixed when a run starts. An agent inside a workflow takes its strategy, budget, and limits from the step definition; a standalone agent takes them from the launch request; a Process Studio case carries them in its content, where the process owner can change them for the next run. Nobody switches a strategy on a run in flight, and there is no need to: a run started with max_iterations: 40 should be started with token_aware history, and a run started with the defaults never grows past what full can hold.
What a person can do while a run is in flight is narrower and deliberate: answer a pause, resume a paused run with new instructions, or cancel it. What they can do after it stops is start the next run from its record with previous_run_id.
How a run ends at a limit
| Status | What happened |
|---|---|
budget_exceeded |
The next model call would have crossed a budget line. The call was not made. The reason names the limit |
max_iterations |
The iteration cap was reached without __complete__ |
timeout |
timeout_ms passed |
stuck |
Stuck detection chose to stop |
Each is a terminal status with the trace intact, so the record shows exactly how far the run got and why it stopped. None of them spend anything further.
Rules of thumb
- Put instructions in the objective, and data behind references or tools.
- Set the history strategy with the iteration cap:
fullup to about ten iterations,token_awarebeyond it. - Give every tool a description that says what it returns and how large that can be.
- Set a cost cap on any run a person is not watching.
- Keep what a later run will need in the final answer or a table, not in memory.
- Let a workflow do the volume and the agent do the judgment.
ā Next: Deployment Patterns