mirror of
https://github.com/Piebald-AI/claude-code-system-prompts.git
synced 2026-06-19 11:30:17 +08:00
259 lines
8.1 KiB
Markdown
259 lines
8.1 KiB
Markdown
<!--
|
|
name: 'Data: Tool use reference — PHP'
|
|
description: PHP tool use reference including the beta tool runner and the manual agentic loop with camelCase keys
|
|
ccVersion: 2.1.182
|
|
-->
|
|
# Tool Use — PHP
|
|
|
|
For conceptual overview (tool definitions, tool choice, tips), see [shared/tool-use-concepts.md](../../shared/tool-use-concepts.md).
|
|
|
|
## Tool Use
|
|
|
|
### Tool Runner (Beta)
|
|
|
|
**Beta:** The PHP SDK provides a tool runner via `$client->beta->messages->toolRunner()`. Define tools with `BetaRunnableTool` — a definition array plus a `run` closure:
|
|
|
|
```php
|
|
use Anthropic\Lib\Tools\BetaRunnableTool;
|
|
|
|
$weatherTool = new BetaRunnableTool(
|
|
definition: [
|
|
'name' => 'get_weather',
|
|
'description' => 'Get the current weather for a location.',
|
|
'inputSchema' => [
|
|
'type' => 'object',
|
|
'properties' => [
|
|
'location' => ['type' => 'string', 'description' => 'City and state'],
|
|
],
|
|
'required' => ['location'],
|
|
],
|
|
],
|
|
run: function (array $input): string {
|
|
return "The weather in {$input['location']} is sunny and 72°F.";
|
|
},
|
|
);
|
|
|
|
$runner = $client->beta->messages->toolRunner(
|
|
maxTokens: 16000,
|
|
messages: [['role' => 'user', 'content' => 'What is the weather in Paris?']],
|
|
model: '{{OPUS_ID}}',
|
|
tools: [$weatherTool],
|
|
);
|
|
|
|
foreach ($runner as $message) {
|
|
foreach ($message->content as $block) {
|
|
if ($block->type === 'text') {
|
|
echo $block->text;
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Manual Loop
|
|
|
|
Tools are passed as arrays. **The SDK uses camelCase keys** (`inputSchema`, `toolUseID`, `stopReason`) and auto-maps to the API's snake_case on the wire — since v0.5.0. See [shared tool use concepts](../../shared/tool-use-concepts.md) for the loop pattern.
|
|
|
|
```php
|
|
use Anthropic\Messages\ToolUseBlock;
|
|
|
|
$tools = [
|
|
[
|
|
'name' => 'get_weather',
|
|
'description' => 'Get the current weather in a given location',
|
|
'inputSchema' => [ // camelCase, not input_schema
|
|
'type' => 'object',
|
|
'properties' => [
|
|
'location' => ['type' => 'string', 'description' => 'City and state'],
|
|
],
|
|
'required' => ['location'],
|
|
],
|
|
],
|
|
];
|
|
|
|
$messages = [['role' => 'user', 'content' => 'What is the weather in SF?']];
|
|
|
|
$response = $client->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 16000,
|
|
tools: $tools,
|
|
messages: $messages,
|
|
);
|
|
|
|
while ($response->stopReason === 'tool_use') { // camelCase property
|
|
$toolResults = [];
|
|
foreach ($response->content as $block) {
|
|
if ($block instanceof ToolUseBlock) {
|
|
// $block->name : string — tool name to dispatch on
|
|
// $block->input : array<string,mixed> — parsed JSON input
|
|
// $block->id : string — pass back as toolUseID
|
|
$result = executeYourTool($block->name, $block->input);
|
|
$toolResults[] = [
|
|
'type' => 'tool_result',
|
|
'toolUseID' => $block->id, // camelCase, not tool_use_id
|
|
'content' => $result,
|
|
];
|
|
}
|
|
}
|
|
|
|
// Append assistant turn + user turn with tool results
|
|
$messages[] = ['role' => 'assistant', 'content' => $response->content];
|
|
$messages[] = ['role' => 'user', 'content' => $toolResults];
|
|
|
|
$response = $client->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 16000,
|
|
tools: $tools,
|
|
messages: $messages,
|
|
);
|
|
}
|
|
|
|
// Final text response
|
|
foreach ($response->content as $block) {
|
|
if ($block->type === 'text') {
|
|
echo $block->text;
|
|
}
|
|
}
|
|
```
|
|
|
|
`$block->type === 'tool_use'` also works; `instanceof ToolUseBlock` narrows for PHPStan.
|
|
|
|
|
|
---
|
|
|
|
## Structured Outputs
|
|
|
|
### Using StructuredOutputModel (Recommended)
|
|
|
|
Define a PHP class implementing `StructuredOutputModel` and pass it as `outputConfig`:
|
|
|
|
```php
|
|
use Anthropic\Lib\Contracts\StructuredOutputModel;
|
|
use Anthropic\Lib\Concerns\StructuredOutputModelTrait;
|
|
use Anthropic\Lib\Attributes\Constrained;
|
|
|
|
class Person implements StructuredOutputModel
|
|
{
|
|
use StructuredOutputModelTrait;
|
|
|
|
#[Constrained(description: 'Full name')]
|
|
public string $name;
|
|
|
|
public int $age;
|
|
|
|
public ?string $email = null; // nullable = optional field
|
|
}
|
|
|
|
$message = $client->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 16000,
|
|
messages: [['role' => 'user', 'content' => 'Generate a profile for Alice, age 30']],
|
|
outputConfig: ['format' => Person::class],
|
|
);
|
|
|
|
$person = $message->parsedOutput(); // Person instance
|
|
echo $person->name;
|
|
```
|
|
|
|
Types are inferred from PHP type hints. Use `#[Constrained(description: '...')]` to add descriptions. Nullable properties (`?string`) become optional fields.
|
|
|
|
### Raw Schema
|
|
|
|
```php
|
|
$message = $client->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 16000,
|
|
messages: [['role' => 'user', 'content' => 'Extract: John (john@co.com), Enterprise plan']],
|
|
outputConfig: [
|
|
'format' => [
|
|
'type' => 'json_schema',
|
|
'schema' => [
|
|
'type' => 'object',
|
|
'properties' => [
|
|
'name' => ['type' => 'string'],
|
|
'email' => ['type' => 'string'],
|
|
'plan' => ['type' => 'string'],
|
|
],
|
|
'required' => ['name', 'email', 'plan'],
|
|
'additionalProperties' => false,
|
|
],
|
|
],
|
|
],
|
|
);
|
|
|
|
// First text block contains valid JSON
|
|
foreach ($message->content as $block) {
|
|
if ($block->type === 'text') {
|
|
$data = json_decode($block->text, true);
|
|
break;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Beta Features & Anthropic-Defined Tools
|
|
|
|
**`betas:` is NOT a param on `$client->messages->create()`** — it only exists on the beta namespace. Use it for features that need an explicit opt-in header:
|
|
|
|
```php
|
|
use Anthropic\Beta\Messages\BetaRequestMCPServerURLDefinition;
|
|
|
|
$response = $client->beta->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 16000,
|
|
mcpServers: [
|
|
BetaRequestMCPServerURLDefinition::with(
|
|
name: 'my-server',
|
|
url: 'https://example.com/mcp',
|
|
),
|
|
],
|
|
betas: ['mcp-client-2025-11-20'], // only valid on ->beta->messages
|
|
messages: [['role' => 'user', 'content' => 'Use the MCP tools']],
|
|
);
|
|
```
|
|
|
|
### Task budgets
|
|
|
|
```php
|
|
$response = $client->beta->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 16000,
|
|
outputConfig: ['taskBudget' => ['type' => 'tokens', 'total' => 64000]],
|
|
tools: [...],
|
|
messages: [...],
|
|
betas: ['task-budgets-2026-03-13'],
|
|
);
|
|
```
|
|
|
|
### Cache diagnostics
|
|
|
|
Pass the previous response's `id` on the next request; print the `diagnostics` object on the response:
|
|
|
|
```php
|
|
$r2 = $client->beta->messages->create(
|
|
model: '{{OPUS_ID}}', maxTokens: 1024,
|
|
diagnostics: ['previousMessageId' => $r1->id],
|
|
betas: ['cache-diagnosis-2026-04-07'],
|
|
messages: [...],
|
|
);
|
|
```
|
|
|
|
**Anthropic-defined tools** (bash, web_search, text_editor, code_execution) are GA and work on both paths. Of these, web_search and code_execution are server-executed; bash and text_editor are client-executed (you handle the `tool_use` locally) — `Anthropic\Messages\ToolBash20250124` / `WebSearchTool20260209` / `ToolTextEditor20250728` / `CodeExecutionTool20260120` for non-beta, `Anthropic\Beta\Messages\BetaToolBash20250124` / `BetaWebSearchTool20260209` / `BetaToolTextEditor20250728` / `BetaCodeExecutionTool20260120` for beta. No `betas:` header needed for these.
|
|
|
|
### Tool search (non-beta, server-side)
|
|
|
|
```php
|
|
tools: [
|
|
['type' => 'tool_search_tool_regex_20251119', 'name' => 'tool_search_tool_regex'],
|
|
['name' => 'get_weather', 'description' => '...', 'inputSchema' => [...], 'deferLoading' => true],
|
|
// ... other user tools with 'deferLoading' => true
|
|
],
|
|
```
|
|
|
|
### Memory tool (non-beta, client-executed)
|
|
|
|
Declare `['type' => 'memory_20250818', 'name' => 'memory']`. Handle the `tool_use` by reading/writing files under a fixed `/memories` directory. **Validate every model-supplied path**: resolve to its canonical form and verify it remains within the memory directory; reject traversal (`..`, symlinks) — see `shared/tool-use-concepts.md` § Client-Side Tools.
|
|
|
|
---
|
|
|