ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Corsair Breathe HR 插件接入指南:用 API Key 将员工 HR 数据接入你的 Agent

2026/9/16 14:51:48 拓冰建站 浏览量
Corsair Breathe HR 插件接入指南:用 API Key 将员工 HR 数据接入你的 Agent Corsair Breathe HR 插件接入指南用 API Key 将员工 HR 数据接入你的 Agent【免费下载链接】corsairConnect your users to their apps项目地址: https://gitcode.com/GitHub_Trending/corsa/corsair本篇技术指南围绕 Corsair 仓库中的corsair-dev/breathehr插件展开介绍如何在 Corsair 生态中安装、认证并调用 Breathe HR英国主流 HR 管理系统的 50 个 REST 端点覆盖员工、请假、缺勤、病假、报销、薪资、培训等 HR 域操作。读完本文你将掌握该插件的安装方式、API Key 认证与沙箱路由机制、端点全貌与风险分级、Zod 校验模型、错误重试策略以及如何用仓库自带的单元测试验证请求路径的正确性。插件定位Corsair 与 Breathe HR 之间的桥梁corsair-dev/breathehr是 Corsair 官方维护的 Breathe HR 连接插件plugin。它的职责不是重复实现一套 HR 系统而是把 Breathe HR 公开的 REST API 封装成 Corsair 插件约定下的“端点endpoint”让接入方可以通过统一的插件接口读取员工数据、审批请假、创建报销单等而无需关心底层 HTTP 细节。从包结构看插件核心由四部分组成见 packages/breathehrendpoints/handlers.ts每个端点的实际 HTTP 调用逻辑endpoints/types.ts所有端点的 Zod 输入/输出校验 Schemaschema/database.tsBreathe HR 核心实体的 Zod 数据模型client.ts底层请求封装、错误类型与沙箱地址路由。安装一行命令接入在 packages/breathehr/README.md 中给出的安装方式为pnpm add corsair-dev/breathehr结合 packages/breathehr/package.json 可以看到更完整的依赖约定该包以corsair 0.1.0和zod ^4.1.13作为 peerDependencies当前版本为0.1.1这意味着你的项目必须已安装 Corsair 运行时与 Zod 4 才能正常使用。包采用 ESM 输出type: module并声明了dist/index.js与dist/index.d.ts可在tsconfig与tsup构建链下直接消费。认证方式API KeyREADME 的 Auth 一节明确指出Auth: API key. Corsair prompts your tenant for credentials on first use.这是唯一的认证方式也是该插件区别于 OAuth 类插件如 GitHub、Google Calendar 插件的关键特征接入方只需提供 Breathe HR 的 API Key无需走完整的 OAuth 授权流程。租户凭据的首次提示与 Key 解析“Corsair prompts your tenant for credentials on first use”对应 index.ts 中的keyBuilder实现keyBuilder: async (ctx: BreatheHrKeyBuilderContext, source) { if (source endpoint options.key) { return options.key; } if (source endpoint ctx.authType api_key) { const res await ctx.keys.get_api_key(); if (!res) { throw new AuthMissingError(breathehr, api_key); } return res; } throw new AuthMissingError(breathehr, api_key); },从源码可以推断出 Key 的解析优先级首先检查插件初始化时传入的静态options.key未传入时再向 Corsair 的租户凭据存储ctx.keys.get_api_key()查询两者都拿不到 Key 时抛出AuthMissingError。因此在实际落地时你可以选择“运行时注入”或“租户侧配置”两种方式之一。插件工厂与可选参数插件工厂函数breathehr()接收的BreatheHrPluginOptions完整定义为export type BreatheHrPluginOptions { authType?: PickAuthapi_key; key?: string; hooks?: InternalBreatheHrPlugin[hooks]; errorHandlers?: CorsairErrorHandler; permissions?: PluginPermissionsConfigtypeof breathehrEndpointsNested; };即除了认证相关的authType默认api_key与key外还支持通过hooks挂接插件生命周期钩子、通过errorHandlers覆盖默认错误处理、通过permissions按端点配置租户权限。生产环境与沙箱环境的自动路由client.ts 中定义了双环境地址export const BREATHE_HR_API_BASE https://api.breathehr.com/v1; export const BREATHE_HR_SANDBOX_API_BASE https://api.sandbox.breathehr.info/v1; export function breatheHrBaseUrl(apiKey: string): string { return apiKey.startsWith(sandbox-) ? BREATHE_HR_SANDBOX_API_BASE : BREATHE_HR_API_BASE; }这是一个非常实用的设计以sandbox-开头的 API Key 会被自动路由到 Breathe HR 沙箱环境api.sandbox.breathehr.info其余 Key 走生产环境api.breathehr.com。开发联调与生产上线可以共用同一套插件代码无需手工切换 base URL。请求头方面makeBreatheHrRequest统一携带X-API-KEY头与Accept: application/json、Content-Type: application/jsonGET 请求把参数放入 query并通过compactQuery过滤掉undefined值POST/PUT/PATCH 请求把参数放入 JSON body。端点全景50 个 HR 操作README 以表格形式完整列出了插件的全部端点这是本插件的核心资产。下表按 README 原文完整收录操作名、Operation ID、风险级别与描述均保持一致并按领域分为四组便于检索。员工与账号域OperationOperation IDRiskDescriptionaccount.getbreathehr.api.account.getreadRetrieve Breathe HR account detailsemployees.listbreathehr.api.employees.listreadList employees with paginationemployees.getbreathehr.api.employees.getreadGet an employee by IDemployees.createbreathehr.api.employees.createwriteCreate an employeeemployees.createChangeRequestbreathehr.api.employees.createChangeRequestwriteCreate an employee change requestemployees.createExpensebreathehr.api.employees.createExpensewriteCreate an employee expenseemployees.createExpenseClaimbreathehr.api.employees.createExpenseClaimwriteCreate an employee expense claimemployees.createSicknessbreathehr.api.employees.createSicknesswriteCreate an employee sickness recordemployees.listAbsencesbreathehr.api.employees.listAbsencesreadList absences for an employeeemployees.listBenefitsbreathehr.api.employees.listBenefitsreadList benefits for an employeeemployees.listBonusesbreathehr.api.employees.listBonusesreadList bonuses for an employeeemployees.listChangeRequestsbreathehr.api.employees.listChangeRequestsreadList change requests for an employeeemployees.listHolidayYearsbreathehr.api.employees.listHolidayYearsreadList holiday years for an employeeemployees.listLeaveRequestsbreathehr.api.employees.listLeaveRequestsreadList leave requests for an employeeemployees.listSalariesbreathehr.api.employees.listSalariesreadList salaries for an employeeemployeeJobs.listbreathehr.api.employeeJobs.listreadList employee jobs请假、缺勤与病假域OperationOperation IDRiskDescriptionabsences.listbreathehr.api.absences.listreadList absencesleaveRequests.approvebreathehr.api.leaveRequests.approvewriteApprove a leave requestleaveRequests.getbreathehr.api.leaveRequests.getreadGet a leave request by IDleaveRequests.getCancellingbreathehr.api.leaveRequests.getCancellingreadGet the leave request being cancelledleaveRequests.listbreathehr.api.leaveRequests.listreadList leave requestsleaveRequests.rejectbreathehr.api.leaveRequests.rejectwriteReject a leave requestholidayAllowances.listbreathehr.api.holidayAllowances.listreadList holiday allowancesotherLeaveReasons.listbreathehr.api.otherLeaveReasons.listreadList other leave reasonssicknesses.listbreathehr.api.sicknesses.listreadList sickness recordssicknesses.updatebreathehr.api.sicknesses.updatewriteUpdate a sickness record报销与培训域OperationOperation IDRiskDescriptionemployeeExpenseClaims.listbreathehr.api.employeeExpenseClaims.listreadList employee expense claimsemployeeExpenseClaims.updatebreathehr.api.employeeExpenseClaims.updatewriteApprove or reject an expense claimemployeeExpenses.deletebreathehr.api.employeeExpenses.deletedestructiveDelete an employee expense [DESTRUCTIVE]employeeExpenses.getbreathehr.api.employeeExpenses.getreadGet an employee expense by IDemployeeExpenses.listbreathehr.api.employeeExpenses.listreadList employee expensesemployeeTrainingCourses.deletebreathehr.api.employeeTrainingCourses.deletedestructiveDelete an employee training course [DESTRUCTIVE]employeeTrainingCourses.listbreathehr.api.employeeTrainingCourses.listreadList employee training coursesemployeeTrainingCourses.updatebreathehr.api.employeeTrainingCourses.updatewriteUpdate an employee training course组织结构与其他域OperationOperation IDRiskDescriptionbenefits.listbreathehr.api.benefits.listreadList employee benefitsbonuses.listbreathehr.api.bonuses.listreadList employee bonuseschangeRequests.listbreathehr.api.changeRequests.listreadList change requestscompanyDocuments.listbreathehr.api.companyDocuments.listreadList company documentscompanyProjects.listbreathehr.api.companyProjects.listreadList company projectscompanyTrainingTypes.listbreathehr.api.companyTrainingTypes.listreadList company training typesdepartments.listbreathehr.api.departments.listreadList departmentsdepartments.listAbsencesbreathehr.api.departments.listAbsencesreadList absences for a departmentdepartments.listBenefitsbreathehr.api.departments.listBenefitsreadList benefits for a departmentdepartments.listBonusesbreathehr.api.departments.listBonusesreadList bonuses for a departmentdepartments.listLeaveRequestsbreathehr.api.departments.listLeaveRequestsreadList leave requests for a departmentdepartments.listSalariesbreathehr.api.departments.listSalariesreadList salaries for a departmentdivisions.listbreathehr.api.divisions.listreadList divisionslocations.listbreathehr.api.locations.listreadList locationssalaries.listbreathehr.api.salaries.listreadList salariesworkingPatterns.listbreathehr.api.workingPatterns.listreadList working patterns端点的 REST 映射从 Operation ID 到底层 HTTP每一个 Operation ID 都对应 endpoints/handlers.ts 中的一个处理器而处理器内部通过makeBreatheHrRequest组装出真实的 Breathe HR REST 请求。典型的映射关系包括account.get→GET /accountemployees.list→GET /employees分页参数走 queryemployees.get→GET /employees/{id}employees.create→POST /employeesbody 包裹为{ employee: {...} }leaveRequests.approve→POST /leave_requests/{id}/approveleaveRequests.reject→POST /leave_requests/{id}/rejectbody 携带rejection_reasonemployeeExpenses.delete→DELETE /employee_expenses/{id}。值得注意的是employeesCreate的一个业务细节创建员工时若只提供了company_join_date而未提供join_date处理器会自动用前者回填join_dateinput.join_date ?? input.company_join_date保证创建请求总能带上入职日期字段。端点树的组织方式在 index.ts 中全部端点被组织成一个嵌套的breathehrEndpointsNested对象如employees下挂list/get/create/listAbsences/...Corsair 会基于此结构自动生成绑定后的端点集合BreatheHrBoundEndpoints。同时breathehrEndpointSchemas以“employees.list”这样的点号字符串为键把每个端点的输入/输出 Schema 一一对应起来供运行时做参数校验与结果解析。风险分级read / write / destructiveREADME 端点表中的 Risk 列是 Corsair 插件的通用约定用于把端点划分为三个风险等级。结合 index.ts 中breathehrEndpointMeta的定义可以统计出本插件的分布read38 个全部查询类端点如employees.list、absences.list、salaries.list。只读、无副作用适合授权给 Agent 自由调用write10 个会修改数据的端点如employees.create、leaveRequests.approve、leaveRequests.reject、employeeExpenseClaims.update批准/驳回报销、sicknesses.update等destructive2 个删除类端点即employeeExpenses.delete与employeeTrainingCourses.deleteREADME 表格中特意用[DESTRUCTIVE]标注提醒调用方这是不可恢复的操作。这组分级直接服务于插件选项中的permissions?: PluginPermissionsConfig接入方可以在初始化插件时按端点收紧租户权限例如默认只放行read级端点把destructive端点留给管理员场景。数据模型与参数校验实体模型宽松的 Zod Schemaschema/database.ts 用 Zod 定义了 7 个核心实体并在 schema/index.ts 中汇总为BreatheHrSchema版本1.0.0BreatheHrAccount账号id、name、domain、uuid、using_rta、health_and_safety_enabledBreatheHrEmployee员工id、first_name、last_name、email、job_title、status、join_date、department、division、location、working_pattern、holiday_allowance、line_manager 等BreatheHrLeaveRequest请假请求id、start_date、end_date、type、status、notesBreatheHrAbsence缺勤记录id、start_date、end_date、typeBreatheHrDepartment部门id、nameBreatheHrSickness病假记录id、start_date、end_date、status、reasonBreatheHrEmployeeExpense员工报销id、amount、description、expense_date。这些实体 Schema 有一个共同特征字段全部optional且对象整体.loose()。也就是说插件对 Breathe HR 返回的字段持“宽容”策略——未知字段不会被丢弃缺失字段也不会导致校验失败。这对第三方 API 集成是合理选择Breathe HR 各租户返回的字段可能略有差异宽松 Schema 能避免因字段缺失导致整个响应被拒。此外员工实体中的department、division、location、line_manager等嵌套引用统一使用Ref{ id?, name? }结构与 Breathe HR “引用式返回”的 API 风格保持一致。输入校验分页与关键约束endpoints/types.ts 为每个端点定义了独立的输入/输出 Schema其中复用率最高的基础结构是PageQueryconst PageQuery z.object({ page: z.number().int().positive().optional(), per_page: z.number().int().positive().max(100).optional(), });即分页参数page必须为正整数per_page上限为 100。employees.list还额外支持filterhr/line_manager/either与rotacloud参数absences.list支持typeHoliday/OtherLeave、起止日期、employee_id、department_id、exclude_cancelled_absences等过滤条件employeeExpenseClaims.list支持state_filtersubmitted/approved/completed。创建类端点的校验更严格例如employees.create要求first_name、last_name非空、email合法并且通过.refine()强制join_date与company_join_date至少提供其一leaveRequests.reject要求rejection_reason非空employees.createExpense则要求employee_id、amount、description、expense_date、payable_to_employee、company_expense_type_id齐备。错误处理与重试策略插件在 error-handlers.ts 中内置了一套针对 Breathe HR 的CorsairErrorHandler按错误类别给出不同的重试建议错误类别匹配条件重试策略RATE_LIMIT_ERRORBreatheHrRateLimitError、HTTP 429或消息含 “rate limit” / “too many requests”maxRetries: 5并透传retryAfter作为headersRetryAfterMsAUTH_ERRORHTTP 401或消息含 “unauthorized” / “invalid api key” / “401”maxRetries: 0不重试VALIDATION_ERRORHTTP 400 / 422或消息含 “unprocessable” / “422”maxRetries: 0不重试DEFAULT兜底匹配maxRetries: 0底层错误类型定义在 client.tsBreatheHrAPIError携带 code、status、body、retryAfter与BreatheHrRateLimitError固定 429。makeBreatheHrRequest会把corsair/http抛出的ApiError归一化为这两类错误并尝试从响应 body 的error.message/error.type/message字段提取可读的错误信息。另外有一个容易忽略的细节DELETE 请求成功后若响应体为空客户端会返回{ deleted: true }让调用方有一个确定的成功信号。如果在初始化插件时传入自定义errorHandlers它会与内置错误处理器合并{ ...errorHandlers, ...options.errorHandlers }允许按需覆盖特定错误类别的行为。测试验证请求路径与方法的可验证性仓库为该插件提供了两层测试api.test.ts通过 mockcorsair/http的request函数逐条断言每个端点的 URL 与 HTTP 方法是否正确例如accountGet应请求/account、employeesCreate应POST /employees、leaveRequestsApprove应POST /leave_requests/1/approve。这套测试直接印证了上文的 REST 映射关系是验证端点契约最直接的依据integration.test.ts通过test:live脚本jest --testPathIgnorePatterns/node_modules/ --testPathPatternintegration运行的真实环境联调测试需要可用的 Breathe HR 凭据。如果你要二次开发或扩展该插件可以先运行pnpm test跑通单元测试再以沙箱 API Keysandbox-前缀执行集成测试。Webhooks当前不支持README 明确说明Webhooks: No webhooks.这一点在源码中同样得到印证index.ts 中breathehrWebhooksNested {} as const为空对象pluginWebhookMatcher: () false恒为 false。因此本插件目前只支持“Agent 主动拉取”Breathe HR 数据的模式如果你的场景需要被动接收 Breathe HR 事件推送需要通过轮询如定时调用leaveRequests.list、absences.list来模拟实时性。相关资源插件说明文档packages/breathehr/README.md插件完整文档含类型与示例位于仓库 docs/plugins/breathehr插件通用概念可参考 docs/guides/plugins.mdx 与 docs/guides/create-your-own-plugin.mdx插件声明元数据packages/breathehr/plugin-docs.yaml本插件以 Apache-2.0 协议开源可以放心在商业项目中集成使用。接入时只需记住三点用pnpm add corsair-dev/breathehr安装、以 API Key沙箱 Key 带sandbox-前缀认证、并按 read/write/destructive 三级风险为租户配置端点权限。【免费下载链接】corsairConnect your users to their apps项目地址: https://gitcode.com/GitHub_Trending/corsa/corsair创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考