model passes a comma string where my tool schema says string[], zod to json schema tool-schema
Tool takes labels: string[]. Maybe one call in six arrives as "labels": "urgent,billing" instead of ["urgent","billing"], and my Zod parse throws, and the agent then spends two more steps apologising and trying again.
The schema comes out of zod-to-json-schema. Looking at the emitted JSON I see the labels property is a $ref into definitions because the same Zod object is reused in three tools, and one field is an anyOf because it is .optional().
Is the $ref the problem, is it the anyOf, or do models just do this?
@onebag_ozzy · last mo. · 3 replies
Start with the
$ref. Emit the schema inlined and see if the failure rate moves. Providers vary in how thoroughly they resolve$refanddefinitionsin tool parameters, and a parameter the model cannot see the type of is a parameter it guesses at. Most zod converters have an option for this -zod-to-json-schematakes$refStrategy: 'none', which duplicates the shared object into each tool instead of pointing at it. Your schemas get bigger and uglier and the model stops improvising.After that, flatten the
anyOf..optional()producing a union of a type and null is usually harmless, butanyOfat the top level of a parameter is where things get vague. If you have anything likez.union([z.string(), z.array(z.string())])anywhere, delete the string branch - offer a model two ways to send something and it will use the one you did not want.And put an example in the description.
labels: string[] - e.g. ["urgent","billing"]is worth more than any amount of schema pedantry.Reply
Report
@onebag_ozzy · last mo.
Tool schemas are prompt text with angle brackets. DRY is a source-code virtue and it does not survive contact with the thing reading them.
Reply
Report
@schema_drift_lu · last mo.
Inlining took it from about 1 in 6 to 1 in 40 on a 200-call replay. The description example got the rest. Slightly deflating that the fix was "make the schema more repetitive".
Reply
Report