TypeScript 指南
TypeScript 版 OpenAI Decisions API
OpenAI 尚未为其 Decisions API 发布 SDK——没有 client.decisions.create 可抄。本页展示针对本站端点的可用、完整类型化的 TypeScript 代码——该端点是可调用的 OpenAI Decisions API 替代方案,由 decisions-1 提供服务,遵循相同的受限决策模式。
更新于
定义契约
把请求类型定义一次,到处复用。model 是字面量联合类型,固定的 ID 不会写成手误。questions 是以你的 ID 为键的 record,每个问题的类型为 noul、choice 或 score。
把 answers 定义为以 type 为判别字段的联合类型——这正是让响应处理安全的原因:noul 答案有 noul 字段,choice 答案有 choice 和 probabilities——按 type 收窄就能得到正确的字段。
TypeScript
interface DecisionQuestion {
type: 'noul' | 'choice' | 'score'
instructions: string
criteria?: Record<string, string> | string[]
}
interface DecisionRequest {
model: 'decisions-1' | 'decisions-latest'
state: string | Record<string, unknown> | unknown[]
questions: Record<string, DecisionQuestion>
}
interface DecisionAnswers {
[questionId: string]:
| { type: 'noul'; noul: number }
| { type: 'choice'; choice: string; probabilities: Record<string, number>; confidence: number }
| { type: 'score'; score: number; legend: string[]; probabilities: Record<string, number>; confidence: number }
}发起调用
一次 POST,携带 Bearer 密钥。satisfies DecisionRequest 在编译期检查请求体;AbortSignal.timeout 防止挂起的调用卡住流水线。读取 answers 之前先按 type 字段收窄。
TypeScript
const res = await fetch('https://decisions-api.net/api/v1/decisions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(request satisfies DecisionRequest),
signal: AbortSignal.timeout(30000),
})
const { answers } = (await res.json()) as { answers: DecisionAnswers }
const team = answers.team
if (team.type === 'choice' && team.confidence >= 0.7) {
routeTo(team.choice)
}超时与重试
429 和 502 值得短退避重试——失败的调用不计费。402 表示余额不足:去充值,不要重试。422 是校验错误;报错信息会指明字段,应该修正请求体而不是重试。
TypeScript
async function decide(body: DecisionRequest, attempts = 3): Promise<DecisionAnswers> {
for (let i = 0; i < attempts; i++) {
const res = await fetch('https://decisions-api.net/api/v1/decisions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000),
})
if (res.status === 429 || res.status === 502) {
await new Promise(r => setTimeout(r, 2 ** i * 1000))
continue
}
if (res.status === 402) throw new Error('out of credits')
if (!res.ok) throw new Error(`decision call failed: ${res.status}`)
return (await res.json() as { answers: DecisionAnswers }).answers
}
throw new Error('decision call failed')
}把 provider 藏在一个函数后面
调用方应该只看到一个“文本进、标签出”的带类型函数——而不是 HTTP 细节。等 OpenAI 开放其 Decisions API 时,你只需替换 decide() 的内部实现,所有调用点不动。问题文本、选项和阈值都能沿用。
TypeScript
// Keep the decision behind one typed function. Swap the HTTP
// layer when OpenAI publishes its schema — callers never change.
export async function routeTicket(text: string): Promise<string> {
const answers = await decide({
model: 'decisions-1',
state: text,
questions: {
team: {
type: 'choice',
instructions: 'Which team should own this ticket?',
criteria: {
payments: 'Checkout or billing.',
frontend: 'Rendering or browser behavior.',
account: 'Login or permissions.',
},
},
},
})
const team = answers.team
return team.type === 'choice' && team.confidence >= 0.7 ? team.choice : 'triage'
}常见问题
OpenAI 官方有 Decisions API 的 SDK 示例吗?
没有。OpenAI 尚未发布其 Decisions API 的 SDK 方法或请求模式——任何展示 client.decisions.create 的代码都是虚构的。本页使用纯 HTTP,这也正是任何 provider SDK 内部的封装。
这些类型需要代码生成器吗?
不需要——本页的接口已覆盖整个契约。把它们复制进项目即可;代码量小到可以审查,且跨 provider 稳定。
如何发送结构化上下文?
state 不只接受字符串,也接受 JSON 对象或数组——在 json 请求体里直接传 dict,模型会把它作为上下文读取。
在浏览器里跑一次决策
跳过配置——在试用台用新访客的 2 个免费积分发起真实调用。