Go SDK
前提条件
第 1 步:安装
该模块直接从 GitHub 分发。生产构建应固定到 Release Tag。
下文示例默认已经导入以下依赖:
在调用函数内创建 context:
第 2 步:选择协议接口
OpenAI
Anthropic
WithAPIBaseURL 会派生 <base>/openai/v1。只有需要覆盖模型 API 地址时才使用 WithOpenAIBaseURL。
Chat Completions
Responses
CreateResponse 与 StreamResponse 保留 Responses 原生 output items 和事件结构。
上面的显式非 nil 空 Tools 切片让连通性示例保持无工具调用。删除它即可启用 SDK 默认兜底工具,也可以替换为你自己的完整声明。
编排响应
model: "auto" 请求可能以编排(多任务规划)模式处理。SDK 返回的是网关原始结构,因此需要按其形态分支处理:
Choices[0].Message.Content是一段 JSON 编码的数组(每个元素为{ "title", "content" }的每任务输出),而非普通字符串。渲染前需先json.Unmarshal;顶层的plan字段可用于确认是否为编排模式。metadata是一个数组,每个任务对应一条(包括保留项__planner__/__final__)。总费用应将各条的billing.credits_used相加,而非读取单个metadata.billing对象。- 流式场景下,先到达一个 planning 事件(一个
orchestration.phase为planning的 chunk,携带有序的plan),其后紧跟__planner__的 metadata 事件;随后每个任务的完整正文作为一个 chunk 到达,该 chunk 携带orchestration字段(task_id、task_seq、task_status、title),每个任务之后再跟一个独立的 metadata 事件(值为单个对象,而非数组)。
第 3 步:模型列表
需要英文描述时使用 joytoken.ModelLocaleEN。ListModels(ctx) 不传 locale,因此接口默认返回英文描述。目录项位于 models.Data.Models。
工具调用
SDK 会把调用方工具与默认兜底工具严格分开。每个请求只选择一个来源:
显式空切片表示不发送任何工具。Client 注册工具会整体替换默认工具,不做合并。续轮会继续携带同一组已解析声明,而且每个工具只出现一次。
选择正确的方法
只有优先级 3 选择了 SDK 自有默认工具时,基础 Create* 才会自动续轮。传入请求工具或注册 Client 工具后,Create* 始终只透传一次。
请求级声明不包含可执行的 Go handler。若要通过 Run* 执行它,还必须在 Client 上注册同名 handler。找不到 handler 时,SDK 会把结构化工具错误回传模型,不会猜测或执行任意代码。
注册并执行工具
构造 Client 时使用 joytoken.WithToolHandler(或 joytoken.WithTools)注册工具:
默认兜底工具
调用方未提供工具时,SDK 会提供 7 个本地工具:
Responses 的托管工具由上游执行,而不是 Go SDK 本地执行。WithDefaultBuiltinTools(true) 当前只会启用 web_search_preview,并且默认关闭。托管 file_search 必须由调用方显式传入有效的 vector_store_ids,SDK 不会自动生成。
托管搜索成功执行时,Responses 输出中会包含 web_search_call。应检查返回的 output items,不能只根据 HTTP 请求成功就判断工具已经运行。
只发送 Gateway 明确支持的工具 type。不要把 web_search、web_search_20250305 与 web_search_preview 当作别名一起发送;未知类型可能在模型路由前就被拒绝。
有副作用的工具受门控保护
file_write 和 shell 始终会声明给模型,但没有宿主授权就绝不执行。安装一个权限回调才能让它们可运行;若未配置回调,模型虽能看到该能力,但每次调用都会在执行期被拒绝(fail-safe 失败即安全)。
如果某个工具你根本用不到,也可以直接把它从默认集合里去掉(而不只是拦截执行):
WithoutDefaultTools 不会过滤调用方显式注册的工具。
循环结果与排查信息
RunChatResult 包含 FinalText、Messages、逐轮 Steps、StoppedBy 和厂商中立的 FinishReason。malformed_function_call 表示模型反复返回非法工具调用负载,不应当作正常空回答。续轮会保留已解析的工具;首个工具调用后,强制 ToolChoice 会放宽为 auto,让模型可以自然结束。
厂商工具元数据
某些厂商会给工具调用附加不透明元数据,必须在下一轮原样返回。JoyToken Go SDK v0.1.3 及以后将其暴露为 ToolCall.ExtraContent,并在 Chat、Responses、Messages、流式以及 Agent 工具循环中原样保留。例如 Gemini 的函数调用可能携带 extra_content.google.thought_signature。
SDK 还会捕获直接位于工具调用顶层的 thought_signature,暴露为 ToolCall.ThoughtSignature(序列化为 thought_signature),与嵌套在 extra_content 中的形式相区分。Gemini 经由网关的 Chat Completions 端点会把它返回在 tool_call 顶层;必须在续跑轮次原样(verbatim)回传,否则 provider 会拒绝该请求(此前表现为 503)。
自动的 Run* 方法会原样保留该字段而不作解释。手写循环时,请追加完整的 assistant 消息或返回的 ToolCall;不要仅用 ID、Type、Function 重建一个调用。
如果后续模型轮次失败,所有显式 Run* 方法都会同时返回错误和非 nil 的部分结果。调用方可先读取已完成的 Steps 以及累积的 Messages 或 Input,再决定重试或恢复。
生产排查建议记录 Gateway request ID、响应 metadata、工具来源(请求 / Client / 默认)、工具名、step 和停止原因。不要记录 API Key 或未脱敏的敏感工具输入。
超时与重试
请求和流默认 60 秒超时。WithTimeout 修改完整操作的超时;传非正值可禁用 SDK 超时。
模型 POST 不天然幂等,因此自动重试默认关闭。WithMaxRetries(n) 可为 HTTP 429、5xx 和传输错误启用带上限、抖动及 Retry-After 支持的退避重试。只有在可接受重复执行或重复计费风险时才应开启。
