Menu ▾ ▴

#69 Tool output: JSON results keep every list item, compactly

closed
nobody
None
2026-10-18
2026-10-17
Anonymous
No

Originally created by: Thanatos9404

Builds on [#68], which builds on [#67]. Merge those first.

Problem

Line-based selection treats JSON as lines. For an 80-issue gh issue list --json result, it kept a window around the matching issue and silently dropped the rest. Agents use list results to decide what to do next, so missing items are worse than short ones.

What changes

llmslim/_json_output.py, used by llmslim proxy and LLMSlimToolOutputMiddleware whenever a long tool result is JSON with a list:

  • The list: it finds the largest list, at the top level or inside an envelope like {"total_count": .., "items": [...]}. The envelope's other fields are kept.
  • Related items stay whole, ranked by the words they share with the call, using up to half the budget.
  • Every other item is one compact line. It tries tighter levels until all items fit:
  • strings cut to 80 characters, nested lists shown as [n items], nested objects as a few short fields;
  • strings cut to 40 characters;
  • identity fields only: id, number, key, name, title, state, status, type, dates, url, path.
  • Only if even identity fields don't fit, items are dropped from the middle (never related ones), with a line naming them: … [163 more items not shown: 4018, 4019, …].
  • The note now says what was kept: "every list item with its short fields, and the items related to the call whole".

Non-JSON output, including log lines that merely start with [, takes the existing line-based path.

Result

For an 80-issue GitHub list asked about "refund rounding":

  • Before: 3,816 tokens, a window of about 12 issues.
  • After: 3,108 tokens with all 80 issues listed (number, title, state, date) and the refund issue whole.

Tests

tests/test_json_output.py has 13 tests. They cover:

  • every item kept, with the related one whole;
  • the levels tried in order;
  • dropping from the middle, with a marker that names and counts the dropped items;
  • envelopes;
  • non-JSON, small and scalar inputs left to the line path;
  • determinism;
  • the note text;
  • JSON printed by Bash going through the proxy.

The full suite passes: 1,824. Ruff is clean, and mypy shows no errors in the new module.

Related

Tickets: #22
Tickets: #67
Tickets: #68

Discussion

  • Anonymous

    Anonymous - 2026-10-17

    Originally posted by: vercel[bot]

    The latest updates on your projects. Learn more about Vercel for GitHub.

    Project Deployment Actions Updated
    llmslim Ready Ready Preview <relative-time datetime="2026-10-17T10:15:21.609Z">Oct 17, 2026 10:15am UTC</relative-time>
     
  • Anonymous

    Anonymous - 2026-10-17

    Ticket changed by: Thanatos9404

    • status: open --> closed
     

Log in to post a comment.