> ## Documentation Index
> Fetch the complete documentation index at: https://docs.engini.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Work with large tool results

> Drill into a big payload with handles, dot-paths and projections - instead of paying for all of it.

<Info>**Uses:** CLI</Info>

When a tool returns more than 4 KB, the CLI stores the payload locally and hands back a **handle** plus a shape preview, rather than printing everything. For an agent this is the difference between spending a few hundred tokens and blowing the context window on one call.

```bash theme={null}
engini tools call crm_list_contacts --args '{}'
# -> { "handle": "h42", "shape": { "items": { "type": "array", "length": 2841, ... } }, "preview": { ... } }
```

You now know the response is 2,841 items and what one looks like - without having read any of it.

## Pull only what you need

```bash theme={null}
engini tools result h42 --select items.email          # a dot-path; maps over the list
engini tools result h42 --fields id,name,email        # project keys, per item
engini tools result h42 --select items --offset 0 --limit 20   # page the list
engini tools result h42 --select items[0].address.city         # index into it
engini tools result h42 --full                        # the entire payload
```

`--select` applied to a list **maps over it**, so `items.email` returns every email rather than erroring. A path that doesn't exist yields `null` instead of throwing - safe to probe.

## Manage the sandbox

```bash theme={null}
engini tools result --list     # known handles, newest first, with age and size
engini tools result --clear    # wipe them
```

Stored results live under `$XDG_CACHE_HOME/engini/results/` (`%APPDATA%` on Windows), auto-pruned to the 20 most recent and anything older than 24h.

<Warning>
  Handles are **short-lived and local**. They don't survive a pruning, another machine, or a CI runner that gets torn down. Drill in during the same session; if you need the data later, write it to a file with `--full`.
</Warning>

## Bypassing it

```bash theme={null}
engini tools call crm_list_contacts --args '{}' --inline        # full payload inline
engini tools call crm_list_contacts --args '{}' --max-bytes 0   # never spill
engini tools call crm_list_contacts --args '{}' --raw           # verbatim output, no envelope
```

Use these in [CI](/examples/ci-automation), where you want the whole thing in a file. Keep the default when an agent is driving.

## Why this matters for agents

The wrong pattern is a tool call returning 2,841 contacts straight into the model's context. The right one is three cheap steps:

```bash theme={null}
engini tools call crm_list_contacts --args '{}'                   # 1. shape + preview
engini tools result h42 --select items --fields name,email --limit 25   # 2. just enough
engini tools result h42 --select items.email                      # 3. the specific field
```

The model sees a summary, then requests precisely the slice it needs. Pair it with `--llm openai|anthropic`, which formats a result as that vendor's tool-result message so it can be handed straight back into the conversation:

```bash theme={null}
engini tools call crm_get_contact --args '{"id":"123"}' --llm anthropic --tool-call-id call_1
```

## In the SDKs

There's no handle mechanism in the SDKs - you already hold the object in memory, so slice it in your own language. Handles exist because the CLI's boundary is a pipe, where "hold it and slice it later" isn't otherwise possible.
