Update claude-api skill: per-SDK doc split, code_execution_20260521, platform-availability, onboarding streamline (#1363)

This commit is contained in:
Lance Martin
2026-06-27 09:07:56 -07:00
committed by GitHub
parent 5754626092
commit 35414756ca
46 changed files with 2490 additions and 1635 deletions
+173
View File
@@ -0,0 +1,173 @@
# Claude API — PHP
> **Note:** The PHP SDK is the official Anthropic SDK for PHP. A beta tool runner is available via `$client->beta->messages->toolRunner()`. Structured output helpers are supported via `StructuredOutputModel` classes. Agent SDK is 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\MantleClient;
// Messages-API Bedrock endpoint. Reads AWS credentials from env.
$client = new MantleClient(awsRegion: 'us-east-1');
```
Model IDs on Bedrock take an `anthropic.` prefix — e.g. `model: 'anthropic.claude-opus-4-8'`.
### 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(
apiKey: getenv('ANTHROPIC_FOUNDRY_API_KEY'),
baseUrl: 'https://<resource>.services.ai.azure.com/anthropic/v1',
);
```
---
## Basic Message Request
```php
$message = $client->messages->create(
model: 'claude-opus-4-8',
maxTokens: 16000,
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;
}
}
```
---
## 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: 'claude-opus-4-8',
maxTokens: 16000,
thinking: ['type' => 'adaptive', 'display' => 'summarized'], // display opt-in: default is omitted (empty thinking text) on Fable 5 / Mythos 5 / Opus 4.8 / 4.7
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";
}
}
```
> **Fable 5, Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6:** Use adaptive thinking (above). `['type' => 'enabled', 'budgetTokens' => N]` is removed on Fable 5, Opus 4.8, and 4.7 (400 if sent); deprecated on Opus 4.6 and Sonnet 4.6.
> **Older models:** Use `thinking: ['type' => 'enabled', 'budgetTokens' => N]` (budget must be < `maxTokens`, min 1024).
`$block->type === 'thinking'` also works for the check; `instanceof` narrows for PHPStan.
---
## Prompt Caching
`system:` takes an array of text blocks; set `cacheControl` on the last block. Array-shape syntax (camelCase keys) is idiomatic. For placement patterns and the silent-invalidator audit checklist, see `shared/prompt-caching.md`.
```php
$message = $client->messages->create(
model: 'claude-opus-4-8',
maxTokens: 16000,
system: [
['type' => 'text', 'text' => $longSystemPrompt, 'cacheControl' => ['type' => 'ephemeral']],
],
messages: [['role' => 'user', 'content' => 'Summarize the key points']],
);
```
For 1-hour TTL: `'cacheControl' => ['type' => 'ephemeral', 'ttl' => '1h']`. There's also a top-level `cacheControl:` on `messages->create(...)` that auto-places on the last cacheable block.
Verify hits via `$message->usage->cacheCreationInputTokens` / `$message->usage->cacheReadInputTokens`.
---
## Stop Details
When `stopReason` is `'refusal'`, the response includes structured `stopDetails`:
```php
if ($message->stopReason === 'refusal' && $message->stopDetails !== null) {
echo "Category: " . $message->stopDetails->category . "\n"; // e.g. "cyber", "bio", "reasoning_extraction", "frontier_llm", or null — see docs for the full set
echo "Explanation: " . $message->stopDetails->explanation . "\n";
}
```
**Refusal fallbacks (Claude Fable 5) — opt in by default.** Fallbacks are opt-in: without them a refused request simply stops. New `claude-fable-5` code should include the server-side `fallbacks` parameter (beta header `server-side-fallback-2026-06-01`, fallback model `claude-opus-4-8`, on the beta messages call) by default. The exact PHP binding (and the client-side middleware for providers without server-side support) is not documented here — WebFetch the PHP SDK repo's `examples/` from `shared/live-sources.md`; full semantics in `shared/model-migration.md` → Migrating to Claude Fable 5 → `refusal` stop reason.
---
## Error Type
`APIStatusException` exposes a `->type` property for programmatic error classification:
```php
try {
$client->messages->create(...);
} catch (\Anthropic\Core\Exceptions\APIStatusException $e) {
echo $e->type?->value; // "rate_limit_error", "overloaded_error", etc.
}
```
@@ -0,0 +1,15 @@
# Message Batches — PHP
## Message Batches API
```php
$batch = $client->messages->batches->create(requests: [
['customId' => 'req-1', 'params' => ['model' => 'claude-opus-4-8', 'maxTokens' => 1024, 'messages' => [...]]],
['customId' => 'req-2', 'params' => [...]],
]);
// Poll $client->messages->batches->retrieve($batch->id) until processingStatus === 'ended',
// then iterate $client->messages->batches->results($batch->id).
```
---
@@ -0,0 +1,11 @@
# Files API — PHP
## Files API
```php
$file = $client->beta->files->upload(
file: fopen('upload_me.txt', 'r'),
betas: ['files-api-2025-04-14'],
);
// Reference $file->id as a file content block on ->beta->messages->create().
```
@@ -0,0 +1,27 @@
# Streaming — PHP
## 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.7"`
```php
use Anthropic\Messages\RawContentBlockDeltaEvent;
use Anthropic\Messages\TextDelta;
$stream = $client->messages->createStream(
model: 'claude-opus-4-8',
maxTokens: 64000,
messages: [
['role' => 'user', 'content' => 'Write a haiku'],
],
);
foreach ($stream as $event) {
if ($event instanceof RawContentBlockDeltaEvent && $event->delta instanceof TextDelta) {
echo $event->delta->text;
}
}
```
---
@@ -1,116 +1,6 @@
# Claude API — PHP
# Tool Use — PHP
> **Note:** The PHP SDK is the official Anthropic SDK for PHP. A beta tool runner is available via `$client->beta->messages->toolRunner()`. Structured output helpers are supported via `StructuredOutputModel` classes. Agent SDK is 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: 'claude-opus-4-8',
maxTokens: 16000,
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.7"`
```php
use Anthropic\Messages\RawContentBlockDeltaEvent;
use Anthropic\Messages\TextDelta;
$stream = $client->messages->createStream(
model: 'claude-opus-4-8',
maxTokens: 64000,
messages: [
['role' => 'user', 'content' => 'Write a haiku'],
],
);
foreach ($stream as $event) {
if ($event instanceof RawContentBlockDeltaEvent && $event->delta instanceof TextDelta) {
echo $event->delta->text;
}
}
```
---
For conceptual overview (tool definitions, tool choice, tips), see [shared/tool-use-concepts.md](../../shared/tool-use-concepts.md).
## Tool Use
@@ -125,7 +15,7 @@ $weatherTool = new BetaRunnableTool(
definition: [
'name' => 'get_weather',
'description' => 'Get the current weather for a location.',
'input_schema' => [
'inputSchema' => [
'type' => 'object',
'properties' => [
'location' => ['type' => 'string', 'description' => 'City and state'],
@@ -156,7 +46,7 @@ foreach ($runner as $message) {
### 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.
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;
@@ -223,61 +113,6 @@ foreach ($response->content as $block) {
`$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: 'claude-opus-4-8',
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.
---
## Prompt Caching
`system:` takes an array of text blocks; set `cacheControl` on the last block. Array-shape syntax (camelCase keys) is idiomatic. For placement patterns and the silent-invalidator audit checklist, see `shared/prompt-caching.md`.
```php
$message = $client->messages->create(
model: 'claude-opus-4-8',
maxTokens: 16000,
system: [
['type' => 'text', 'text' => $longSystemPrompt, 'cacheControl' => ['type' => 'ephemeral']],
],
messages: [['role' => 'user', 'content' => 'Summarize the key points']],
);
```
For 1-hour TTL: `'cacheControl' => ['type' => 'ephemeral', 'ttl' => '1h']`. There's also a top-level `cacheControl:` on `messages->create(...)` that auto-places on the last cacheable block.
Verify hits via `$message->usage->cacheCreationInputTokens` / `$message->usage->cacheReadInputTokens`.
---
## Structured Outputs
@@ -351,7 +186,7 @@ foreach ($message->content as $block) {
---
## Beta Features & Server-Side Tools
## 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:
@@ -372,31 +207,47 @@ $response = $client->beta->messages->create(
);
```
**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.
### Task budgets
```php
$response = $client->beta->messages->create(
model: 'claude-opus-4-8',
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: 'claude-opus-4-8', 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.
---
## Stop Details
When `stopReason` is `'refusal'`, the response includes structured `stopDetails`:
```php
if ($message->stopReason === 'refusal' && $message->stopDetails !== null) {
echo "Category: " . $message->stopDetails->category . "\n"; // "cyber" | "bio" | null
echo "Explanation: " . $message->stopDetails->explanation . "\n";
}
```
---
## Error Type
`APIStatusException` exposes a `->type` property for programmatic error classification:
```php
try {
$client->messages->create(...);
} catch (\Anthropic\Core\Exceptions\APIStatusException $e) {
echo $e->type?->value; // "rate_limit_error", "overloaded_error", etc.
}
```
+17 -10
View File
@@ -7,7 +7,7 @@
## Installation
```bash
composer require "anthropic-ai/sdk"
composer require "anthropic-ai/sdk" "guzzlehttp/guzzle:^7"
```
## Client Initialization
@@ -263,7 +263,14 @@ $client->beta->sessions->resources->delete($resource->id, sessionID: $session->i
## List and Download Session Files
> ️ Listing and downloading files an agent wrote during a session is not yet documented for PHP in this skill or in the apps source examples. See `shared/managed-agents-events.md` and the `anthropic-ai/sdk` PHP repository for the file list/download bindings.
```php
$files = $client->beta->files->list(
scopeID: 'sesn_abc123',
betas: ['managed-agents-2026-04-01'],
);
$content = $client->beta->files->download($files->data[0]->id);
file_put_contents('output.txt', $content);
```
---
@@ -293,7 +300,7 @@ $client->beta->sessions->delete($session->id);
```php
use Anthropic\Beta\Agents\BetaManagedAgentsAgentToolset20260401Params;
use Anthropic\Beta\Agents\BetaManagedAgentsMCPToolsetParams;
use Anthropic\Beta\Agents\BetaManagedAgentsUrlmcpServerParams;
use Anthropic\Beta\Agents\BetaManagedAgentsURLMCPServerParams;
use Anthropic\Beta\Sessions\BetaManagedAgentsAgentParams;
// Agent declares MCP server (no auth here — auth goes in a vault)
@@ -301,7 +308,7 @@ $agent = $client->beta->agents->create(
name: 'GitHub Assistant',
model: 'claude-opus-4-8',
mcpServers: [
BetaManagedAgentsUrlmcpServerParams::with(
BetaManagedAgentsURLMCPServerParams::with(
type: 'url',
name: 'github',
url: 'https://api.githubcopilot.com/mcp/',
@@ -395,8 +402,8 @@ $session = $client->beta->sessions->create(
[
'type' => 'github_repository',
'url' => 'https://github.com/org/repo',
'mountPath' => '/workspace/repo',
'authorizationToken' => 'ghp_your_github_token',
'mount_path' => '/workspace/repo',
'authorization_token' => 'ghp_your_github_token',
],
],
);
@@ -409,14 +416,14 @@ $resources = [
[
'type' => 'github_repository',
'url' => 'https://github.com/org/frontend',
'mountPath' => '/workspace/frontend',
'authorizationToken' => 'ghp_your_github_token',
'mount_path' => '/workspace/frontend',
'authorization_token' => 'ghp_your_github_token',
],
[
'type' => 'github_repository',
'url' => 'https://github.com/org/backend',
'mountPath' => '/workspace/backend',
'authorizationToken' => 'ghp_your_github_token',
'mount_path' => '/workspace/backend',
'authorization_token' => 'ghp_your_github_token',
],
];
```