mirror of
https://github.com/Piebald-AI/claude-code-system-prompts.git
synced 2026-05-30 13:45:23 +08:00
247 lines
7.1 KiB
Markdown
247 lines
7.1 KiB
Markdown
<!--
|
|
name: 'Data: Claude API reference — PHP'
|
|
description: PHP SDK reference
|
|
ccVersion: 2.1.73
|
|
-->
|
|
# Claude API — PHP
|
|
|
|
> **Note:** The PHP SDK is the official Anthropic SDK for PHP. Tool runner and Agent SDK are not available. Bedrock, Vertex AI, and Foundry clients are supported.
|
|
|
|
## Installation
|
|
|
|
\`\`\`bash
|
|
composer require "anthropic-ai/sdk"
|
|
\`\`\`
|
|
|
|
## Client Initialization
|
|
|
|
\`\`\`php
|
|
use Anthropic\\Client;
|
|
|
|
// Using API key from environment variable
|
|
$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));
|
|
\`\`\`
|
|
|
|
### Amazon Bedrock
|
|
|
|
\`\`\`php
|
|
use Anthropic\\Bedrock;
|
|
|
|
// Constructor is private — use the static factory. Reads AWS credentials from env.
|
|
$client = Bedrock\\Client::fromEnvironment(region: 'us-east-1');
|
|
\`\`\`
|
|
|
|
### Google Vertex AI
|
|
|
|
\`\`\`php
|
|
use Anthropic\\Vertex;
|
|
|
|
// Constructor is private. Parameter is \`location\`, not \`region\`.
|
|
$client = Vertex\\Client::fromEnvironment(
|
|
location: 'us-east5',
|
|
projectId: 'my-project-id',
|
|
);
|
|
\`\`\`
|
|
|
|
### Anthropic Foundry
|
|
|
|
\`\`\`php
|
|
use Anthropic\\Foundry;
|
|
|
|
// Constructor is private. baseUrl or resource is required.
|
|
$client = Foundry\\Client::withCredentials(
|
|
authToken: getenv('ANTHROPIC_FOUNDRY_AUTH_TOKEN'),
|
|
baseUrl: 'https://<resource>.services.ai.azure.com/anthropic',
|
|
);
|
|
\`\`\`
|
|
|
|
---
|
|
|
|
## Basic Message Request
|
|
|
|
\`\`\`php
|
|
$message = $client->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 1024,
|
|
messages: [
|
|
['role' => 'user', 'content' => 'What is the capital of France?'],
|
|
],
|
|
);
|
|
|
|
// content is an array of polymorphic blocks (TextBlock, ToolUseBlock,
|
|
// ThinkingBlock). Accessing ->text on content[0] without checking the block
|
|
// type will throw if the first block is not a TextBlock (e.g., when extended
|
|
// thinking is enabled and a ThinkingBlock comes first). Always guard:
|
|
foreach ($message->content as $block) {
|
|
if ($block->type === 'text') {
|
|
echo $block->text;
|
|
}
|
|
}
|
|
\`\`\`
|
|
|
|
If you only want the first text block:
|
|
|
|
\`\`\`php
|
|
foreach ($message->content as $block) {
|
|
if ($block->type === 'text') {
|
|
echo $block->text;
|
|
break;
|
|
}
|
|
}
|
|
\`\`\`
|
|
|
|
---
|
|
|
|
## Streaming
|
|
|
|
> **Requires SDK v0.5.0+.** v0.4.0 and earlier used a single \`$params\` array; calling with named parameters throws \`Unknown named parameter $model\`. Upgrade: \`composer require "anthropic-ai/sdk:^0.6"\`
|
|
|
|
\`\`\`php
|
|
use Anthropic\\Messages\\RawContentBlockDeltaEvent;
|
|
use Anthropic\\Messages\\TextDelta;
|
|
|
|
$stream = $client->messages->createStream(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 1024,
|
|
messages: [
|
|
['role' => 'user', 'content' => 'Write a haiku'],
|
|
],
|
|
);
|
|
|
|
foreach ($stream as $event) {
|
|
if ($event instanceof RawContentBlockDeltaEvent && $event->delta instanceof TextDelta) {
|
|
echo $event->delta->text;
|
|
}
|
|
}
|
|
\`\`\`
|
|
|
|
---
|
|
|
|
## Tool Use (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: 1024,
|
|
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: 1024,
|
|
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.
|
|
|
|
|
|
---
|
|
|
|
## Extended Thinking
|
|
|
|
**Adaptive thinking is the recommended mode for Claude 4.6+ models.** Claude decides dynamically when and how much to think.
|
|
|
|
\`\`\`php
|
|
use Anthropic\\Messages\\ThinkingBlock;
|
|
|
|
$message = $client->messages->create(
|
|
model: '{{OPUS_ID}}',
|
|
maxTokens: 16000,
|
|
thinking: ['type' => 'adaptive'],
|
|
messages: [
|
|
['role' => 'user', 'content' => 'Solve: 27 * 453'],
|
|
],
|
|
);
|
|
|
|
// ThinkingBlock(s) precede TextBlock in content
|
|
foreach ($message->content as $block) {
|
|
if ($block instanceof ThinkingBlock) {
|
|
echo "Thinking:\\n{$block->thinking}\\n\\n";
|
|
// $block->signature is an opaque string — preserve verbatim if
|
|
// passing thinking blocks back in multi-turn conversations
|
|
} elseif ($block->type === 'text') {
|
|
echo "Answer: {$block->text}\\n";
|
|
}
|
|
}
|
|
\`\`\`
|
|
|
|
> **Deprecated:** \`['type' => 'enabled', 'budgetTokens' => N]\` (fixed-budget extended thinking) still works on Claude 4.6 but is deprecated. Use adaptive thinking above.
|
|
|
|
\`$block->type === 'thinking'\` also works for the check; \`instanceof\` narrows for PHPStan.
|
|
|
|
---
|
|
|
|
## Beta Features & Server-Side 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: 1024,
|
|
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']],
|
|
);
|
|
\`\`\`
|
|
|
|
**Server-side tools** (bash, web_search, text_editor, code_execution) are GA and work on both paths — \`Anthropic\\Messages\\ToolBash20250124\` / \`WebSearchTool20260209\` / \`ToolTextEditor20250728\` / \`CodeExecutionTool20260120\` for non-beta, \`Anthropic\\Beta\\Messages\\BetaToolBash20250124\` / \`BetaWebSearchTool20260209\` / \`BetaToolTextEditor20250728\` / \`BetaCodeExecutionTool20260120\` for beta. No \`betas:\` header needed for these.
|