building-nango-functions
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuild Nango Functions
构建Nango Functions
Build Nango action and sync implementations without choosing the execution workflow.
This skill covers the function design contract: schemas, provider calls, action outputs, sync models, checkpoints, deletion handling, metadata, retries, and runtime constraints. It intentionally does not cover local CLI validation/deploy or remote API compile/dryrun/deploy.
If the task becomes clearly local/CLI-based, use instead. If it becomes clearly remote/API-based, use instead.
building-nango-functions-locallybuilding-nango-functions-remotely构建Nango动作和同步实现,无需选择执行工作流。
本技能涵盖函数设计契约:模式(schemas)、提供商调用、动作输出、同步模型、检查点(checkpoints)、删除处理、元数据、重试和运行时约束。它特意不涉及本地CLI验证/部署或远程API编译/试运行/部署的内容。
如果任务明确为本地/CLI相关,请改用。如果任务明确为远程/API相关,请改用。
building-nango-functions-locallybuilding-nango-functions-remotelyImplementation Scope
实现范围
- Build or modify a Nango function implementation
- Build an action in Nango with
createAction() - Build a sync in Nango with
createSync() - Use the active workflow skill for compile, dryrun, test, and deploy mechanics
- 构建或修改Nango函数实现
- 使用在Nango中构建动作
createAction() - 使用在Nango中构建同步
createSync() - 使用活动工作流技能处理编译、试运行、测试和部署机制
Sync Strategy Gate (required before writing code)
同步策略关卡(编写代码前必须完成)
If the task is a sync, read before writing code and state one of these paths first:
references/syncs.md- Checkpoint plan:
- change source (,
updated_at, changed-records endpoint, cursor, page token, offset/page,modified_since, or webhook)since_id - checkpoint schema
- how the checkpoint changes the provider request or resume state
- whether the request still walks the full dataset or returns changed rows only
- delete strategy
- change source (
- Full refresh blocker:
- exact provider limitation from the docs or sample payloads
- why checkpoints cannot work here
Invalid sync implementations:
- full refresh because it is simpler
- without
saveCheckpoint()getCheckpoint() - reading or saving a checkpoint without using it in request params or pagination state
- using or
syncType: 'incremental'in a new syncnango.lastSyncDate - a full refresh with no schema, or one that is never saved after each page — the run restarts from page 1 whenever it exceeds the execution window
checkpoint - calling before
trackDeletesEnd(), or without a precedingclearCheckpoint()at allclearCheckpoint() - using /
trackDeletesStart()with a changed-only checkpoint (trackDeletesEnd(),modified_after, changed-records endpoint). Those requests omit unchanged rows, soupdated_afterwill falsely delete them.trackDeletesEnd() - using /
trackDeletesStart()in an incremental sync that already has explicit deleted-record eventstrackDeletesEnd()
如果任务是同步,请在编写代码前阅读,并首先说明以下路径之一:
references/syncs.md- 检查点计划:
- 变更源(、
updated_at、变更记录端点、游标、页面令牌、偏移量/页码、modified_since或Webhook)since_id - 检查点模式
- 检查点如何更改提供商请求或恢复状态
- 请求是仍遍历完整数据集还是仅返回变更行
- 删除策略
- 变更源(
- 全量刷新限制:
- 来自文档或示例负载的确切提供商限制
- 检查点无法在此处工作的原因
无效的同步实现:
- 因为简单而选择全量刷新
- 调用但未调用
saveCheckpoint()getCheckpoint() - 读取或保存检查点但未在请求参数或分页状态中使用它
- 在新同步中使用或
syncType: 'incremental'nango.lastSyncDate - 没有模式的全量刷新,或者在每页后从不保存检查点——每当执行窗口超时,运行将从第1页重新开始
checkpoint - 在调用之前调用
clearCheckpoint(),或者根本没有先调用trackDeletesEnd()clearCheckpoint() - 将/
trackDeletesStart()与仅变更检查点(trackDeletesEnd()、modified_after、变更记录端点)一起使用。这些请求会忽略未变更的行,因此updated_after会错误地删除它们trackDeletesEnd() - 在已包含显式删除记录事件的增量同步中使用/
trackDeletesStart()trackDeletesEnd()
Choose the Path
选择路径
Action:
- One-time request, user-triggered, built with
createAction() - Read before writing code
references/actions.md
Sync:
- Scheduled or webhook-driven cache updates built with
createSync() - Complete the Sync Strategy Gate first
- Read before writing code
references/syncs.md
动作:
- 一次性请求,由用户触发,使用构建
createAction() - 编写代码前阅读
references/actions.md
同步:
- 基于计划或Webhook的缓存更新,使用构建
createSync() - 首先完成同步策略关卡
- 编写代码前阅读
references/syncs.md
Required Inputs (Ask User if Missing)
必填输入(缺失时询问用户)
Always:
- Integration ID (provider name)
- Script/function name (kebab-case)
- API reference URL or sample response
- Connection ID if the active workflow will validate or dryrun the function
Action-specific:
- Use case summary
- Input parameters
- Output fields
- Metadata JSON if required
- Test input JSON if the active workflow will validate or dryrun the action (use for no-input actions)
{}
Sync-specific:
- Model name (singular, PascalCase)
- Frequency (every hour, every 5 minutes, etc.)
- Checkpoint schema (timestamp, cursor, page token, offset/page, , or composite)
since_id - How the checkpoint changes the provider request or resume state
- Delete strategy (deleted-record endpoint/webhook, or why full refresh is required)
- If proposing a full refresh, the exact provider limitation that blocks checkpoints from the docs/sample response
- Metadata JSON if required (team_id, workspace_id)
If any required external values are missing, ask a targeted question after checking the repo and provider docs. For syncs, choose a checkpoint plus deletion strategy whenever the provider supports one. If you cannot find a viable checkpoint strategy, state exactly why before writing a full refresh.
始终需要:
- 集成ID(提供商名称)
- 脚本/函数名称(短横线命名法,kebab-case)
- API参考URL或示例响应
- 如果活动工作流将验证或试运行函数,则需要连接ID
动作特定输入:
- 使用场景摘要
- 输入参数
- 输出字段
- 如果需要,元数据JSON
- 如果活动工作流将验证或试运行动作,则需要测试输入JSON(无输入动作使用)
{}
同步特定输入:
- 模型名称(单数,大驼峰命名法,PascalCase)
- 频率(每小时一次、每5分钟一次等)
- 检查点模式(时间戳、游标、页面令牌、偏移量/页码、或复合模式)
since_id - 检查点如何更改提供商请求或恢复状态
- 删除策略(删除记录端点/Webhook,或为什么需要全量刷新)
- 如果提议全量刷新,需提供来自文档/示例负载的确切提供商限制,说明为何无法使用检查点
- 如果需要,元数据JSON(team_id、workspace_id)
如果任何必填外部值缺失,请在检查仓库和提供商文档后提出针对性问题。对于同步,只要提供商支持,就选择检查点加删除策略。如果找不到可行的检查点策略,请在编写全量刷新代码前明确说明原因。
Non-Negotiable Rules
不可协商的规则
Shared platform constraints
共享平台约束
- Nango functions use /
createAction().createSync() - You cannot add arbitrary packages. Use relative imports only when the chosen workflow supports them; built-ins include ,
zod/crypto, andnode:crypto/url.node:url - Use the Nango HTTP API for connection lookup, credentials, and proxy calls outside function code. Do not invent CLI token or connection commands.
- Add an API doc link comment above each provider call.
- Action outputs cannot exceed 2MB.
- File uploads and downloads cannot be implemented as actions (sandboxed runtime: no , no
fs, 2 MB output limit). Use a proxy script inaxioswith{integration}/proxy/instead — see@nangohq/node.references/actions.md - HTTP retries default to ; set
0deliberately. Treatretriesas the normal maximum; for sync provider calls, values above3are effectively forbidden unless docs prove they are safe and necessary. Avoid retries for non-idempotent writes unless the API supports idempotency.3 - Do not set deprecated function definition routing fields: action and sync
endpoint. Trigger actions by action name through the SDK/API, and consume sync records through the records API.endpoints
- Nango函数使用/
createAction()。createSync() - 不能添加任意包。仅当所选工作流支持时才使用相对导入;内置包包括、
zod/crypto和node:crypto/url。node:url - 使用Nango HTTP API进行连接查找、凭证获取和函数代码外的代理调用。不要自行发明CLI令牌或连接命令。
- 在每个提供商调用上方添加API文档链接注释。
- 动作输出不能超过2MB。
- 文件上传和下载不能作为动作实现(沙箱运行时:无,无
fs,2MB输出限制)。请改用axios中的代理脚本并配合{integration}/proxy/——详见@nangohq/node。references/actions.md - HTTP重试默认值为;需有意设置
0。通常最大值设为retries;对于同步提供商调用,除非文档证明安全且必要,否则禁止设置超过3的值。除非API支持幂等性,否则避免对非幂等写入进行重试。3 - 不要设置已弃用的函数定义路由字段:动作的和同步的
endpoint。通过SDK/API按动作名称触发动作,并通过记录API使用同步记录。endpoints
Sync rules
同步规则
- Sync records need a stable string .
id - New syncs should define a schema, call
checkpointfirst, andnango.getCheckpoint()after each page or batch.nango.saveCheckpoint() - A checkpoint is valid only if it changes the request or resume state (,
since,updated_after,cursor,page_token,offset,page, etc.). Saving one without using it is not incremental sync.since_id - New syncs must not use or
syncType: 'incremental'.nango.lastSyncDate - Default to +
nango.paginate(...). Avoid manualnango.batchSave(...)loops whenwhile (true),cursor, orlinkpagination fits.offset - Prefer when the provider returns deletions, tombstones, or delete webhooks.
batchDelete() - Use full refresh only if the provider cannot return changes, deletions, or resume state, or if the dataset is tiny.
- For full refresh, cite the exact provider limitation from docs or payloads. "It is easier" is not enough.
- Full refresh syncs still need a schema (page/cursor/offset) covering pagination progress, not just incremental syncs. Nango syncs run inside a time-limited execution window; a full refresh with no checkpoint restarts from page 1 on every run that exceeds the window, wasting compute re-fetching the same early pages and never reaching the rest.
checkpoint - is deprecated. For full refresh, call
deleteRecordsFromPreviousExecutions()on every execution (safe/idempotent — it will not overwrite the start of an already-open window), thentrackDeletesStart()after each page,saveCheckpoint()after the last page, andclearCheckpoint()only after thattrackDeletesEnd().clearCheckpoint() - Never combine /
trackDeletesStart()with changed-only checkpoints (trackDeletesEnd(),modified_after, changed-records endpoints, etc.). They omit unchanged rows, soupdated_afterwould delete them.trackDeletesEnd() - Checkpointed full refreshes are still full refreshes. Call only in the run that finishes and clears the checkpoint.
trackDeletesEnd() - If a sync requires metadata (e.g. ,
team_id,workspace_id), setguild_id. The sync cannot run until the caller has set the metadata, so starting it automatically would fail.autoStart: false
- 同步记录需要稳定的字符串。
id - 新同步应定义模式,首先调用
checkpoint,并在每页或每批后调用nango.getCheckpoint()。nango.saveCheckpoint() - 只有当检查点能更改请求或恢复状态(、
since、updated_after、cursor、page_token、offset、page等)时,它才是有效的。保存检查点但不使用它不属于增量同步。since_id - 新同步不得使用或
syncType: 'incremental'。nango.lastSyncDate - 默认使用+
nango.paginate(...)。当nango.batchSave(...)、cursor或link分页适用时,避免手动offset循环。while (true) - 当提供商返回删除记录、墓碑记录或删除Webhook时,优先使用。
batchDelete() - 仅当提供商无法返回变更、删除或恢复状态,或者数据集极小时,才使用全量刷新。
- 对于全量刷新,需引用来自文档或负载的确切提供商限制。“更简单”不足以成为理由。
- 全量刷新同步仍需要模式(页面/游标/偏移量)来覆盖分页进度,而不仅仅是增量同步。Nango同步在限时执行窗口内运行;没有检查点的全量刷新会在每次超时后从第1页重新开始,浪费计算资源重新获取相同的早期页面,永远无法处理剩余页面。
checkpoint - 已弃用。对于全量刷新,在每次执行时调用
deleteRecordsFromPreviousExecutions()(安全/幂等——不会覆盖已打开窗口的起始点),然后在每页后调用trackDeletesStart(),在最后一页后调用saveCheckpoint(),仅在clearCheckpoint()之后调用clearCheckpoint()。trackDeletesEnd() - 切勿将/
trackDeletesStart()与仅变更检查点(trackDeletesEnd()、modified_after、变更记录端点等)一起使用。这些请求会忽略未变更的行,因此updated_after会错误地删除它们。trackDeletesEnd() - 带检查点的全量刷新仍然是全量刷新。仅在完成并清除检查点的运行中调用。
trackDeletesEnd() - 如果同步需要元数据(例如、
team_id、workspace_id),请设置guild_id。同步在调用者设置元数据之前无法运行,因此自动启动会失败。autoStart: false
Conventions
约定
- Match field casing to the external API. Passthrough fields keep provider casing; non-passthrough fields should use the majority casing of that API.
- Prefer explicit field names.
- Add examples for IDs, timestamps, enums, and URLs.
.describe() - Avoid ; use inline mapping types.
any - List actions should expose plus a next-cursor field in the majority casing of that API (
cursor,next_cursor, etc.).nextCursor - Use only when you need custom validation or logging; otherwise rely on schemas plus the chosen validation workflow.
nango.zodValidateInput()
- 字段大小写与外部API匹配。透传字段保留提供商的大小写;非透传字段应使用该API的主流大小写。
- 优先使用明确的字段名称。
- 为ID、时间戳、枚举和URL添加示例。
.describe() - 避免使用;使用内联映射类型。
any - 列表动作应暴露以及符合API主流大小写的下一个游标字段(
cursor、next_cursor等)。nextCursor - 仅当需要自定义验证或日志记录时才使用;否则依赖模式和所选的验证工作流。
nango.zodValidateInput()
Schema Semantics
模式语义
- Default non-required inputs to .
.optional() - Use only when
.nullable()has meaning, usually clear-on-update; addnullwhen callers may omit the field too..optional() - Raw provider schemas should match the provider: for omitted fields,
.optional()for explicit.nullable(),nullonly when the provider truly does both..nullish() - Final action outputs and normalized sync models should prefer and normalize upstream
.optional()to omission unlessnullmatters.null - Default generated schemas to for non-required inputs and normalized outputs; widen only when the upstream contract justifies it.
.optional() - Prefer over
.nullable()orz.union([z.null(), T]).z.union([T, z.null()]) - Return only when the output schema allows it.
null - strips unknown keys by default. For provider pass-through use
z.object(),z.object({}).passthrough(), orz.record(z.unknown())with minimal refinements.z.unknown()
- 非必填输入默认设为。
.optional() - 仅当有明确含义(通常是更新时清除)时使用
null;当调用者可能省略字段时添加.nullable()。.optional() - 原始提供商模式应与提供商匹配:用于省略的字段,
.optional()用于显式.nullable(),仅当提供商确实同时支持两种情况时使用null。.nullish() - 最终动作输出和标准化同步模型应优先使用,并将上游
.optional()标准化为省略,除非null很重要。null - 生成的模式默认对非必填输入和标准化输出使用;仅当上游契约有理由时才放宽限制。
.optional() - 优先使用而非
.nullable()或z.union([z.null(), T])。z.union([T, z.null()]) - 仅当输出模式允许时才返回。
null - 默认会剥离未知键。对于提供商透传,使用
z.object()、z.object({}).passthrough()或带最小细化的z.record(z.unknown())。z.unknown()
Field Naming and Casing Rules
字段命名和大小写规则
- Use explicit suffixes in the API's majority casing: IDs (,
user_id), names (userId,channel_name), emails (channelName,user_email), URLs (userEmail,callback_url), and timestamps (callbackUrl,created_at).createdAt
Mapping example (API expects a different parameter name):
typescript
const InputSchema = z.object({
userId: z.string()
});
const config: ProxyConfiguration = {
endpoint: 'users.info',
params: {
user: input.userId
},
retries: 3
};If the API is snake_case, use instead. The goal is API consistency.
user_id- 使用API主流大小写的明确后缀:ID(、
user_id)、名称(userId、channel_name)、邮箱(channelName、user_email)、URL(userEmail、callback_url)和时间戳(callbackUrl、created_at)。createdAt
映射示例(API期望不同的参数名称):
typescript
const InputSchema = z.object({
userId: z.string()
});
const config: ProxyConfiguration = {
endpoint: 'users.info',
params: {
user: input.userId
},
retries: 3
};如果API使用蛇形命名法(snake_case),则改用。目标是与API保持一致。
user_idReferences
参考资料
- Action patterns, CRUD examples, metadata usage, and ActionError examples:
references/actions.md - Sync patterns, concrete checkpoint examples, delete strategies, and full refresh fallback:
references/syncs.md
- 动作模式、CRUD示例、元数据用法和ActionError示例:
references/actions.md - 同步模式、具体检查点示例、删除策略和全量刷新回退:
references/syncs.md
Useful Nango docs (quick links)
实用Nango文档(快速链接)
- Functions runtime SDK reference: https://nango.dev/docs/reference/functions
- Implement an action: https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-action
- Implement a sync: https://nango.dev/docs/implementation-guides/use-cases/syncs/implement-a-sync
- Checkpoints: https://nango.dev/docs/implementation-guides/use-cases/syncs/checkpoints
- Deletion detection (full vs incremental): https://nango.dev/docs/implementation-guides/use-cases/syncs/deletion-detection
- Testing integrations (dryrun, , Vitest): https://nango.dev/docs/implementation-guides/platform/functions/testing
--save - Nango HTTP API reference: https://nango.dev/docs/reference/api
- Functions运行时SDK参考:https://nango.dev/docs/reference/functions
- 实现动作:https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-action
- 实现同步:https://nango.dev/docs/implementation-guides/use-cases/syncs/implement-a-sync
- 检查点:https://nango.dev/docs/implementation-guides/use-cases/syncs/checkpoints
- 删除检测(全量vs增量):https://nango.dev/docs/implementation-guides/use-cases/syncs/deletion-detection
- 测试集成(试运行、、Vitest):https://nango.dev/docs/implementation-guides/platform/functions/testing
--save - Nango HTTP API参考:https://nango.dev/docs/reference/api
When API Docs Do Not Render
当API文档无法渲染时
If web fetching returns incomplete docs (JS-rendered):
- Ask the user for a sample response
- Use existing Nango actions or syncs in the workspace as a pattern when they exist
- Use the skill-specific validation or dryrun workflow until it passes
如果网页抓取返回不完整的文档(JS渲染):
- 向用户请求示例响应
- 当工作区中存在现有Nango动作或同步时,将其作为模式使用
- 使用技能特定的验证或试运行工作流,直到通过验证