adachsoft/ai-tool-call

Unified AI tool-calling abstraction for PHP 8.3 with a clean Public API and an extensible SPI for custom tools.

Maintainers

👁 Arkadiusz Adach

Package info

gitlab.com/a.adach/AiToolCall

Issues

pkg:composer/adachsoft/ai-tool-call

Statistics

Installs: 81

Dependents: 23

Suggesters: 0

Stars: 0

2.0.1 2025-12-20 07:14 UTC

Requires

Suggests

None

Provides

None

Conflicts

None

Replaces

None

MIT e396cb6cd308c95ea88150a7a9fb3262df13b58f

  • Arkadiusz Adach

adaptercollectionaispiphp8.3tool-calling

This package is not auto-updated.

Last update: 2026-06-20 08:56:20 UTC


README

Unified AI tool-calling abstraction for PHP 8.3 with a clean Public API and an extensible SPI for custom tools.

  • Public API to list and call tools via a simple facade.
  • SPI to implement your own tools (factories) in a framework-agnostic way.
  • Zero framework assumptions, manual wiring via a small Builder.
  • Uses adachsoft/collection for strict, immutable collections.

Requirements

  • PHP ^8.3
  • adachsoft/collection ^3.0

Installation

composer require adachsoft/ai-tool-call

Quick Start (SPI with factories)

use AdachSoft\AiToolCall\PublicApi\Builder\AiToolCallFacadeBuilder;
use AdachSoft\AiToolCall\PublicApi\Dto\ToolCallRequestDto;
use AdachSoft\AiToolCall\SPI\Collection\ConfigMap;
use AdachSoft\AiToolCall\SPI\Collection\KeyValueMap;
use AdachSoft\AiToolCall\SPI\Collection\TagsCollection;
use AdachSoft\AiToolCall\SPI\Dto\ToolCallRequestDto as SpiRequestDto;
use AdachSoft\AiToolCall\SPI\Dto\ToolCallResultDto as SpiResultDto;
use AdachSoft\AiToolCall\SPI\Dto\ToolDefinitionDto;
use AdachSoft\AiToolCall\SPI\Exception\ToolConfigurationException;
use AdachSoft\AiToolCall\SPI\Factory\ToolFactoryInterface;
use AdachSoft\AiToolCall\SPI\ToolInterface;

final class EchoTool implements ToolInterface
{
 public static function getDefinition(): ToolDefinitionDto
 {
 return new ToolDefinitionDto(
 name: 'echo',
 description: 'Returns input as output',
 parametersSchema: [
 'type' => 'object',
 'properties' => [
 'text' => ['type' => 'string'],
 ],
 ],
 tags: new TagsCollection(['demo']),
 enabled: true,
 );
 }

 public function callTool(SpiRequestDto $request): SpiResultDto
 {
 return new SpiResultDto(
 'echo',
 new KeyValueMap(['text' => $request->parameters->get('text')])
 );
 }
}

final class EchoToolFactory implements ToolFactoryInterface
{
 public function getToolClass(): string
 {
 return EchoTool::class;
 }

 public function create(ConfigMap $config): ToolInterface
 {
 if ($config->has('invalid')) {
 throw new ToolConfigurationException('Invalid configuration for EchoTool.');
 }

 return new EchoTool();
 }
}

$facade = AiToolCallFacadeBuilder::new()
 ->withSpiFactories([new EchoToolFactory()])
 ->withToolConfigs([
 'echo' => new ConfigMap([]),
 ])
 ->build();

// List available tools (includes built-in current_datetime and your SPI tools)
$tools = $facade->listAvailableTools();
foreach ($tools as $tool) {
 echo $tool->name . PHP_EOL;
}

// Call a SPI tool
$result = $facade->callTool(new ToolCallRequestDto(
 toolName: 'echo',
 parameters: ['text' => 'hello'],
));

var_dump($result->result);

// Call the built-in current_datetime tool
$currentDateTimeResult = $facade->callTool(new ToolCallRequestDto(
 toolName: 'current_datetime',
 parameters: [],
));

var_dump($currentDateTimeResult->result);

Public API

  • Facade: AdachSoft\AiToolCall\PublicApi\AiToolCallFacadeInterface
    • callTool(ToolCallRequestDto): ToolCallResultDto
    • listAvailableTools(): AvailableToolCollection
    • listAvailableToolsByTags(array $tags): AvailableToolCollection

DTOs

  • ToolCallRequestDto(string $toolName, array $parameters)
  • ToolCallResultDto(string $toolName, mixed $result)
  • AvailableToolDto(string $name, string $description, array $parametersSchema, array $tags)
  • AvailableToolCollection

SPI (Service Provider Interface)

Implement custom tools by fulfilling the SPI contracts.

  • AdachSoft\AiToolCall\SPI\ToolInterface

    • callTool(ToolCallRequestDto): ToolCallResultDto
    • static getDefinition(): ToolDefinitionDto
  • AdachSoft\AiToolCall\SPI\Factory\ToolFactoryInterface

    • getToolClass(): string
    • create(ConfigMap $config): ToolInterface
  • ToolDefinitionDto

    • name: string
    • description: string
    • parametersSchema: array<string, mixed>
    • tags: TagsCollection
    • enabled: bool
  • Collections used in SPI:

    • TagsCollection (immutable list of strings)
    • KeyValueMap (immutable map string->mixed)
    • ConfigMap (immutable map string->mixed)
    • ToolCollection (immutable collection of SPI tools)
    • ToolFactoryCollection (immutable collection of SPI tool factories)

Minimal tool example (SPI-only)

use AdachSoft\AiToolCall\SPI\ToolInterface;
use AdachSoft\AiToolCall\SPI\Collection\ToolCollection as SpiToolCollection;
use AdachSoft\AiToolCall\SPI\Dto\ToolDefinitionDto;
use AdachSoft\AiToolCall\SPI\Dto\ToolCallRequestDto as SpiRequest;
use AdachSoft\AiToolCall\SPI\Dto\ToolCallResultDto as SpiResult;
use AdachSoft\AiToolCall\SPI\Collection\TagsCollection;
use AdachSoft\AiToolCall\SPI\Collection\KeyValueMap;

final class EchoTool implements ToolInterface
{
 public static function getDefinition(): ToolDefinitionDto
 {
 return new ToolDefinitionDto(
 name: 'echo',
 description: 'Returns input as output',
 parametersSchema: ['type' => 'object', 'properties' => ['text' => ['type' => 'string']]],
 tags: new TagsCollection(['demo']),
 enabled: true,
 );
 }

 public function callTool(SpiRequest $request): SpiResult
 {
 return new SpiResult('echo', new KeyValueMap(['text' => $request->parameters->get('text')]));
 }
}

$tools = new SpiToolCollection([new EchoTool()]);

Tool discovery & registration

  • No autoscan. The builder does not scan directories.
  • Register tools via:
    • SPI factories using withSpiFactories() and optional withToolConfigs() for configuration maps, or
    • Direct SPI tools using withSpiTools() when tools are already fully configured.
  • The builder always registers CurrentDateTimeToolCaller as a built-in domain tool by default.

Error handling

  • Public API throws PublicApi\Exception\ToolCallFailedException on errors during tool execution.
  • Public API throws PublicApi\Exception\ToolRegistrationException when tool registration or configuration fails while building the facade (e.g. duplicate tool names or invalid factory/config types).
  • SPI exceptions:
    • SPI\Exception\InvalidToolCallException
    • SPI\Exception\ToolExecutionException
    • SPI\Exception\ToolConfigurationException These are mapped through the adapter when calling SPI tools through the Domain.

Versioning

  • Semantic Versioning.
  • Package version is controlled by Git tags (do not set version in composer.json).

License

MIT