| title | Offload Response Structure |
|---|---|
| diataxis_type | reference |
This document specifies the exact dict structure returned by LROOffloader.offload_if_needed (and by extension, lro_offload and LROContext) when offloading activates.
offload_if_needed returns one of three possible outcomes:
| Condition | Return value |
|---|---|
enabled is False |
Original data dict, unchanged. |
estimate_size(data) <= threshold |
Original data dict, unchanged. |
| Threshold exceeded, write succeeds | Offload descriptor (documented below). |
| Threshold exceeded, write fails | Fallback response (documented below). |
When offloading activates and all JSONL writes succeed, the returned dict has the following structure:
| Field | Type | Description |
|---|---|---|
offloaded |
bool |
Always True. |
| (inline keys) | (varies) | Zero or more keys copied verbatim from the original data dict, as specified by the inline_keys parameter. |
summary |
dict[str, dict[str, Any]] |
Per-section summary produced by each section's summarizer. |
files |
dict[str, str] |
Per-section mapping of section key to absolute file path string. |
schemas |
dict[str, dict[str, Any]] |
Per-section schema information. |
jq_recipes |
dict[str, str] |
Merged dict of all sections' jq extraction recipes. |
guidance |
str |
Auto-generated advisory text for the consuming LLM. |
Fields appear in this order in the returned dict:
offloaded- Inline keys (in the order specified by
inline_keys, if present indata) summaryfilesschemasjq_recipesguidance
"offloaded": TrueAlways True. Use this field to detect whether a response has been offloaded.
Keys listed in the inline_keys parameter are copied from the original data dict into the offload descriptor. Only keys that exist in data are included; missing keys are silently skipped.
# Given inline_keys=["query", "total_count"] and data={"query": "test", "total_count": 500, ...}
"query": "test",
"total_count": 500,"summary": {
"results": {"count": 247},
"metadata": {"count": 15},
}A dict mapping each section key to the output of that section's summarizer function.
Default summarizer output:
| Items type | Output |
|---|---|
list |
{"count": len(items)} |
dict |
{"count": len(items)} |
| Other | {} |
Custom summarizers (set via OffloadSection.summarize) can return any dict[str, Any].
Sections whose key is not present in the original data are omitted from the summary.
"files": {
"results": "/tmp/mcp-lro/search-sess_001-20260325T225815Z-a1b2c3d4.jsonl",
"metadata": "/tmp/mcp-lro/meta-sess_001-20260325T225815Z-a1b2c3d4.jsonl",
}A dict mapping each section key to the absolute file path (as a str) of the written JSONL file.
- Paths are resolved (
Path.resolve()) before inclusion. - Sections whose key is not in
dataare omitted. - Sections that fail the path traversal security check are omitted.
"schemas": {
"results": {
"description": "Line 1 is header metadata. Lines 2+ are data objects.",
"line_schema": {"id": "string", "title": "string", "score": "number"},
},
}A dict mapping each section key to a schema descriptor with two fields:
| Sub-field | Type | Source |
|---|---|---|
description |
str |
OffloadSection.schema_description |
line_schema |
dict[str, Any] |
OffloadSection.schema |
"jq_recipes": {
"list_all_results": "tail -n +2 '{results_file}' | jq '.'",
"count_results": "tail -n +2 '{results_file}' | jq -s 'length'",
"first_10_results": "tail -n +2 '{results_file}' | head -10 | jq '.'",
}A merged dict of all sections' jq recipes. The file path placeholder in each recipe is {section_key_file} (e.g., {results_file}).
Recipe sources:
- If
OffloadSection.jq_recipesis provided, those recipes are used as-is (no placeholder substitution is performed by the library on custom recipes). - If
OffloadSection.jq_recipesisNone, three auto-generated recipes are produced per section. See OffloadSection.get_jq_recipes.
When multiple sections produce recipes, all are merged into a single dict. If two sections produce recipes with the same name, the later section's recipe overwrites the earlier one.
"guidance": (
"Results offloaded to JSONL (2 section(s): results, metadata).\n"
"Files:\n"
" - results: /tmp/mcp-lro/search-sess_001-20260325T225815Z-a1b2c3d4.jsonl\n"
" - metadata: /tmp/mcp-lro/meta-sess_001-20260325T225815Z-a1b2c3d4.jsonl\n"
"\n"
"Use the jq_recipes above to extract specific data, or read files directly.\n"
"Header line (line 1) contains metadata; data objects start at line 2."
)Auto-generated advisory text. Format:
Results offloaded to JSONL ({N} section(s): {comma-separated section keys}).
Files:
- {key1}: {path1}
- {key2}: {path2}
Use the jq_recipes above to extract specific data, or read files directly.
Header line (line 1) contains metadata; data objects start at line 2.
The guidance is always present when offloading succeeds. It is a plain string, not Markdown.
Given:
data = {"query": "test", "total_count": 500, "results": [... 247 items ...]}inline_keys = ["query", "total_count"]sectionswith one section: key"results", prefix"search", default summarizer
{
"offloaded": True,
"query": "test",
"total_count": 500,
"summary": {
"results": {"count": 247},
},
"files": {
"results": "/tmp/mcp-lro/search-sess_001-20260325T225815Z-a1b2c3d4.jsonl",
},
"schemas": {
"results": {
"description": "Line 1 is header metadata. Lines 2+ are data objects.",
"line_schema": {"id": "string", "title": "string", "score": "number"},
},
},
"jq_recipes": {
"list_all_results": "tail -n +2 '{results_file}' | jq '.'",
"count_results": "tail -n +2 '{results_file}' | jq -s 'length'",
"first_10_results": "tail -n +2 '{results_file}' | head -10 | jq '.'",
},
"guidance": "Results offloaded to JSONL (1 section(s): results).\nFiles:\n - results: /tmp/mcp-lro/search-sess_001-20260325T225815Z-a1b2c3d4.jsonl\n\nUse the jq_recipes above to extract specific data, or read files directly.\nHeader line (line 1) contains metadata; data objects start at line 2.",
}When the JSONL write fails due to an OSError or TypeError, the method:
- Logs the error.
- Attempts to delete the partial file (suppressing any
OSErrorduring deletion). - Returns the original data dict with an appended warning field.
{**data, "lro_warning": "Offload failed: {exception_message}"}Fields:
| Field | Type | Description |
|---|---|---|
| (all original data keys) | (varies) | The complete original data dict, spread into the return value. |
lro_warning |
str |
Error message in the format "Offload failed: {str(exc)}". |
{
"query": "test",
"total_count": 500,
"results": [... original items ...],
"lro_warning": "Offload failed: [Errno 28] No space left on device: '/tmp/mcp-lro/search-sess_001-20260325T225815Z-a1b2c3d4.jsonl'",
}The fallback triggers on:
OSErrorduring file write (disk full, permission denied, etc.)TypeErrorduring JSON serialization (non-serializable objects in data lines)
The fallback does not trigger on:
- Output directory errors (symlink check, creation failure) -- these are caught earlier and return
dataunchanged. - Path traversal failures for individual sections -- those sections are skipped; other sections may still succeed.
If none of the declared sections' keys exist in data, the offload descriptor is still returned with empty files, schemas, summary, and jq_recipes dicts, and offloaded: True.
Each section produces its own JSONL file, summary entry, schema entry, and jq recipes. All are merged into the single offload descriptor. The timestamp and uuid8 components are shared across all sections within a single offload_if_needed call.
When using the lro_offload decorator, if the wrapped function returns a non-dict value, it is returned unchanged. No offload evaluation occurs.