news 2026/10/6 2:25:53

PHP SDK 工具调用实战指南:Beta 工具运行器、手动 Agentic Loop 与结构化输出

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP SDK 工具调用实战指南:Beta 工具运行器、手动 Agentic Loop 与结构化输出
  • 文档
  • 提示工程
  • 人工智能

【免费下载链接】claude-code-system-prompts

All parts of Claude Code's system prompt, 27 builtin tool descriptions, sub agent prompts (Plan/Explore/Task), utility prompts (CLAUDE.md, compact, statusline, magic docs, WebFetch, Bash cmd, security review, agent creation). Updated for each Claude Code version.

项目地址:https://gitcode.com/gh_mirrors/cl/claude-code-system-prompts
点击查看免费下载

本文以 Claude Code 系统提示仓库(claude-code-system-prompts)中嵌入的 PHP 语言参考文档 system-prompts/data-tool-use-reference-php.md 为骨架展开,面向使用 Anthropic PHP SDK(anthropic-ai/sdk)构建 Agent 应用、需要在 Messages API 中接入函数调用(Tool Use)的开发者。读完本文你将掌握:通过toolRunner()自动执行工具的 Beta 路径、使用 camelCase 键手动编写 Agentic Loop 的完整模式、基于StructuredOutputModel类与原生 JSON Schema 的结构化输出方案,以及 MCP 服务器、任务预算、缓存诊断等 Beta 特性与 Anthropic 定义工具(bash、web_search、text_editor、code_execution)的正确用法与常见陷阱。

一、文档定位:一份嵌入在 Claude Code 系统提示中的 PHP SDK 参考

在 Claude Code 的运行时上下文中,data-tool-use-reference-php.md属于“Data”类参考文档,ccVersion: 2.1.246,是随 Claude Code 版本更新的 PHP 语言工具调用速查表。它与其他语言的对应文档(C# 版、Ruby 版)并列,共同构成多语言 SDK 的工具调用指引。原文档明确指出,关于工具定义、工具选择与使用技巧的概念性总览属于一份共享文档(内部路径shared/tool-use-concepts.md),本文聚焦 PHP 特有的实现细节。

从 PHP API 参考文档 可以确认 PHP SDK 的几个关键前提:

  • 安装方式:composer require "anthropic-ai/sdk";
  • 客户端初始化:new Client(apiKey: getenv("ANTHROPIC_API_KEY")),此外还支持 Amazon Bedrock(MantleClient)、Google Vertex AI(Vertex\Client::fromEnvironment)、Anthropic Foundry(Foundry\Client::withCredentials);
  • 命名参数风格:SDK 的messages->create()采用 PHP 8 命名参数调用(model:、maxTokens:、messages:),且要求 SDK v0.5.0+(详见 PHP 流式参考:v0.4.0 及更早版本使用单一$params数组,用命名参数调用会抛出Unknown named parameter $model,升级命令为composer require "anthropic-ai/sdk:^0.7")。

文中的{{OPUS_ID}}是 Claude Code 会话注入时的模型 ID 占位符(README 提到提示词中包含这类插值变量),实际使用时请替换为你所选用的模型 ID(如claude-opus-4-8等)。

二、两条工具调用路径总览

PHP SDK 提供了两条接入工具调用的路径,二者的选择取决于你是否需要 SDK 替你管理“调用模型 → 执行工具 → 回填结果”的循环:

路径入口特点适用场景
Beta 工具运行器$client->beta->messages->toolRunner()以BetaRunnableTool定义“工具 schema + run 闭包”,runner 自动循环直至模型给出最终文本快速原型、无需精细控制每轮内容的场景
手动 Agentic Loop$client->messages->create()+while ($response->stopReason === 'tool_use')完全掌控消息历史拼接、工具分发与结果回填生产级应用、需要自定义工具执行与错误处理

两条路径都遵循相同的工具定义格式:一个包含name、description、inputSchema的数组(JSON Schema 风格)。PHP SDK 的关键约定是:客户端使用 camelCase 键(inputSchema、toolUseID、stopReason),SDK 在传输时自动映射为 API 的 snake_case(input_schema、tool_use_id、stop_reason)——该行为自 SDK v0.5.0 起生效。这是 PHP 参考与 C# 版(属性 PascalCase)、Ruby 版(snake_case 符号)在风格上的显著差异,也是新手最容易踩坑的地方。

三、Beta 工具运行器(Tool Runner)

Beta 状态提示:PHP SDK 通过$client->beta->messages->toolRunner()提供工具运行器。定义工具使用BetaRunnableTool——它由“定义数组 +run闭包”两部分组成:定义数组描述工具的 schema(模型侧可见),run闭包则在本地执行工具逻辑并返回结果字符串。

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; } } }

要点拆解:

  • run闭包的入参是模型按inputSchema生成的参数数组(这里是['location' => 'Paris']),返回值会作为tool_result内容回传给模型;
  • toolRunner()返回的是一个可迭代对象(foreach ($runner as $message)),运行器在内部完成多轮工具执行后,逐条产出最终消息;配合 PHP 流式参考 中createStream()的RawContentBlockDeltaEvent/TextDelta模式,也可以按块增量输出;
  • 每个message->content都是多态块数组(TextBlock、ToolUseBlock、ThinkingBlock),必须先检查$block->type === 'text'再访问$block->text——这一点在 PHP API 参考 的基本请求示例中被反复强调:启用扩展思考时ThinkingBlock会排在最前,直接访问->text会抛异常。

四、手动 Agentic Loop:camelCase 键与完整循环模式

当你需要完全掌控每一轮交互时,使用手动循环。工具仍以数组形式传入,但所有键使用 camelCase:

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; } }

这个循环模式是 Agent 应用的核心骨架,逐段理解其职责:

  1. 首次请求:携带tools定义与初始messages发起调用;
  2. 判断循环条件:$response->stopReason === 'tool_use'(注意这是 camelCase 属性;若模型直接结束,stopReason为end_turn等值则退出循环);
  3. 分发工具:遍历content,对每个ToolUseBlock取出$block->name(工具名,用于switch/映射分发)、$block->input(已解析的 JSON 输入,array<string,mixed>)、$block->id(必须原样回传为toolUseID,这是 API 将工具结果关联到对应调用块的凭证);
  4. 构造tool_result:每个结果块形如['type' => 'tool_result', 'toolUseID' => $block->id, 'content' => $result];
  5. 回填消息历史:先追加['role' => 'assistant', 'content' => $response->content](原样回显模型生成的助手轮内容,包含其中的tool_use块),再追加['role' => 'user', 'content' => $toolResults];助手轮与工具结果轮必须成对追加,否则 API 会因tool_useID 缺失匹配的tool_result而拒绝后续请求(C# 参考 中同样强调了“每个 tool_use 块必须恰好对应一个 tool_result”);
  6. 重复调用直至stopReason不再为tool_use,最后输出文本块。

类型检查方面,原文档特别注明:$block->type === 'tool_use'同样可用,但instanceof ToolUseBlock能让 PHPStan 等静态分析工具完成类型收窄,推荐在需要属性访问($block->id、$block->name)时使用instanceof形式。

五、结构化输出:从 PHP 类到 JSON Schema

当你不满足于解析自由文本,而是要求模型返回严格符合 schema 的 JSON 时,PHP SDK 提供两种结构化输出方式。

5.1 推荐方案:StructuredOutputModel 类

定义一个实现StructuredOutputModel接口的 PHP 类,配合StructuredOutputModelTrait与Constrained属性,然后以outputConfig: ['format' => Person::class]传入:

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;

这套方案的核心映射规则非常直观,值得单独记忆:

  • 类型从 PHP 类型声明自动推断:string→{"type": "string"}、int→{"type": "integer"}等,无需手写 schema;
  • #[Constrained(description: '...')]属性用于附加字段描述,帮助模型生成更准确的值;
  • 可空属性(?string)自动成为可选字段:public ?string $email = null;意味着email在输出中可缺省,而非可空类型(如public string $name;)则进入required列表;
  • $message->parsedOutput()返回Person实例,直接以强类型方式访问字段,省去手写json_decode与类型断言。

5.2 原生 JSON Schema(Raw Schema)

如果你已有现成的 JSON Schema(例如从 OpenAPI 迁移、或需要additionalProperties: false等细粒度约束),可以直接把 schema 作为数组传入:

$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; } }

注意这里的差异:Raw Schema 方案下模型输出的有效 JSON 位于第一个文本块中(foreach+break只取第一个文本块),需要自行json_decode;而StructuredOutputModel方案由parsedOutput()直接完成反序列化。additionalProperties: false可用于严格限制模型不得输出 schema 之外的键。

六、Beta 特性与 Anthropic 定义工具

6.1betas:只存在于 beta 命名空间

原文档用一个醒目的警告开篇:betas:不是$client->messages->create()的参数——它只存在于 beta 命名空间($client->beta->messages->create())。凡是需要显式 opt-in 请求头(beta header)的特性,都必须走 beta 路径。最典型的例子是 MCP 服务器接入:

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']], );

这里BetaRequestMCPServerURLDefinition::with(name: ..., url: ...)是 PHP SDK 提供的 MCP 服务器定义构造器,betas: ['mcp-client-2025-11-20']是启用该 beta 特性的版本化请求头。

6.2 任务预算(Task Budgets)

通过outputConfig的taskBudget参数为多工具 Agent 任务设置令牌预算:

$response = $client->beta->messages->create( model: '{{OPUS_ID}}', maxTokens: 16000, outputConfig: ['taskBudget' => ['type' => 'tokens', 'total' => 64000]], tools: [...], messages: [...], betas: ['task-budgets-2026-03-13'], );

预算类型为tokens,total指定整个任务(含多轮工具调用)的令牌总量上限。

6.3 缓存诊断(Cache Diagnostics)

把上一次响应的id作为previousMessageId传入下一次请求,即可在响应上读取diagnostics对象,用于排查 prompt 缓存命中情况:

$r2 = $client->beta->messages->create( model: '{{OPUS_ID}}', maxTokens: 1024, diagnostics: ['previousMessageId' => $r1->id], betas: ['cache-diagnosis-2026-04-07'], messages: [...], );

与之配合的常规缓存实践见 PHP API 参考:system:接受文本块数组,在最后一个块上设置cacheControl(['type' => 'ephemeral'],1 小时 TTL 时追加'ttl' => '1h'),并通过$message->usage->cacheCreationInputTokens/cacheReadInputTokens验证命中。

6.4 Anthropic 定义工具:服务端执行 vs 客户端执行

bash、web_search、text_editor、code_execution四类 Anthropic 定义工具已经 GA,在 beta 与常规两条路径上都可用,且不需要betas:头。它们的关键差异在于执行位置:

  • 服务端执行:web_search、code_execution——模型调用后由 Anthropic 服务端直接执行并返回结果;
  • 客户端执行:bash、text_editor——SDK 只返回tool_use块,你需要在本地处理执行逻辑(这与手动 Agentic Loop 模式一致)。

PHP SDK 为每个工具提供了 beta 与常规两套类名:

工具常规命名空间(Anthropic\Messages\)Beta 命名空间(Anthropic\Beta\Messages\)
bashToolBash20250124BetaToolBash20250124
web_searchWebSearchTool20260209BetaWebSearchTool20260209
text_editorToolTextEditor20250728BetaToolTextEditor20250728
code_executionCodeExecutionTool20260120BetaCodeExecutionTool20260120

类名中的日期后缀是版本化类型标识(与mcp-client-2025-11-20等 beta 头的版本化思路一致),构造时会把type/name自动填好。对比 C# 参考 可看到跨语言一致的设计:web_search 支持AllowedDomains、BlockedDomains、MaxUses、UserLocation等可选约束(PHP 中对应数组键)。

6.5 工具搜索(Tool Search,非 beta、服务端)

当工具数量很多时,可以让模型先用正则工具搜索再决定加载哪些工具。声明方式是在tools:数组里加入特殊条目,其余用户工具标记deferLoading => true延迟加载:

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 ],

该特性位于常规(非 beta)路径,由服务端处理。

6.6 记忆工具(Memory Tool,非 beta、客户端执行)

声明方式为['type' => 'memory_20250818', 'name' => 'memory']。该工具由客户端执行:当模型发起tool_use时,你在固定的/memories目录下执行文件读写。原文档特别强调了一条安全红线:

校验每一个模型提供的路径:将其解析为规范形式(canonical form),确认其仍位于记忆目录之内;拒绝路径穿越(..)与符号链接(symlink)。

这是因为模型输出的路径不可信,若不校验就可能让模型读取或写入记忆目录之外的文件——这类“由模型驱动但由客户端执行”的工具,安全边界必须由客户端代码自己守牢。

七、配套实践要点:把工具调用接入完整的 PHP 应用

将上面的工具调用模式与 PHP API 参考 中的其他能力组合,可以构成完整的 Agent 应用:

  • 多态内容块守卫:无论工具调用还是普通对话,遍历$message->content时都先判断$block->type(text/tool_use/thinking),再访问对应属性;扩展思考开启时ThinkingBlock位于最前,且其signature在多轮对话回传时必须原样保留;
  • 错误分类:用\Anthropic\Core\Exceptions\APIStatusException的->type属性做程序化错误分流(rate_limit_error、overloaded_error等),可在工具循环中针对限流实现退避重试;
  • 拒绝响应:stopReason === 'refusal'时响应携带结构化stopDetails(category、explanation),可用于工具调用前的合规校验;
  • 批量场景:若工具任务彼此独立,可改用 PHP Batches 参考 的$client->messages->batches->create(requests: [...]),轮询retrieve($batch->id)至processingStatus === 'ended'后迭代results($batch->id),以更低成本批量执行;
  • 版本约束:camelCase 自动映射、命名参数调用、流式事件均要求 SDK v0.5.0+,升级到^0.7以获取完整能力(详见 PHP 流式参考)。

八、小结

回到data-tool-use-reference-php.md这条主线,可以提炼出 PHP SDK 工具调用的四个核心心智模型:

  1. 两条路径:Beta 工具运行器(BetaRunnableTool+toolRunner())适合快速闭环;手动 Agentic Loop(while ($response->stopReason === 'tool_use')+ 成对追加 assistant/user 消息)适合生产级精细控制;
  2. 一个键名约定:PHP 侧全部使用 camelCase(inputSchema、toolUseID、stopReason),SDK 自动映射为线上 snake_case,自 v0.5.0 起生效;
  3. 两种结构化输出:类驱动(StructuredOutputModel+#[Constrained]+parsedOutput())与 schema 驱动(json_schema原始数组 + 首文本块json_decode);
  4. 一条边界纪律:betas:只属于 beta 命名空间;Anthropic 定义工具中 web_search/code_execution 服务端执行、bash/text_editor 与 memory 客户端执行,客户端执行型工具的模型输入(尤其是文件路径)必须严格校验。

这套参考文档随 Claude Code 版本持续更新(本仓库还收录了 CHANGELOG.md 记录各版本提示词演变),建议在接入新 SDK 版本时回到对应文档核对类名与 beta 头的版本后缀是否变化。

  • 文档
  • 提示工程
  • 人工智能

【免费下载链接】claude-code-system-prompts

All parts of Claude Code's system prompt, 27 builtin tool descriptions, sub agent prompts (Plan/Explore/Task), utility prompts (CLAUDE.md, compact, statusline, magic docs, WebFetch, Bash cmd, security review, agent creation). Updated for each Claude Code version.

项目地址:https://gitcode.com/gh_mirrors/cl/claude-code-system-prompts
点击查看免费下载

相关推荐

上一篇:5分钟上手libcdma:从安装到实现异步内存传输的完整指南
下一篇:开发者必读:openEuler-agreements中的PR重新提交完整流程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 2:24:58

基于Spring Boot的玉林地区农产品销售平台的设计与开发

一、选题的目的和意义本选题的核心目的&#xff0c;是解决百色市非遗文化宣传与管理中的现存痛点&#xff0c;搭建一个集宣传、展示、管理、互动于一体的数字化平台[1]。当前百色市拥有丰富的非遗资源&#xff0c;但存在传播渠道单一、信息分散、管理模式传统等问题&#xff0c…

作者头像 李华
网站建设 2026/10/6 2:19:19

uBlock Origin:免费开源的轻量广告拦截插件

uBlock Origin&#xff1a;免费开源的轻量广告拦截插件 【免费下载链接】uBlock uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean. 项目地址: https://gitcode.com/GitHub_Trending/ub/uBlock 点开一个新闻页&#xff0c;标题还没读完&a…

作者头像 李华
网站建设 2026/10/6 2:15:32

AI Agent 面试题 166:如何设计Agent的上下文优先级排序机制?

&#x1f525; AI Agent 面试题 166&#xff1a;如何设计Agent的上下文优先级排序机制&#xff1f;摘要&#xff1a;本文深入解析了「如何设计Agent的上下文优先级排序机制&#xff1f;」这一 AI Agent 领域的核心面试题。文章从 上下文窗口管理 的基本概念出发&#xff0c;系统…

作者头像 李华