-
Notifications
You must be signed in to change notification settings - Fork 79
[Server] Add ToolExecutionExceptionInterface for custom tool error handling #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Hi @MartkCz, The Currently the I would prefer, instead of creating a new interface to implement, you create a |
|
@chr-hertel Thanks for your time.
interface ReferenceExceptionInterface {}
final class ExecutionReferenceException extends \RuntimException implements ReferenceExceptionInterface {} // business errors
abstract class ProtocolReferenceException extends \LogicException implements ReferenceExceptionInterface {} // unknown tools, invalid arguments, server errors
final class ToolNotFoundReferenceException extends ProtocolReferenceException {}
final class InvalidParamsReferenceException extends ProtocolReferenceException {}
final class InternalErrorReferenceException extends ProtocolReferenceException {}This is just a proposal — there wouldn’t necessarily have to be so many exception classes inheriting from ProtocolReferenceException, but I wanted to preserve throwing ToolNotFoundException. The naming is also not final. and then this is simplified from this: try {
$result = $this->referenceHandler->handle($toolReference, $arguments);
/** @var TextContent[]|ImageContent[]|EmbeddedResource[]|AudioContent[] $formattedResult */
$formattedResult = $toolReference->formatResult($result);
$this->logger->debug('Tool executed successfully', [
'name' => $toolName,
'result_type' => \gettype($result),
]);
return new CallToolResult($formattedResult);
} catch (RegistryException $e) {
throw new ToolCallException($request, $e);
} catch (\Throwable $e) {
if ($e instanceof ToolCallException) {
throw $e;
}
$this->logger->error('Tool execution failed', [
'name' => $toolName,
'exception' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
throw new ToolCallException($request, RegistryException::internalError('Error while executing tool', $e));
}to this: try {
$result = $this->referenceHandler->handle($toolReference, $arguments);
/** @var TextContent[]|ImageContent[]|EmbeddedResource[]|AudioContent[] $formattedResult */
$formattedResult = $toolReference->formatResult($result);
$this->logger->debug('Tool executed successfully', [
'name' => $toolName,
'result_type' => \gettype($result),
]);
return new CallToolResult($formattedResult);
} catch (ReferenceExceptionInterface $e) {
throw $e;
} catch (\Throwable $e) {
$this->logger->error('Tool execution failed', [
'name' => $toolName,
'exception' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
throw new InternalErrorReferenceException($request, $e);
}and this: try {
$content = $this->toolCaller->call($message);
} catch (ToolNotFoundException $exception) {
return Error::forInvalidParams($exception->getMessage(), $message->getId());
} catch (ToolCallException $exception) {
$registryException = $exception->registryException;
if ($registryException instanceof ReferenceExecutionException) {
return new Response($message->getId(), CallToolResult::error(array_map(
fn (string $message): TextContent => new TextContent($message),
$registryException->messages,
)));
}
return new Error($message->getId(), $registryException->getCode(), $registryException->getMessage());
}to this: try {
$content = $this->toolCaller->call($message);
} catch (ProtocolReferenceException $exception) {
return new Error($message->getId(), $exception->getCode(), $exception->getMessage());
} catch (ExecutionReferenceException $exception) {
return new Response($message->getId(), CallToolResult::error(array_map(
fn (string $message): TextContent => new TextContent($message),
$exception->messages,
)));
} |
|
@MartkCz Thanks for the follow-up and the detailed explanation! 🙏 btw, this needs a rebase - and please make sure to have a squashed, signed commit please |
Motivation and Context
The current tool execution system lacks a standardized way for handling tool-specific errors. This change provides a consistent way for tools to report errors.
How Has This Been Tested?
Added unit tests in ToolCallerTest.php
Breaking Changes
No breaking changes.
Types of changes
Checklist
Additional context
The implementation includes modifications to:
Usage