> This page is for Harness.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.moveworks.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.moveworks.com/_mcp/server.

# Processing Tool Responses

Every time a tool's action runs, its response goes through a processing step before the reasoning engine sees it. What the engine can do with that data depends on the response's size and format. This step happens after execution in each pass of the [reasoning loop](/harness/agentic-reasoning-engine/reasoning-loops), and its result is added to the [conversation history](/harness/agentic-reasoning-engine/conversation-history) for the rest of the conversation.

## Size limits

| Response               | Threshold                    | What happens                                                                                                                                                                                                                                                                                                    |
| ---------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Small                  | Up to 7K tokens (about 28KB) | Goes into the context window as-is. The engine reads the full payload and reasons over it directly.                                                                                                                                                                                                             |
| Large, structured JSON | Over 7K tokens               | Stored as a named variable. The engine sees a truncated preview and a JSON schema, and uses the [Code Interpreter](/harness/agentic-reasoning-engine/code-interpreter) to work with the full data. This is what triggers [Structured Data Analysis (SDA)](/tool-studio/core-concepts/structured-data-analysis). |
| Large, plaintext       | Over 7K tokens               | Goes into the context window as-is. No schema, no variable, no Code Interpreter.                                                                                                                                                                                                                                |
| Any                    | Over 100MB                   | Hard failure. The whole response is rejected, the tool returns nothing, and the user sees an error.                                                                                                                                                                                                             |

You can't change these thresholds.

## What happens to tool responses

#### Small responses pass through unchanged

A response under the threshold goes into the context window exactly as returned. Nothing is transformed or dropped.

#### Large structured responses use variable passing

When a response is over the threshold and is valid structured JSON, the engine stores the full dataset as a named variable. It generates a truncated preview and a JSON schema describing the structure, plus an instruction that the full data is available through the Code Interpreter. This keeps thousands of tokens of raw API data out of the context window while still giving the engine enough to reason about what came back.

Both the original action result and the engine's processed version are added to the conversation history. The engine sees enough to decide what to do next without spending its whole context budget on one large payload.

## Variable passing

Variable passing is how the engine handles structured data that is too large for the context window:

1. **Schema extraction.** The engine reads the JSON structure of the response and generates a JSON schema that describes its shape, field names, and types. This schema is the engine's map of what data is available.
2. **Text truncation.** The full response is cut down to a preview: the first few records, enough to show the shape and content of the data but not the whole dataset.
3. **Variable creation.** The engine stores the complete response as a named variable the Code Interpreter can access. The full dataset lives outside the context window but is available for code execution.
4. **Preview generation.** The preview, the schema, and a reference to the named variable are packaged together. This package is what enters the context window.
5. **Code Interpreter instruction.** The engine adds an instruction that the full dataset is available through the Code Interpreter tool. When it needs aggregations, filters, or analysis across all the data, it writes Python that runs against the complete variable.

This is the link between your tool's raw output and [SDA](/tool-studio/core-concepts/structured-data-analysis). When SDA runs on a large dataset, it works with the variable the engine created, not the truncated preview it saw in context.

> **Info**
>
> Variable passing only works with structured JSON. If an action returns a large plaintext string, the engine can't extract a schema, can't create a variable, and can't route to the Code Interpreter. The whole string goes into context as-is. This is why structured output mappers matter.

## Variable tracking

Variables also keep business data accurate across steps. The engine tracks the records and IDs that tools return as variables, so later tool calls use the exact values that came back. This gives you two benefits:

1. **IDs stay grounded.** The LLM can't hallucinate an ID or mix up IDs from different records, because variable tracking carries the real values from one tool call to the next.
2. **The engine can handle much more data.** Operations aren't limited by the size of the LLM's context window, so the Assistant can work across thousands of records and run calculations with the [Code Interpreter](/harness/agentic-reasoning-engine/code-interpreter).

![](https://files.readme.io/7a82d03669f36ebc390362e770ffc86bbdcfb48e74ea563292277a1d9489fd9a-CleanShot_2025-06-20_at_15.59.322x.png)

## Structured vs plaintext: two different paths

The format of your output mapper's response decides which path the engine takes, and that changes what it can do with your data.

**When your output mapper returns structured JSON**, the engine can parse it, extract a schema, sample a few objects, and send a compact version to the reasoner. The full dataset is stored as a variable. The engine can reason about the structure, and the Code Interpreter can run analysis on the complete data.

**When your output mapper returns plaintext** (for example, a RENDER string), the engine can't parse it. The whole string is forwarded to the reasoner as-is, which bloats the context when there's a lot of data. There's no schema extraction, no variable passing, and no Code Interpreter access.

Here is the same expense data through both paths.

**Plaintext path (RENDER):**

```yaml
output_mapper:
  expense_summary: |
    RENDER
    Here are your submitted expenses:
    {{#each data.expenses}}
    - {{this.description}}: ${{this.amount}} ({{this.category}})
    {{/each}}
    Total: ${{data.total_amount}}
```

The engine receives a rendered string. It can't parse the individual expense records, can't create a variable, and can't route to the Code Interpreter. The full text goes into context. With 500 expenses, that's 500 lines of text competing for the engine's attention.

**Structured path (MAP):**

```yaml
output_mapper:
  expenses:
    MAP():
      items: data.expenses
      converter:
        description: item.description
        amount: item.amount
        category: item.category
  total_amount: data.total_amount
  expense_count: data.expenses.$LENGTH()
```

The engine receives clean JSON. It extracts the schema, stores the full dataset as a named variable, and sends a truncated preview to the reasoner. If the user asks "What's my highest expense category?", the engine writes Python against the full variable instead of scanning 500 lines of text.

> **Warning**
>
> The RENDER version produces a string the engine can't work with. The MAP version produces structured JSON the engine can parse, store, and send to the Code Interpreter. That is the reason structured output mappers work better: the platform can work with JSON, but plaintext skips that handling entirely.

## display_instructions_for_model

One key gets special handling: `display_instructions_for_model`. When it is present in your output mapper's response, the engine pulls it out and passes it to the reasoner as a system-level instruction. It is not treated as data. It tells the engine how to interpret the data.

Use it to [steer SDA's analysis](/tool-studio/core-concepts/structured-data-analysis#steering-sda-with-instructions) without adding noise to the dataset. The engine separates the instructions from the data before either reaches the reasoner.

## Practical implications

You don't configure response processing, you don't see its logs, and you can't change its thresholds. But it shapes everything that happens next.

> **Warning**
>
> You can't control how the engine filters or truncates tool responses. You can control the shape of the data you give it. Return structured JSON from your output mappers, use `MAP()` to flatten and rename fields, and include `display_instructions_for_model` for baseline analysis rules. The better the output shape, the more the engine can do with it.

* **If the engine isn't referencing specific fields from a large response**, it is probably working from the truncated preview, not the full payload. Put the most important data first, or use compound actions to filter the data before it reaches this step. See [The Golden Rule](/tool-studio/guides/best-practices/the-golden-rule).
* **If SDA isn't running**, your output might be under 7K tokens, or it might not be valid structured JSON. Check both. Data embedded inside a string field (`"data": "{\"accounts\": [...]}"`) won't take the structured path. If your API returns stringified JSON, parse it in your output mapper.

## What to Read Next

#### [Structured Data Analysis](/tool-studio/core-concepts/structured-data-analysis)

How SDA runs on large datasets and how to design your output for code execution.

#### [What Goes Into a Turn](/harness/agentic-reasoning-engine/how-the-reasoning-engine-works)

What the engine reads on every turn, and where this step fits in the loop.

#### [The Reasoning Loop](/harness/agentic-reasoning-engine/reasoning-loops)

How planning, execution, and user feedback fit together.

#### [The Golden Rule](/tool-studio/guides/best-practices/the-golden-rule)

Why attention matters, and how to move logic out of the LLM with resolvers, compound actions, and output mappers.

#### [Output Mapper Reference](/api-reference/configuration-languages/moveworks-bender-language-reference)

MAP(), RENDER, FILTER(), and the full data mapper syntax for shaping action outputs.