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
json
{
  "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; a doc: 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.

json
{
  "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
json
{
  "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: full up to about ten iterations, token_aware beyond 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