前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9915
  • Meta 推出8160亿参数开放权重多模态模型
  • 两台 M5 Ultra Mac 可运行 Muse 开放模型
  • SageMaker 支持部署 Muse Spark Open
  • 谷歌 ADK 配方库贯通 Agent 开发部署
  • 为多轮 Agent 建立持续评估流水线
  • ctxtrim 压缩日志,节省编程上下文
  • 技能触发不准,先改好 description
  • AI 生成页面上线前,补验 GA4 事件链路
  • 让客服机器人把处理结果反馈到检索排序
  • Muse Spark Open 发布,主打编程与 Agent
  • FLUX 3 Klein 开放权重,8GB 显存可运行
  • Gemini 4 Argon 整合机器人控制与仿真
  • 英伟达开放多模态模型,面向企业智能体
  • Vercel 扩展后端与 Agent 部署能力
  • 英伟达发布面向智能体的多模态开放模型
  • 英伟达扩充智能体模型,覆盖云端与本地
  • 日合并超三万次,Anthropic 重构版本控制
  • CLiF 将智能体运行记录转为训练评测资产
  • GitHub 代码扫描智能体修复正式可用
  • Webhook 驱动 Agent 的可靠性要点
  • 用 TypeScript 为 Agent 补齐应用连接器
  • 177 项科研技能补齐智能体领域知识
  • 发现 AI 擅自决策:简单审查胜过复杂流水线
  • WhatsApp 智能体上线后的工程难题
  • Netflix 为编程智能体接入 IDE 代码分析引擎
  • PentAGI 用多智能体执行渗透测试
  • MCP 排错日志里的凭据泄露隐患
  • Jev新版加入图像输入与26.2万上下文
  • 微软用知识编译降低智能体延迟与耗量
  • Grok语音模型升级,接口与价格保持不变
  • 把 ClickUp 项目记录变成 Agent 可查询记忆
  • Matrix-Game 4.0 开源单卡实时生成游戏
  • Agent 接入外部服务前先检查失败恢复能力
  • 多模型网关踩坑:推理预算吃光了回答
  • Step 5 Preview 开放权重,可部署百万上下文
  • AI 工具写操作防重:执行前先抢占
  • 给 n8n 的模型输出加一道契约检查
  • 自托管 AI 工具漏洞公告可能漏过扫描
  • 本地运行 Gemma 4:推测解码与草稿模型
  • AI 代码上线前先排查这些安全漏洞
  • Copilot更新HydraFusion并新增Max
  • MCP工具数量实测:准确率之外更要看成本
  • Apigee 支持在自有集群运行 MCP 工具
  • 编程 Agent 源码研究:架构比功能清单耐用
  • 把 GPU 内核调优变成夜间并行搜索
  • AI 生成的 Supabase 权限代码可能允许提权
  • Agent 成本控制要先预留并发调用预算
  • 全 AI 编码项目如何靠质量关卡持续交付
  • AI反编译加速老游戏移植,也带来风险
  • 用 AgentCore 构建可适应新格式的文档处理
  • 用 Issue 标签驱动 AI 分析与提 PR
  • 已加载 51 / 9915
8.0
热点
AI SCORE
技术实践2026-10-15 20:34

用 TypeScript 为 Agent 补齐应用连接器

dev.to · AI#TypeScript#Agent#工具集成
Editor brief · 编辑速览

教程介绍借助开源集成框架搭建插件,为接口添加类型约束、配置认证并避免硬编码密钥。还讨论一次性调用与需要服务多租户、长期维护的集成应如何选择实现规模。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

当你的 Agent 需要连接一个还没人适配的应用

迟早有一天,Agent 会需要访问某个应用,而你的技术栈里还没有任何组件为它提供 connector。它可能是一款小众 CRM、一个内部工具,也可能是某个较新的 API,集成平台还没来得及支持。到了这一步,基本只有两条路:手写一个专用的 TypeScript 客户端,或者利用开源集成框架现成的插件脚手架,采用与其他插件一致的结构。

本文会完整走一遍第二条路:搭建插件脚手架,为每个 endpoint 定义类型,避免 Agent 错误调用;接入认证,全程不硬编码任何密钥;最后把成果贡献回社区,让下一个需要相同 API 的人不必重复劳动。本文不会从头讲解 SDK 设计理论,这方面已经有整本书可以读。这里关注的是实际落地:一个生产环境可用的集成,需要补上哪些临时脚本通常会跳过的环节,以及为什么要补。

自己构建集成的真正成本

搭建脚手架之前,值得先做一个简单判断:这个集成只是产品偶尔需要的一次性调用,还是需要提供类型约束、接入认证,并持续服务于产品的所有租户?答案决定了你应该提前投入多少结构设计。

任何自定义 API 集成,前 80% 通常都比较容易:阅读服务提供方的文档,映射几个 endpoint,再把调用跑通。真正耗费工程时间的是剩下的 20%:在 OAuth token 过期前完成轮换,为每个收到的事件验证 webhook 签名,在不悄悄丢弃请求的前提下遵守限流要求,以及隔离多租户凭据,确保一个租户的 token 绝不会混入另一个租户的调用。这些问题在最初的概念验证里都不会出现,但生产环境出问题的那一周,它们会一并找上门。

这才是集成方案中自建还是购买的真正取舍。关键不在于你能不能写出 HTTP 调用——当然能——而在于你是否愿意长期负责那剩下的 20%。封闭平台可以替你承担维护,但下一次需要它尚未支持的 API 时,你也只能等别人的路线图排期。

开源集成改变了这笔账,但并没有让工作凭空消失。你不必受制于供应商的进度:可以先查看现有插件目录,如果没有所需应用,就按其他集成采用的相同结构,自己生成脚手架。你也不必从空文件开始:下面介绍的脚手架、类型约定和认证模式,就是这套结构在实践中的样子。

用一条命令生成插件脚手架

手写集成通常从一个文件、几个 fetch 调用开始。起初这样没问题,但等到要添加第二个 endpoint、第一个 webhook,或者第二个租户首次需要独立凭据时,你就会开始重新搭建一套 TypeScript SDK 结构,而几乎所有集成最终都会走向同样的布局:

packages/<plugin-name>/
├── index.ts            # entry point, auth setup
├── client.ts            # HTTP client with auth headers
├── error-handlers.ts    # error classes and status mappers
├── endpoints/            # typed API operations by resource
├── webhooks/             # webhook signature verification and event routing
└── schema/               # Zod schemas for anything cached locally

生成器只需一条命令,就能创建相同的布局,无须手动搭建:

pnpm run generate:plugin MyService

这条命令做的不只是创建空文件夹。它还会把插件注册到框架的核心常量中,让你可以立即导入;接好 API key 或 OAuth 2 流程的基础认证模式;配置好 bundler 和包设置,让 workspace 将它识别为真正的包,而不是一堆松散文件。

无论你封装的是哪个 API,这套结构本身都在发挥作用。按这种方式构建的插件布局一致,因此开发者只要参与过一个集成,就知道下一个集成的 webhook handler 或 Zod schema 在哪里。这对 AI Agent 工具也很重要:编码 Agent 可以检查并正确补全一套可预测的脚手架,因为它已经知道 client.ts 或 endpoints/ 应该包含什么,无须从头摸索某个专用文件的约定。Corsair 的插件生成器采用的正是这套布局,即使你最终决定在自己的技术栈里手动搭建脚手架,也值得参考。

为每个 endpoint 定义类型,避免 Agent 错误调用

Agent 调用集成,本质上仍然是在调用函数。这意味着,正确调用与格式错误的调用之间,唯一的防线就是函数签名。与面向人类开发者时相比,API 客户端的设计决策对 Agent 更重要,因为 Agent 不会凭直觉察觉某个字段悄悄缺失了。按业务领域划分命名空间,并提供类型安全的 endpoint,可以同时解决可发现性和类型约束问题:

const sdk = new MyServiceClient({ apiKey });

await sdk.customers.list({ limit: 20 });
await sdk.invoices.create({ customerId, amount });

输入 sdk. 时,IDE 就会列出它所知道的全部资源。每个方法都有自己的请求和响应契约,而不是共用一个泛化的 options 对象。请求类型(CreateInvoiceRequest、ListCustomersRequest)和泛型响应包装(APIResponse<T>、PaginatedResponse<T>)可以让返回数据的结构保持可预测。如果服务提供方已经发布了 OpenAPI 规范,就可以使用 openapi-typescript 或 Fern 之类的工具,通过 OpenAPI 代码生成直接产出这些接口,无须逐个手写。动手写代码之前,值得先做这一步。

不过,静态类型会在运行时消失,而第三方 API 可能在毫无预警的情况下改变响应结构。这正是在数据边界使用 Zod 校验,而不是只相信编译器的理由:schema 可以在格式错误或结构发生变化的数据进入 Agent 推理环节之前将其拦截,还能直接推导出对应的 TypeScript 类型,让接口定义与校验器始终保持一致。代价也确实存在:Zod 会增加少量运行时开销,写得过于严格的 schema 还可能拒绝服务提供方后来新增的无害字段。因此,对于你没有明确依赖的字段,schema 通常最好保持宽松。

错误与重试也应当像响应一样认真处理。集中式请求执行器可以把 HTTP 状态码映射为标准化的 SDKError,并携带 RATE_LIMIT_ERROR 或 AUTHENTICATION_ERROR 这样的明确错误码,让 Agent 能据此选择处理分支。同一个执行器也应当负责错误处理和重试逻辑:超时、503、429 这类暂时性失败采用退避策略重试,而 401 或 400 则立即向上抛出,避免盲目重试。

接入认证,不硬编码任何密钥

密钥应该放在环境变量中,在启动时注入,绝不能直接写进源文件。客户端构造函数是落实这一要求的合适位置:创建客户端时就检查必需的密钥是否齐全,在发出任何网络请求之前明确报错,而不是等到三个请求之后才出现令人困惑的失败。

OAuth token 刷新是大多数自定义集成悄悄出问题的地方。这里需要同时做好三件事。

第一,提前检查有效期。收到 token 时保存它的过期时间戳,当当前时间距离过期只剩几分钟时就主动刷新,而不是等请求失败再处理。

第二,收到 401 后刷新并重试。即使已经提前检查,请求仍可能返回未授权,比如时钟出现偏差,或者 token 被提前撤销。这时应刷新 token,并将原请求重试一次。

第三,用 single-flight 锁保护刷新操作。一旦存在并发,这一点就很重要:如果多个请求同时发现 token 已过期,应该只有一个请求真正调用 token endpoint。其他请求等待同一个进行中的 promise。因为对于会轮换 refresh token 的服务提供方,同时发出多个刷新请求,可能导致其中一些请求被拒绝,甚至直接撤销整个会话。

if (Date.now() >= expiresAt - BUFFER_MS) {
  await (refreshPromise ??= refreshToken());
}

在真正的多租户产品中,这些细节都不应该暴露给 Agent。每次调用发生时,系统在内部解析对应租户的凭据,并将其作用域限定在该租户内。Corsair 的托管和自托管方案也采用这种模式,让 Agent 始终只能看到方法名和结果,看不到底层 token。

把成果贡献回去,不再等待路线图排期

这里向开源项目贡献代码的流程,与其他开源项目一样:开始之前,先认领工作。大多数开源集成框架都会维护任务看板或公开 issue 列表,就是为了避免两位贡献者各花一个周末,独立开发出同一个 Notion 插件。通常,创建一个 issue,附上目标 API 的文档、计划覆盖的 endpoint,以及所需的认证类型,就足以把这项工作认领到自己名下。

向成熟框架提交 pull request 时,在有人审查具体逻辑之前,必须先通过几项明确但并不起眼的门槛:类型检查、lint 检查,以及确认目录符合约定的插件校验脚本。这些检查无关你的想法好不好,而是为了确保下一个打开插件的人,能在预期的位置找到预期的内容。

真正进入代码审查后,草率的实现就会暴露出来。审查者会拒绝那些把简单的 header 映射技巧包装成 OAuth 支持的认证实现,也会拒绝大范围使用 as any、悄悄把有类型的 endpoint 重新变成无类型调用的代码。这两种做法都违背了脚手架的初衷。

跨过这些门槛,你能获得封闭平台无法提供的东西:你无须提交功能请求然后等待,而是可以亲手交付集成,下一个需要相同 API 的开发者则能免费使用。Corsair 正是围绕这种模式构建的:每个插件交付时都有类型定义,并经过预先验证;自托管免费;凭据始终保留在你自己的数据库中。如果现有插件尚未覆盖你需要的集成,你可以生成脚手架并贡献代码,无须等待供应商的路线图排期。可以查看当前的插件目录,并到 corsair.dev 亲自试试。

常见问题

只调用一次 API,值得构建自定义集成吗?还是直接在业务代码里写就行?

如果确实是一次性调用,而且认证只需要一个静态 API key,那么一个带类型的函数就够了。当集成需要完善的认证、支持多租户,或者需要在首次发布后持续维护时,本文介绍的脚手架和结构才会体现价值。

相比只编写 TypeScript interface,Zod 的实际优势是什么?

TypeScript 类型会在运行时消失,无法防范结构不符合预期的数据。Zod 在响应到达时进行校验,并从同一个 schema 推导出 TypeScript 类型,因此服务提供方 API 悄悄发生的变化会被及时发现,不会继续向流水线下游传播并破坏数据。

如何防止同时发出多个 refresh token 请求?

用一个共享的 promise 包装刷新调用。第一个发现 token 已过期的请求启动刷新,其他所有并发请求都等待同一个 promise,而不再重复调用 token endpoint。这样也能避免触发某些服务提供方的机制:它们会轮换 refresh token,并在重复使用时使其失效。

开源维护者通常会拒绝新插件 PR 中的哪些问题?

最常见的两类问题是:认证实现只是走捷径映射 header,没有真正处理 OAuth;以及使用 as any 之类宽泛的类型断言,绕过框架其他部分所依赖的类型约束。

贡献插件必须支持 webhook 吗?只读功能够不够?

如果服务提供方的 API 没有值得响应的事件,或者你的使用场景确实不需要这些事件,那么只读功能就够了。如果服务提供方支持 webhook,而你的集成没有实现,审查者通常会要求在合并前补上签名验证和事件路由。

如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
Webhook 驱动 Agent 的可靠性要点
下一篇
177 项科研技能补齐智能体领域知识