Skip to content

Commit 8329402

Browse files
ThomasVitaletzolov
authored andcommitted
ToolContext is now excluded from JSON Schema Generation
When generating the JSON Schema for a tool input from a method, ToolContext is now excluded since it's not something we want the model to provide. The framework takes care of passing a value for it when actually executing the tool call. Fixes gh-2366 Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
1 parent 3c17750 commit 8329402

File tree

4 files changed

+48
-2
lines changed

4 files changed

+48
-2
lines changed

spring-ai-core/src/main/java/org/springframework/ai/chat/model/ToolContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
* @author Christian Tzolov
4444
* @since 1.0.0
4545
*/
46-
public class ToolContext {
46+
public final class ToolContext {
4747

4848
/**
4949
* The key for the running, tool call history stored in the context map.

spring-ai-core/src/main/java/org/springframework/ai/util/json/schema/JsonSchemaGenerator.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@
3131
import com.github.victools.jsonschema.module.jackson.JacksonOption;
3232
import com.github.victools.jsonschema.module.swagger2.Swagger2Module;
3333
import io.swagger.v3.oas.annotations.media.Schema;
34+
import org.springframework.ai.chat.model.ToolContext;
3435
import org.springframework.ai.tool.annotation.ToolParam;
3536
import org.springframework.ai.util.json.JsonParser;
3637
import org.springframework.lang.Nullable;
3738
import org.springframework.util.Assert;
39+
import org.springframework.util.ClassUtils;
3840
import org.springframework.util.StringUtils;
3941

4042
import java.lang.reflect.Method;
@@ -125,6 +127,14 @@ public static String generateForMethodInput(Method method, SchemaOption... schem
125127
for (int i = 0; i < method.getParameterCount(); i++) {
126128
String parameterName = method.getParameters()[i].getName();
127129
Type parameterType = method.getGenericParameterTypes()[i];
130+
if (parameterType instanceof Class<?> parameterClass
131+
&& ClassUtils.isAssignable(parameterClass, ToolContext.class)) {
132+
// A ToolContext method parameter is not included in the JSON Schema
133+
// generation.
134+
// It's a special type used by Spring AI to pass contextual data to tools
135+
// outside the model interaction flow.
136+
continue;
137+
}
128138
if (isMethodParameterRequired(method, i)) {
129139
required.add(parameterName);
130140
}

spring-ai-core/src/test/java/org/springframework/ai/util/json/JsonSchemaGeneratorTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.fasterxml.jackson.databind.JsonNode;
2424
import io.swagger.v3.oas.annotations.media.Schema;
2525
import org.junit.jupiter.api.Test;
26+
import org.springframework.ai.chat.model.ToolContext;
2627
import org.springframework.ai.tool.annotation.ToolParam;
2728
import org.springframework.ai.util.json.schema.JsonSchemaGenerator;
2829
import org.springframework.lang.Nullable;
@@ -347,6 +348,36 @@ void generateSchemaForMethodWithTimeParameters() throws Exception {
347348
assertThat(schema).isEqualToIgnoringWhitespace(expectedJsonSchema);
348349
}
349350

351+
@Test
352+
void generateSchemaForMethodWithToolContext() throws Exception {
353+
Method method = TestMethods.class.getDeclaredMethod("contextMethod", String.class, LocalDateTime.class,
354+
ToolContext.class);
355+
356+
String schema = JsonSchemaGenerator.generateForMethodInput(method);
357+
String expectedJsonSchema = """
358+
{
359+
"$schema": "https://json-schema.org/draft/2020-12/schema",
360+
"type": "object",
361+
"properties": {
362+
"deliveryStatus": {
363+
"type": "string"
364+
},
365+
"expectedDelivery": {
366+
"type": "string",
367+
"format": "date-time"
368+
}
369+
},
370+
"required": [
371+
"deliveryStatus",
372+
"expectedDelivery"
373+
],
374+
"additionalProperties": false
375+
}
376+
""";
377+
378+
assertThat(schema).isEqualToIgnoringWhitespace(expectedJsonSchema);
379+
}
380+
350381
// TYPES
351382

352383
@Test
@@ -658,6 +689,9 @@ public void complexMethod(List<String> items, TestData data, MoreTestData moreDa
658689
public void timeMethod(Duration duration, LocalDateTime localDateTime, Instant instant) {
659690
}
660691

692+
public void contextMethod(String deliveryStatus, LocalDateTime expectedDelivery, ToolContext toolContext) {
693+
}
694+
661695
}
662696

663697
record TestData(int id, @ToolParam(description = "The special name") String name) {

spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,11 @@ To use this automation:
171171

172172
This approach can save time and reduce the chance of errors when upgrading multiple projects or complex codebases.
173173

174+
== Upgrading to 1.0.0.M7
174175

175-
== Upgrading to 1.0.0.M6
176+
* The `ToolContext` class has now been marked as final and cannot be extended anymore. It was never supposed to be subclassed. You can add all the contextual data you need when instantiating a `ToolContext`, in the form of a `Map<String, Object>`. For more information, check the [documentation](https://docs.spring.io/spring-ai/reference/api/tools.html#_tool_context).
176177

178+
== Upgrading to 1.0.0.M6
177179

178180
=== Changes to Usage Interface and DefaultUsage Implementation
179181

0 commit comments

Comments
 (0)