Building Tools¶
Using BaseTool¶
Extend BaseTool and implement __invoke(). The parameter schema is auto-generated from the method signature:
use Cognesy\Agents\Core\Tools\BaseTool;
use Cognesy\Schema\Attributes\Description;
class GetWeather extends BaseTool
{
public function __construct()
{
parent::__construct(
name: 'get_weather',
description: 'Get current weather for a city',
);
}
public function __invoke(
#[Description('City name')] string $city,
#[Description('Unit: celsius or fahrenheit')] string $unit = 'celsius',
): string {
// Your implementation
return "Weather in {$city}: 22 {$unit}";
}
}
Using FunctionTool¶
Wrap any callable without creating a class:
use Cognesy\Agents\Core\Tools\FunctionTool;
$tool = FunctionTool::fromCallable(function (string $query): string {
return "Results for: {$query}";
});
Accessing Agent State¶
Implement CanAccessAgentState (already included in BaseTool) to receive the current agent state:
class StatefulTool extends BaseTool
{
public function __invoke(string $input): string
{
$stepCount = $this->agentState?->stepCount() ?? 0;
return "Step {$stepCount}: processing {$input}";
}
}
The ToolInterface¶
All tools implement ToolInterface:
interface ToolInterface
{
public function use(mixed ...$args): Result;
public function toToolSchema(): array;
public function name(): string;
public function description(): string;
public function metadata(): array;
public function instructions(): array;
}
use()- execute the tool, returnsResult(success or failure)toToolSchema()- OpenAI-compatible function schema for the LLMmetadata()- lightweight info for tool discoveryinstructions()- full specification for detailed tool documentation