news 2026/9/16 20:05:36

Corsair × Synthflow AI 插件完全指南:37 个类型化 API 操作、多租户认证与本地数据同步实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Corsair × Synthflow AI 插件完全指南:37 个类型化 API 操作、多租户认证与本地数据同步实战

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 个本地同步实体actionsassistantscallscontactsknowledgeBasesmemoryStoresphoneBooksvoices会被自动同步到本地数据库,支持快速的.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.0zod ^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 行):

  1. 若在插件选项中显式传入key,且请求来自 endpoint,则直接使用该 key(适合服务端全局共用一个 key 的场景);
  2. 否则从租户的 key 存储中读取get_api_key()
  3. 读不到就抛出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、风险等级与描述。该表是插件能力面的权威索引,原文完整继承如下:

OperationOperation IDRiskDescription
actions.attachsynthflowai.api.actions.attachwriteAttach actions to a Synthflow AI agent
actions.createsynthflowai.api.actions.createwriteCreate a new action in Synthflow AI
actions.deletesynthflowai.api.actions.deletedestructiveDelete an action in Synthflow AI [DESTRUCTIVE]
actions.detachsynthflowai.api.actions.detachwriteDetach actions from a Synthflow AI agent
actions.getsynthflowai.api.actions.getreadRetrieve metadata about a specific action by ID
actions.listsynthflowai.api.actions.listreadList all actions in the workspace
actions.updatesynthflowai.api.actions.updatewriteUpdate an existing action in Synthflow AI
assistants.createsynthflowai.api.assistants.createwriteCreate a new Synthflow AI assistant
assistants.deletesynthflowai.api.assistants.deletedestructiveDelete a Synthflow AI assistant [DESTRUCTIVE]
assistants.getsynthflowai.api.assistants.getreadRetrieve details of an existing Synthflow AI assistant
assistants.listsynthflowai.api.assistants.listreadList all Synthflow AI assistants
assistants.updatesynthflowai.api.assistants.updatewriteUpdate a Synthflow AI assistant's settings
calls.createsynthflowai.api.calls.createwriteInitiate an outbound voice call via Synthflow AI
calls.getsynthflowai.api.calls.getreadRetrieve details and transcript of a phone call
calls.listsynthflowai.api.calls.listreadList call history logs for a Synthflow AI model
contacts.createsynthflowai.api.contacts.createwriteCreate a new contact in Synthflow AI
contacts.deletesynthflowai.api.contacts.deletedestructiveDelete a contact in Synthflow AI [DESTRUCTIVE]
contacts.getsynthflowai.api.contacts.getreadRetrieve details of a contact by ID
contacts.listsynthflowai.api.contacts.listreadList contacts in Synthflow AI
contacts.updatesynthflowai.api.contacts.updatewriteUpdate contact details in Synthflow AI
knowledgeBases.attachsynthflowai.api.knowledgeBases.attachwriteAttach a knowledge base to an assistant model
knowledgeBases.createsynthflowai.api.knowledgeBases.createwriteCreate a new knowledge base in Synthflow AI
knowledgeBases.deletesynthflowai.api.knowledgeBases.deletedestructiveDelete a knowledge base in Synthflow AI [DESTRUCTIVE]
knowledgeBases.detachsynthflowai.api.knowledgeBases.detachwriteDetach a knowledge base from an assistant model
knowledgeBases.getsynthflowai.api.knowledgeBases.getreadGet details of a knowledge base by ID
knowledgeBases.updatesynthflowai.api.knowledgeBases.updatewriteUpdate a knowledge base name or usage conditions
memoryStores.attachToAgentsynthflowai.api.memoryStores.attachToAgentwriteAttach a memory store to an assistant agent
memoryStores.createsynthflowai.api.memoryStores.createwriteCreate a new memory store in Synthflow AI
memoryStores.deletesynthflowai.api.memoryStores.deletedestructiveDelete a memory store in Synthflow AI [DESTRUCTIVE]
memoryStores.detachFromAgentsynthflowai.api.memoryStores.detachFromAgentwriteDetach a memory store from an assistant agent
memoryStores.getsynthflowai.api.memoryStores.getreadGet details of a memory store by ID
memoryStores.listsynthflowai.api.memoryStores.listreadList memory stores in Synthflow AI
memoryStores.updatesynthflowai.api.memoryStores.updatewriteUpdate a memory store's title and description
phoneBooks.createsynthflowai.api.phoneBooks.createwriteCreate a new phone book in Synthflow AI
phoneBooks.deletesynthflowai.api.phoneBooks.deletedestructiveDelete a phone book in Synthflow AI [DESTRUCTIVE]
phoneBooks.listsynthflowai.api.phoneBooks.listreadList all phone books in the workspace
voices.listsynthflowai.api.voices.listreadList all text-to-speech voices available in the workspace

4.1 风险等级语义

风险等级(read/write/destructive)定义在 index.ts 的synthflowaiEndpointMeta中,与 README 表格一一对应:

  • read:只读查询,如getlist
  • write:创建、更新、绑定类操作,如createupdateattachdetach
  • destructive:删除类操作(README 中标注[DESTRUCTIVE]),如delete,如actions.deleteassistants.deletecontacts.deleteknowledgeBases.deletememoryStores.deletephoneBooks.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):

NameTypeRequiredDescription
typeoutbound \| inbound \| widgetYes助手类型:外呼 / 呼入 / 网页挂件
namestringYes助手名称
agentobjectYesAgent 配置(见下)
descriptionstringNo描述
phone_numberstringNo绑定号码
external_webhook_urlstringNo外部 Webhook 回调地址
is_recordingbooleanNo是否录音

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):

NameTypeRequiredDescription
model_idstringYes目标助手 ID
phonestringYes被叫号码
namestringYes联系人姓名
from_phone_numberstringNo主叫号码
custom_variablesobjectNo自定义变量,{ key, value }[]或对象
lead_emailstringNo线索邮箱
lead_timezonestringNo线索时区
promptstringNo本次通话覆盖提示词
greetingstringNo本次通话覆盖问候语

Output:{ status?, response?: { answer?, call_id? }, eta? },其中call_id用于后续calls.get查询通话详情与转写。

5.4 actions.attach / detach:为 Agent 绑定动作

attach的输入比较特殊,三种方式可任选其一(types.ts 的ActionsAttachInputSchema):

NameTypeRequiredDescription
model_idstringYes目标 Agent ID
actionsstring[]No动作名称列表
action_idsstring[]No动作 ID 列表
itemsobject[]No结构化动作项

底层实现(actions.ts 的attach)做了归一化:若提供了items则发送items,否则发送actions ?? action_ids,最终 POST 到/v2/actions/attachdetach类似,但只接受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_EVAL

5.6 分页与查询参数

list类操作普遍支持limit/offset分页。以actions.list为例(actions.ts 的list),实现会把limit/offset组装为 GET query 参数;voices.list额外支持workspace(必填)、searchprovider(枚举elevenlabs | deepgram | synthflow)过滤。

全部 37 个端点的输入/输出字段、必填性、嵌套类型与返回值,可查阅 docs/plugins/synthflowai/api.mdx(按 Actions / Assistants / Calls / Contacts 等分组逐项列出)。

六、错误处理与重试策略

6.1 统一的错误类型

所有 Synthflow AI 调用都经由 client.ts 的makeSynthflowAiRequest封装,抛出的错误统一为:

  • SynthflowAiAPIError:携带codestatusbody,覆盖 HTTP 错误与网络错误;
  • SynthflowAiRateLimitError:HTTP 429 专用,携带retryAfterMs(来自响应头的重试时间)。

错误消息提取遵循"detail.description → detail 字符串 → message → error"的优先级,尽量还原服务端返回的可读信息。

6.2 内置重试策略

error-handlers.ts 内置了三类错误处理器:

类型匹配条件行为
RATE_LIMIT_ERROR429 状态码,或消息包含too many requests/rate_limited/rate limitmaxRetries: 5,并按retryAfterMs回退
AUTH_ERROR401 状态码,或消息包含unauthorized/invalid_auth/invalid api key/401maxRetries: 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):

assistantscallscontactsknowledgeBasesmemoryStoresphoneBooksactionsvoices

各实体的字段模型见 schema/database.ts,例如SynthflowAiCallcall_id/model_id/call_status/lead_phone_number/durationSynthflowAiVoicevoice_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为所有实体共有的隔离字段,用于多租户数据圈定):

Actionsdb.actions.search):entity_idaction_ididname—— 字符串字段均支持equals, contains, startsWith, endsWith, in

Assistantsdb.assistants.search):entity_idmodel_idnametypedescriptionphone_number—— 同上字符串操作符。

Callsdb.calls.search):entity_idcall_idmodel_idcall_statuslead_phone_number(字符串操作符);duration(number,支持equals, gt, gte, lt, lte, in)。

Contactsdb.contacts.search):entity_ididnamephone_numberemailcompany

Knowledge Basesdb.knowledgeBases.search):entity_ididknowledge_base_idnamerag_use_condition

Memory Storesdb.memoryStores.search):entity_ididtitledescription

Phone Booksdb.phoneBooks.search):entity_idphone_book_idnameworkspace_id(字符串);entry_count(number,支持比较操作符)。

Voicesdb.voices.search):entity_idvoice_idnameworkspace

所有.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/updateexternal_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),仅供参考

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

SpringCloud与Dubbo整合实战:微服务架构优化方案

1. 为什么需要整合SpringCloud与Dubbo在微服务架构选型中&#xff0c;SpringCloud和Dubbo都是主流方案&#xff0c;但各自有不同的设计哲学。SpringCloud基于HTTP RESTful风格&#xff0c;强调标准化和开放性&#xff1b;Dubbo则采用RPC通信&#xff0c;追求高性能和低延迟。实…

作者头像 李华
网站建设 2026/9/16 20:02:15

dhcpd.service 启动失败?journalctl 日志定位与配置修复全指南

凌晨两点&#xff0c;实验室的同事给我发来一条截图&#xff0c;上面就一行字&#xff1a;Job for dhcpd.service failed because the control process exited with error code.他说自己照着教程配了半天 DHCP 服务器&#xff0c;systemctl start dhcpd一敲下去就弹出这个&…

作者头像 李华
网站建设 2026/9/16 20:02:07

Amazon S3工具链实战:选型、配置、同步与成本优化

1. 别急着敲命令&#xff1a;先把 S3 和 S3 工具的关系理顺1.1 对象存储的思维模型&#xff0c;用储物柜来类比最省事很多人第一次接触对象存储会水土不服&#xff0c;因为它跟"服务器上挂载一块盘"完全不是一回事。你可以把 Amazon S3 想象成一个超大型的自助储物柜…

作者头像 李华
网站建设 2026/9/16 20:00:58

WinForm项目目录结构设计:从单项目到多项目的分层实践

很多C#新手拿到WinForm项目&#xff0c;第一反应就是把所有窗体堆在根目录下&#xff0c;公共方法全部塞进MainForm&#xff0c;等代码量上去了才意识到项目已经变成一盘散沙。这篇东西就是想跟你聊聊WinForm项目的目录结构到底应该怎么设计&#xff0c;从最简单的单项目结构讲…

作者头像 李华