Corsair × Synthflow AI 插件完全指南:37 个类型化 API 操作、多租户认证与本地数据同步实战
【免费下载链接】corsairConnect your users to their apps项目地址: https://gitcode.com/GitHub_Trending/corsa/corsair
本指南以仓库内 packages/synthflowai/README.md 为骨架,结合 插件源码、HTTP 客户端实现、错误处理策略 及 官方文档 编写。你将掌握如何在 Corsair 应用中接入 Synthflow AI(语音 AI 平台,用于构建电话 Agent、通话自动化与对话式 IVR 流程),完成安装、租户认证、37 个类型化端点调用与本地数据库查询,并理解其底层实现原理。
一、插件是什么
@corsair-dev/synthflowai是 Corsair 生态中的 Synthflow AI 官方插件。Synthflow AI 是一个语音 AI 平台,专注于构建电话 Agent(assistant)、通话自动化(calls)与对话式 IVR 流程。通过该插件,你的应用可以获得:
- 37 个类型化 API 操作:覆盖 assistant、calls、contacts、knowledge bases、memory stores、phone books、actions、voices 八大资源域,全部以
tenant.synthflowai.api.*形式暴露; - 8 个本地同步实体:
actions、assistants、calls、contacts、knowledgeBases、memoryStores、phoneBooks、voices会被自动同步到本地数据库,支持快速的.search()/.list()查询; - 多租户隔离:每个租户独立持有 Synthflow AI 凭据,账号数据互不可见。
从源码角度看,插件是一个标准的 Corsair Plugin 对象(见 packages/synthflowai/index.ts),核心导出为synthflowai()工厂函数,配合 schema/index.ts 中声明的实体 Schema 与 endpoints/ 下的端点实现,共同构成完整能力面。
二、安装与初始化
2.1 安装
推荐使用 pnpm(与仓库 pnpm-workspace.yaml 一致),corsair与插件需要同时安装:
pnpm add @corsair-dev/synthflowai对应不同包管理器(参照 docs/plugins/synthflowai/overview.mdx):
npm install corsair @corsair-dev/synthflowai yarn add corsair @corsair-dev/synthflowai bun add corsair @corsair-dev/synthflowai插件通过peerDependencies声明了对corsair >= 0.1.0与zod ^4.1.13的依赖(见 packages/synthflowai/package.json),因此宿主项目必须自行安装这两个包。
2.2 创建 Corsair 实例并注册插件
// corsair.ts import Database from 'better-sqlite3'; import { createCorsair } from 'corsair'; import { synthflowai } from '@corsair-dev/synthflowai'; export const corsair = createCorsair({ plugins: [ synthflowai(), ], database: new Database('corsair.db'), kek: process.env.CORSAIR_KEK!, hub: { projectApiKey: process.env.CORSAIR_API_KEY!, signingSecret: process.env.CORSAIR_SIGNING_SECRET!, }, });要点说明:
synthflowai()不传任何参数即可,认证所需的 API Key 会在租户首次发起请求时由 Corsair 提示录入(详见第三节);kek(Key Encryption Key)与 Hub 密钥的获取方式见 docs/quick-start.mdx;- 多租户是默认行为:通过
corsair.withTenant(id)圈定调用范围,账户隔离细节见 docs/concepts/multi-tenancy.mdx。
从插件工厂实现看(index.ts 的synthflowai函数),它组装了id: 'synthflowai'、认证配置、Schema、端点注册表、端点元信息(风险等级与描述)、Webhook 匹配器、错误处理链以及keyBuilder,是一个完整的自包含插件单元。
三、认证机制:API Key
README 明确说明:Auth: API key,并且"Corsair prompts your tenant for credentials on first use"(租户首次使用时 Corsair 会提示录入凭据)。
3.1 认证配置
源码中认证配置固定为单个账号(index.ts):
export const synthflowaiAuthConfig = { api_key: { account: ['one'] as const, }, } as const satisfies PluginAuthConfig;即:每个租户只需一个 API Key,且只有一个账号维度。
3.2 Key 的获取链路
keyBuilder是理解认证的关键(index.ts 第 515-529 行):
- 若在插件选项中显式传入
key,且请求来自 endpoint,则直接使用该 key(适合服务端全局共用一个 key 的场景); - 否则从租户的 key 存储中读取
get_api_key(); - 读不到就抛出
AuthMissingError('synthflowai', 'api_key'),这正是"Corsair 提示录入凭据"的底层实现。
3.3 请求头注入
真正的 HTTP 层实现在 client.ts:所有请求都会注入以下 Header:
const config: OpenAPIConfig = { BASE: SYNTHFLOW_AI_API_BASE, // https://api.synthflow.ai/v2 VERSION: '2.0.0', WITH_CREDENTIALS: false, CREDENTIALS: 'omit', TOKEN: apiKey, HEADERS: { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: `Bearer ${apiKey}`, }, };即:API Base URL 为https://api.synthflow.ai/v2,认证方式是Authorization: Bearer <apiKey>。
3.4 连接租户
把租户引导到 Hub 托管的连接页完成凭据录入,然后由 Hub 把结果回传给应用:
const { connectUrl } = await corsair.manage.connect.createLink({ plugin: 'synthflowai', tenantId: 'acme', }); // 将用户浏览器重定向到 connectUrl完整流程见 docs/management/connect.mdx 与 docs/concepts/api-key.mdx。
四、端点总览(完整清单)
README 提供了完整的端点矩阵,包含操作路径、Operation ID、风险等级与描述。该表是插件能力面的权威索引,原文完整继承如下:
| Operation | Operation ID | Risk | Description |
|---|---|---|---|
actions.attach | synthflowai.api.actions.attach | write | Attach actions to a Synthflow AI agent |
actions.create | synthflowai.api.actions.create | write | Create a new action in Synthflow AI |
actions.delete | synthflowai.api.actions.delete | destructive | Delete an action in Synthflow AI [DESTRUCTIVE] |
actions.detach | synthflowai.api.actions.detach | write | Detach actions from a Synthflow AI agent |
actions.get | synthflowai.api.actions.get | read | Retrieve metadata about a specific action by ID |
actions.list | synthflowai.api.actions.list | read | List all actions in the workspace |
actions.update | synthflowai.api.actions.update | write | Update an existing action in Synthflow AI |
assistants.create | synthflowai.api.assistants.create | write | Create a new Synthflow AI assistant |
assistants.delete | synthflowai.api.assistants.delete | destructive | Delete a Synthflow AI assistant [DESTRUCTIVE] |
assistants.get | synthflowai.api.assistants.get | read | Retrieve details of an existing Synthflow AI assistant |
assistants.list | synthflowai.api.assistants.list | read | List all Synthflow AI assistants |
assistants.update | synthflowai.api.assistants.update | write | Update a Synthflow AI assistant's settings |
calls.create | synthflowai.api.calls.create | write | Initiate an outbound voice call via Synthflow AI |
calls.get | synthflowai.api.calls.get | read | Retrieve details and transcript of a phone call |
calls.list | synthflowai.api.calls.list | read | List call history logs for a Synthflow AI model |
contacts.create | synthflowai.api.contacts.create | write | Create a new contact in Synthflow AI |
contacts.delete | synthflowai.api.contacts.delete | destructive | Delete a contact in Synthflow AI [DESTRUCTIVE] |
contacts.get | synthflowai.api.contacts.get | read | Retrieve details of a contact by ID |
contacts.list | synthflowai.api.contacts.list | read | List contacts in Synthflow AI |
contacts.update | synthflowai.api.contacts.update | write | Update contact details in Synthflow AI |
knowledgeBases.attach | synthflowai.api.knowledgeBases.attach | write | Attach a knowledge base to an assistant model |
knowledgeBases.create | synthflowai.api.knowledgeBases.create | write | Create a new knowledge base in Synthflow AI |
knowledgeBases.delete | synthflowai.api.knowledgeBases.delete | destructive | Delete a knowledge base in Synthflow AI [DESTRUCTIVE] |
knowledgeBases.detach | synthflowai.api.knowledgeBases.detach | write | Detach a knowledge base from an assistant model |
knowledgeBases.get | synthflowai.api.knowledgeBases.get | read | Get details of a knowledge base by ID |
knowledgeBases.update | synthflowai.api.knowledgeBases.update | write | Update a knowledge base name or usage conditions |
memoryStores.attachToAgent | synthflowai.api.memoryStores.attachToAgent | write | Attach a memory store to an assistant agent |
memoryStores.create | synthflowai.api.memoryStores.create | write | Create a new memory store in Synthflow AI |
memoryStores.delete | synthflowai.api.memoryStores.delete | destructive | Delete a memory store in Synthflow AI [DESTRUCTIVE] |
memoryStores.detachFromAgent | synthflowai.api.memoryStores.detachFromAgent | write | Detach a memory store from an assistant agent |
memoryStores.get | synthflowai.api.memoryStores.get | read | Get details of a memory store by ID |
memoryStores.list | synthflowai.api.memoryStores.list | read | List memory stores in Synthflow AI |
memoryStores.update | synthflowai.api.memoryStores.update | write | Update a memory store's title and description |
phoneBooks.create | synthflowai.api.phoneBooks.create | write | Create a new phone book in Synthflow AI |
phoneBooks.delete | synthflowai.api.phoneBooks.delete | destructive | Delete a phone book in Synthflow AI [DESTRUCTIVE] |
phoneBooks.list | synthflowai.api.phoneBooks.list | read | List all phone books in the workspace |
voices.list | synthflowai.api.voices.list | read | List all text-to-speech voices available in the workspace |
4.1 风险等级语义
风险等级(read/write/destructive)定义在 index.ts 的synthflowaiEndpointMeta中,与 README 表格一一对应:
read:只读查询,如get、list;write:创建、更新、绑定类操作,如create、update、attach、detach;destructive:删除类操作(README 中标注[DESTRUCTIVE]),如delete,如actions.delete、assistants.delete、contacts.delete、knowledgeBases.delete、memoryStores.delete、phoneBooks.delete。
该元信息用于权限系统(PluginPermissionsConfig,可通过插件选项permissions覆盖),帮助你在多租户场景下对端点做细粒度放行。
五、关键端点实战与底层实现
每个端点都经过 Zod Schema 校验后,由 endpoints/ 下对应的实现发起 HTTP 请求。以下选取代表性端点,结合 endpoints/actions.ts 与 endpoints/types.ts 讲解。
5.1 通用调用方式
所有操作都通过多租户作用域暴露,返回类型由 Zod 输出 Schema 推导:
const tenant = corsair.withTenant('acme'); await tenant.synthflowai.api.actions.get({ action_id: 'act_123' });5.2 assistants.create:创建语音 Agent
Input(来自AssistantsCreateInputSchema,types.ts):
| Name | Type | Required | Description |
|---|---|---|---|
type | outbound \| inbound \| widget | Yes | 助手类型:外呼 / 呼入 / 网页挂件 |
name | string | Yes | 助手名称 |
agent | object | Yes | Agent 配置(见下) |
description | string | No | 描述 |
phone_number | string | No | 绑定号码 |
external_webhook_url | string | No | 外部 Webhook 回调地址 |
is_recording | boolean | No | 是否录音 |
agent对象结构(Schema 要求 5 个字段,.passthrough()允许透传额外字段):
{ prompt: string, // Agent 提示词 greeting_message: string,// 开场问候语 llm: string, // 底层 LLM language: string, // 语言 voice_id: string // TTS 音色 ID }Output:{ status?, response?: { model_id? }, details?: { phone?, voice? } },model_id是创建后得到的助手标识,后续调用(如calls.create)需要用到。
5.3 calls.create:发起外呼
Input(CallsCreateInputSchema):
| Name | Type | Required | Description |
|---|---|---|---|
model_id | string | Yes | 目标助手 ID |
phone | string | Yes | 被叫号码 |
name | string | Yes | 联系人姓名 |
from_phone_number | string | No | 主叫号码 |
custom_variables | object | No | 自定义变量,{ key, value }[]或对象 |
lead_email | string | No | 线索邮箱 |
lead_timezone | string | No | 线索时区 |
prompt | string | No | 本次通话覆盖提示词 |
greeting | string | No | 本次通话覆盖问候语 |
Output:{ status?, response?: { answer?, call_id? }, eta? },其中call_id用于后续calls.get查询通话详情与转写。
5.4 actions.attach / detach:为 Agent 绑定动作
attach的输入比较特殊,三种方式可任选其一(types.ts 的ActionsAttachInputSchema):
| Name | Type | Required | Description |
|---|---|---|---|
model_id | string | Yes | 目标 Agent ID |
actions | string[] | No | 动作名称列表 |
action_ids | string[] | No | 动作 ID 列表 |
items | object[] | No | 结构化动作项 |
底层实现(actions.ts 的attach)做了归一化:若提供了items则发送items,否则发送actions ?? action_ids,最终 POST 到/v2/actions/attach。detach类似,但只接受actions ?? action_ids。
5.5 actions.create:创建动作(多类型)
create输入是一组可选的类型键,每个键对应一种动作类型,值均为自由对象(z.record(z.string(), z.unknown()),types.ts 的ActionTypeBodySchema):
REAL_TIME_BOOKING / CALCOM / GHL / INFORMATION_EXTRACTOR / LIVE_TRANSFER / SEND_SMS / INCALL_SMS / INCALL_WHATSAPP / CUSTOM_ACTION / CUSTOM_EVAL5.6 分页与查询参数
list类操作普遍支持limit/offset分页。以actions.list为例(actions.ts 的list),实现会把limit/offset组装为 GET query 参数;voices.list额外支持workspace(必填)、search与provider(枚举elevenlabs | deepgram | synthflow)过滤。
全部 37 个端点的输入/输出字段、必填性、嵌套类型与返回值,可查阅 docs/plugins/synthflowai/api.mdx(按 Actions / Assistants / Calls / Contacts 等分组逐项列出)。
六、错误处理与重试策略
6.1 统一的错误类型
所有 Synthflow AI 调用都经由 client.ts 的makeSynthflowAiRequest封装,抛出的错误统一为:
SynthflowAiAPIError:携带code、status、body,覆盖 HTTP 错误与网络错误;SynthflowAiRateLimitError:HTTP 429 专用,携带retryAfterMs(来自响应头的重试时间)。
错误消息提取遵循"detail.description → detail 字符串 → message → error"的优先级,尽量还原服务端返回的可读信息。
6.2 内置重试策略
error-handlers.ts 内置了三类错误处理器:
| 类型 | 匹配条件 | 行为 |
|---|---|---|
RATE_LIMIT_ERROR | 429 状态码,或消息包含too many requests/rate_limited/rate limit | maxRetries: 5,并按retryAfterMs回退 |
AUTH_ERROR | 401 状态码,或消息包含unauthorized/invalid_auth/invalid api key/401 | maxRetries: 0,立即失败 |
DEFAULT | 兜底 | maxRetries: 0 |
认证错误不重试是合理的——401 通常意味着凭据失效,重试无意义;而限流最多重试 5 次,配合服务端Retry-After提示做指数回退,保证生产稳定性。你也可以通过插件选项errorHandlers覆盖或扩展这些策略:
synthflowai({ errorHandlers: { // 合并进默认 errorHandlers }, });七、本地数据库同步:.search()与.list()
插件将 Synthflow AI 数据同步到 Corsair 本地数据库(默认 SQLite,如corsair.db),从而支持快速查询,无需频繁打远程 API。
7.1 8 个同步实体
定义于 schema/index.ts 的SynthflowAiSchema(version1.0.0):
assistants、calls、contacts、knowledgeBases、memoryStores、phoneBooks、actions、voices
各实体的字段模型见 schema/database.ts,例如SynthflowAiCall含call_id/model_id/call_status/lead_phone_number/duration,SynthflowAiVoice含voice_id/name/workspace/provider。所有模型均使用.loose()(宽松模式),远端新增字段不会导致同步失败。
7.2 查询示例
// 通用形态:data 传过滤器,limit/offset 分页 const rows = await corsair.synthflowai.db.calls.search({ data: { model_id: 'mdl_1', call_status: 'completed', duration: { gte: 60 } }, limit: 100, offset: 0, });7.3 各实体可搜索字段与操作符
以下来自 docs/plugins/synthflowai/database.mdx(entity_id为所有实体共有的隔离字段,用于多租户数据圈定):
Actions(db.actions.search):entity_id、action_id、id、name—— 字符串字段均支持equals, contains, startsWith, endsWith, in。
Assistants(db.assistants.search):entity_id、model_id、name、type、description、phone_number—— 同上字符串操作符。
Calls(db.calls.search):entity_id、call_id、model_id、call_status、lead_phone_number(字符串操作符);duration(number,支持equals, gt, gte, lt, lte, in)。
Contacts(db.contacts.search):entity_id、id、name、phone_number、email、company。
Knowledge Bases(db.knowledgeBases.search):entity_id、id、knowledge_base_id、name、rag_use_condition。
Memory Stores(db.memoryStores.search):entity_id、id、title、description。
Phone Books(db.phoneBooks.search):entity_id、phone_book_id、name、workspace_id(字符串);entry_count(number,支持比较操作符)。
Voices(db.voices.search):entity_id、voice_id、name、workspace。
所有
.search()均接受limit/offset分页;同一路径上不带.search后缀即为.list()(如db.actions.list())。通用数据库能力见 docs/concepts/database.mdx,同步机制见 docs/concepts/integrations.mdx。
八、Webhooks:当前无订阅
README 明确说明No webhooks。源码佐证:synthflowaiWebhooksNested为空对象(index.ts),pluginWebhookMatcher恒返回false,即插件不会注册任何 Webhook 接收器。如果你需要监听 Synthflow AI 侧的事件(如通话结束回调),目前需要通过assistants.create/update的external_webhook_url字段自行配置外部回调地址。
九、测试与验证
仓库为该插件配备了完整测试,可作为理解行为与验证集成的参考:
- packages/synthflowai/api.test.ts:API 行为测试;
- packages/synthflowai/integration.test.ts:集成测试(通过
pnpm test:live运行,见 package.json); - packages/synthflowai/schema.test.ts:Schema 校验测试。
十、License 与生态位置
插件以Apache-2.0协议开源(README 与 package.json 均标注)。整个插件是 Corsair 集成生态的一部分——通过 mcp-adapters 可以将synthflowai.api.*操作直接暴露为 MCP 工具,供各类 AI Agent(如 Claude、Cursor、Codex 等)调用;配合 docs/adapters/client.mdx 中的适配器能力,可进一步与 LangChain、LlamaIndex、Mastra 等框架打通。想了解插件从 OpenAPI/JSON 生成的过程,可参考仓库 scripts/generate-plugin.ts。
结语
通过@corsair-dev/synthflowai,Corsair 应用可以用一套类型安全、多租户隔离、自带重试与本地缓存的编程模型,快速接入 Synthflow AI 的语音 Agent、通话与知识库能力。安装插件、创建租户连接、按端点清单调用tenant.synthflowai.api.*、用db.<entity>.search()做本地查询,四条主线即构成完整的集成闭环;风险等级元信息与错误处理策略则保障了生产环境下的权限可控与稳定性。
【免费下载链接】corsairConnect your users to their apps项目地址: https://gitcode.com/GitHub_Trending/corsa/corsair
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考