Cut Mid Object

An agent calls search_orders, which matches 900 rows. It then reports order totals that do not exist anywhere in the database, and confidently cites order numbers that are one digit off.

MAX_TOOL_RESULT_CHARS = 20_000

def run_tool(name, args, tool_use_id):
    result = TOOLS[name](**args)              # list[dict]
    payload = json.dumps(result)
    if len(payload) > MAX_TOOL_RESULT_CHARS:
        payload = payload[:MAX_TOOL_RESULT_CHARS]
    return {"type": "tool_result", "tool_use_id": tool_use_id, "content": payload}

What is producing the fabricated values, and what is the fix?

A

json.dumps does not guarantee key order across runs, so repeated calls disagree and the model averages them.

B

The slice lands inside a record, so the model receives a JSON document that stops mid-object. Truncate on a record boundary and append a marker saying how many of the 900 rows are shown.

C

20,000 characters is too small for this workload. Raise the cap to 400,000 characters so the full 900-row result fits in a single tool result.

D

The cap counts characters rather than tokens, so the real budget varies with the content of the rows. Switch it to a token count.