Skip to content

ToolCallback fails if tool context is provided #3389

Open
@filiphr

Description

@filiphr

I have few ToolCallback(s) and one of them is taking use of the ToolContext, whereas the others aren't.

e.g.

public class CustomersToolCallback implements ToolCallback {

    @Override
    public ToolDefinition getToolDefinition() {
        return ToolDefinition.builder()
                .name("getCustomerInfo")
                .description("Retrieve customer information")
                .build();

    }

    @Override
    public String call(String toolInput, ToolContext tooContext) {
        if (tooContext == null) {
            throw new UnsupportedOperationException("ToolContext cannot be null");
        }
        Object tenantId = tooContext.getContext().get("tenant");
        // Fetch customer by their id
    }

    @Override
    public String call(String toolInput) {
        throw new UnsupportedOperationException("This method is not supported. Use call(String toolInput, ToolContext toolContext) instead.");
    }
}

And another one

public class MockCustomerToolCallback implements ToolCallback {

    @Override
    public ToolDefinition getToolDefinition() {
        return ToolDefinition.builder()
                .name("mockCustomer")
                .description("Retrieve mock customer information")
                .build();

    }

    @Override
    public String call(String toolInput) {
        // Some implementation
    }
}

If I have this tool callback registered with the ChatModel and I do

ChatModel chatModel = ...

String response = ChatClient.create(chatModel)
        .prompt("How does a mock customer look like")
        .toolContext(Map.of("tenantId", "acme"))
        .call()
        .content();

You can imagine that the call is a bit more dynamic than this. So if this happens, and my MockCustomerToolCallback needs to be called it'll fail due to the

if (tooContext != null && !tooContext.getContext().isEmpty()) {
    throw new UnsupportedOperationException("Tool context is not supported!");
}

In the ToolCallback.

What exactly is the reason for this UnsupportedOperationException on the interface level? It is a bit inconvenient if all of my ToolCallback implementations have to implement the method with the ToolContext even if they do not need it.

Fix proposal

I would propose the following:

Add new interface

Similar to how it is done for Spring Kafka GenericMessageListener and its different implementations, or Spring AMQP MessageListener and its different implementation. Spring AI could add a ToolContextAwareToolCallback which can look something like

public interface ToolContextAwareToolCallback extends ToolCallback {

	@Override
	default String call(String toolInput) {
		throw new UnsupportedOperationException("This method is not supported. Use call(String toolInput, ToolContext toolContext) instead.");
	}

	@Override
	String call(String toolInput, @NonNull ToolContext toolContext);
}

This would make it easier to implement, since I won't need to override ToolCallback#cal(String). The exception can be adjusted though.

Relax the constraint in the ToolCallback#call(String, ToolContext)

The ToolCallback.call(String, ToolContext) would need to be adjusted to allow empty tool context.

Potentially similar issues

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions