building-nango-functions

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Build 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
building-nango-functions-locally
instead. If it becomes clearly remote/API-based, use
building-nango-functions-remotely
instead.
构建Nango动作和同步实现,无需选择执行工作流。
本技能涵盖函数设计契约:模式(schemas)、提供商调用、动作输出、同步模型、检查点(checkpoints)、删除处理、元数据、重试和运行时约束。它特意不涉及本地CLI验证/部署或远程API编译/试运行/部署的内容。
如果任务明确为本地/CLI相关,请改用
building-nango-functions-locally
。如果任务明确为远程/API相关,请改用
building-nango-functions-remotely

Implementation 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函数实现
  • 使用
    createAction()
    在Nango中构建动作
  • 使用
    createSync()
    在Nango中构建同步
  • 使用活动工作流技能处理编译、试运行、测试和部署机制

Sync Strategy Gate (required before writing code)

同步策略关卡(编写代码前必须完成)

If the task is a sync, read
references/syncs.md
before writing code and state one of these paths first:
  • Checkpoint plan:
    • change source (
      updated_at
      ,
      modified_since
      , changed-records endpoint, cursor, page token, offset/page,
      since_id
      , or webhook)
    • 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
  • 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
  • saveCheckpoint()
    without
    getCheckpoint()
  • reading or saving a checkpoint without using it in request params or pagination state
  • using
    syncType: 'incremental'
    or
    nango.lastSyncDate
    in a new sync
  • a full refresh with no
    checkpoint
    schema, or one that is never saved after each page — the run restarts from page 1 whenever it exceeds the execution window
  • calling
    trackDeletesEnd()
    before
    clearCheckpoint()
    , or without a preceding
    clearCheckpoint()
    at all
  • using
    trackDeletesStart()
    /
    trackDeletesEnd()
    with a changed-only checkpoint (
    modified_after
    ,
    updated_after
    , changed-records endpoint). Those requests omit unchanged rows, so
    trackDeletesEnd()
    will falsely delete them.
  • using
    trackDeletesStart()
    /
    trackDeletesEnd()
    in an incremental sync that already has explicit deleted-record events
如果任务是同步,请在编写代码前阅读
references/syncs.md
,并首先说明以下路径之一:
  • 检查点计划:
    • 变更源(
      updated_at
      modified_since
      、变更记录端点、游标、页面令牌、偏移量/页码、
      since_id
      或Webhook)
    • 检查点模式
    • 检查点如何更改提供商请求或恢复状态
    • 请求是仍遍历完整数据集还是仅返回变更行
    • 删除策略
  • 全量刷新限制:
    • 来自文档或示例负载的确切提供商限制
    • 检查点无法在此处工作的原因
无效的同步实现:
  • 因为简单而选择全量刷新
  • 调用
    saveCheckpoint()
    但未调用
    getCheckpoint()
  • 读取或保存检查点但未在请求参数或分页状态中使用它
  • 在新同步中使用
    syncType: 'incremental'
    nango.lastSyncDate
  • 没有
    checkpoint
    模式的全量刷新,或者在每页后从不保存检查点——每当执行窗口超时,运行将从第1页重新开始
  • 在调用
    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
    references/actions.md
    before writing code
Sync:
  • Scheduled or webhook-driven cache updates built with
    createSync()
  • Complete the Sync Strategy Gate first
  • Read
    references/syncs.md
    before writing code
动作:
  • 一次性请求,由用户触发,使用
    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,
    since_id
    , or composite)
  • 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
    /
    node:crypto
    , and
    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
    fs
    , no
    axios
    , 2 MB output limit). Use a proxy script in
    {integration}/proxy/
    with
    @nangohq/node
    instead — see
    references/actions.md
    .
  • HTTP retries default to
    0
    ; set
    retries
    deliberately. Treat
    3
    as the normal maximum; for sync provider calls, values above
    3
    are effectively forbidden unless docs prove they are safe and necessary. Avoid retries for non-idempotent writes unless the API supports idempotency.
  • Do not set deprecated function definition routing fields: action
    endpoint
    and sync
    endpoints
    . Trigger actions by action name through the SDK/API, and consume sync records through the records API.
  • Nango函数使用
    createAction()
    /
    createSync()
  • 不能添加任意包。仅当所选工作流支持时才使用相对导入;内置包包括
    zod
    crypto
    /
    node:crypto
    url
    /
    node:url
  • 使用Nango HTTP API进行连接查找、凭证获取和函数代码外的代理调用。不要自行发明CLI令牌或连接命令。
  • 在每个提供商调用上方添加API文档链接注释。
  • 动作输出不能超过2MB。
  • 文件上传和下载不能作为动作实现(沙箱运行时:无
    fs
    ,无
    axios
    ,2MB输出限制)。请改用
    {integration}/proxy/
    中的代理脚本并配合
    @nangohq/node
    ——详见
    references/actions.md
  • HTTP重试默认值为
    0
    ;需有意设置
    retries
    。通常最大值设为
    3
    ;对于同步提供商调用,除非文档证明安全且必要,否则禁止设置超过
    3
    的值。除非API支持幂等性,否则避免对非幂等写入进行重试。
  • 不要设置已弃用的函数定义路由字段:动作的
    endpoint
    和同步的
    endpoints
    。通过SDK/API按动作名称触发动作,并通过记录API使用同步记录。

Sync rules

同步规则

  • Sync records need a stable string
    id
    .
  • New syncs should define a
    checkpoint
    schema, call
    nango.getCheckpoint()
    first, and
    nango.saveCheckpoint()
    after each page or batch.
  • A checkpoint is valid only if it changes the request or resume state (
    since
    ,
    updated_after
    ,
    cursor
    ,
    page_token
    ,
    offset
    ,
    page
    ,
    since_id
    , etc.). Saving one without using it is not incremental sync.
  • New syncs must not use
    syncType: 'incremental'
    or
    nango.lastSyncDate
    .
  • Default to
    nango.paginate(...)
    +
    nango.batchSave(...)
    . Avoid manual
    while (true)
    loops when
    cursor
    ,
    link
    , or
    offset
    pagination fits.
  • Prefer
    batchDelete()
    when the provider returns deletions, tombstones, or delete webhooks.
  • 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
    checkpoint
    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.
  • deleteRecordsFromPreviousExecutions()
    is deprecated. For full refresh, call
    trackDeletesStart()
    on every execution (safe/idempotent — it will not overwrite the start of an already-open window), then
    saveCheckpoint()
    after each page,
    clearCheckpoint()
    after the last page, and
    trackDeletesEnd()
    only after that
    clearCheckpoint()
    .
  • Never combine
    trackDeletesStart()
    /
    trackDeletesEnd()
    with changed-only checkpoints (
    modified_after
    ,
    updated_after
    , changed-records endpoints, etc.). They omit unchanged rows, so
    trackDeletesEnd()
    would delete them.
  • Checkpointed full refreshes are still full refreshes. Call
    trackDeletesEnd()
    only in the run that finishes and clears the checkpoint.
  • If a sync requires metadata (e.g.
    team_id
    ,
    workspace_id
    ,
    guild_id
    ), set
    autoStart: false
    . The sync cannot run until the caller has set the metadata, so starting it automatically would fail.
  • 同步记录需要稳定的字符串
    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()
  • 仅当提供商无法返回变更、删除或恢复状态,或者数据集极小时,才使用全量刷新。
  • 对于全量刷新,需引用来自文档或负载的确切提供商限制。“更简单”不足以成为理由。
  • 全量刷新同步仍需要
    checkpoint
    模式(页面/游标/偏移量)来覆盖分页进度,而不仅仅是增量同步。Nango同步在限时执行窗口内运行;没有检查点的全量刷新会在每次超时后从第1页重新开始,浪费计算资源重新获取相同的早期页面,永远无法处理剩余页面。
  • 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
    .describe()
    examples for IDs, timestamps, enums, and URLs.
  • Avoid
    any
    ; use inline mapping types.
  • List actions should expose
    cursor
    plus a next-cursor field in the majority casing of that API (
    next_cursor
    ,
    nextCursor
    , etc.).
  • Use
    nango.zodValidateInput()
    only when you need custom validation or logging; otherwise rely on schemas plus the chosen validation workflow.
  • 字段大小写与外部API匹配。透传字段保留提供商的大小写;非透传字段应使用该API的主流大小写。
  • 优先使用明确的字段名称。
  • 为ID、时间戳、枚举和URL添加
    .describe()
    示例。
  • 避免使用
    any
    ;使用内联映射类型。
  • 列表动作应暴露
    cursor
    以及符合API主流大小写的下一个游标字段(
    next_cursor
    nextCursor
    等)。
  • 仅当需要自定义验证或日志记录时才使用
    nango.zodValidateInput()
    ;否则依赖模式和所选的验证工作流。

Schema Semantics

模式语义

  • Default non-required inputs to
    .optional()
    .
  • Use
    .nullable()
    only when
    null
    has meaning, usually clear-on-update; add
    .optional()
    when callers may omit the field too.
  • Raw provider schemas should match the provider:
    .optional()
    for omitted fields,
    .nullable()
    for explicit
    null
    ,
    .nullish()
    only when the provider truly does both.
  • Final action outputs and normalized sync models should prefer
    .optional()
    and normalize upstream
    null
    to omission unless
    null
    matters.
  • Default generated schemas to
    .optional()
    for non-required inputs and normalized outputs; widen only when the upstream contract justifies it.
  • Prefer
    .nullable()
    over
    z.union([z.null(), T])
    or
    z.union([T, z.null()])
    .
  • Return
    null
    only when the output schema allows it.
  • z.object()
    strips unknown keys by default. For provider pass-through use
    z.object({}).passthrough()
    ,
    z.record(z.unknown())
    , or
    z.unknown()
    with minimal refinements.
  • 非必填输入默认设为
    .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
    ,
    userId
    ), names (
    channel_name
    ,
    channelName
    ), emails (
    user_email
    ,
    userEmail
    ), URLs (
    callback_url
    ,
    callbackUrl
    ), and timestamps (
    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
user_id
instead. The goal is API consistency.
  • 使用API主流大小写的明确后缀:ID(
    user_id
    userId
    )、名称(
    channel_name
    channelName
    )、邮箱(
    user_email
    userEmail
    )、URL(
    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),则改用
user_id
。目标是与API保持一致。

References

参考资料

  • 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文档(快速链接)

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动作或同步时,将其作为模式使用
  • 使用技能特定的验证或试运行工作流,直到通过验证