Best
I think the solution here is simply to use the [“number”, “null”] union of output types.
You’re going to get more keys, but then at least each key is being evaluated for its need to be output instead of a premature “that was enough output”. A model like gpt-4.1-mini can produce 80 tokens a second, so unless you are using these keys like enums with a hundred, you won’t have much more latency by using null values.
You can present the key ordering so that any dependencies are output first, so the AI isn’t producing other information based on a choice that hasn’t been made yet.
What you want - but will confuse and cost in input
- make a separate anyOf schema for every possible combination of final output. One for [a], one for [b], one for [a,b], one for [c], …
The number of subschemas blows up quickly…
number of options vs. number of schemas needed (any non-empty combination)
Options (n) |
Schemas needed (2^n − 1) |
1 |
1 |
2 |
3 |
3 |
7 |
4 |
15 |
5 |
31 |
6 |
63 |
7 |
127 |
8 |
255 |
9 |
511 |
10 |
1023 |
so here, try the option with 5 ==> 31 anyOf schemas.
{
"name": "five_key_combinations_numbers_a_to_e",
"strict": true,
"schema": {
"type": "object",
"properties": {
"output": {
"anyOf": [
{
"type": "object",
"properties": {
"a": {
"type": "number"
}
},
"required": [
"a"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
}
},
"required": [
"b"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"c": {
"type": "number"
}
},
"required": [
"c"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"d": {
"type": "number"
}
},
"required": [
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"e": {
"type": "number"
}
},
"required": [
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
}
},
"required": [
"a",
"b"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"c": {
"type": "number"
}
},
"required": [
"a",
"c"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"d": {
"type": "number"
}
},
"required": [
"a",
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
},
"c": {
"type": "number"
}
},
"required": [
"b",
"c"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
},
"d": {
"type": "number"
}
},
"required": [
"b",
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"b",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"c": {
"type": "number"
},
"d": {
"type": "number"
}
},
"required": [
"c",
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"c": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"c",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"d",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"c": {
"type": "number"
}
},
"required": [
"a",
"b",
"c"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"d": {
"type": "number"
}
},
"required": [
"a",
"b",
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"b",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"c": {
"type": "number"
},
"d": {
"type": "number"
}
},
"required": [
"a",
"c",
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"c": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"c",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"d",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
},
"c": {
"type": "number"
},
"d": {
"type": "number"
}
},
"required": [
"b",
"c",
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
},
"c": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"b",
"c",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
},
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"b",
"d",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"c": {
"type": "number"
},
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"c",
"d",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"c": {
"type": "number"
},
"d": {
"type": "number"
}
},
"required": [
"a",
"b",
"c",
"d"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"c": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"b",
"c",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"b",
"d",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"c": {
"type": "number"
},
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"c",
"d",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"b": {
"type": "number"
},
"c": {
"type": "number"
},
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"b",
"c",
"d",
"e"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"a": {
"type": "number"
},
"b": {
"type": "number"
},
"c": {
"type": "number"
},
"d": {
"type": "number"
},
"e": {
"type": "number"
}
},
"required": [
"a",
"b",
"c",
"d",
"e"
],
"additionalProperties": false
}
],
"description": "Object containing one or more of keys 'a'..'e', each a number. Only the listed keys for the chosen combination are permitted."
}
},
"required": [
"output"
],
"additionalProperties": false
}
}
A custom type of output where you get to provide a different schema to the AI than is enforced would be nice…