functions

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Zavu Functions

Zavu Functions

Zavu Functions = serverless TypeScript on Zavu Cloud + a declarative framework for AI agents.
ts
import { defineAgent, defineTool } from "@zavu/functions"

defineAgent({
  senderId: process.env.SENDER_ID!,
  name: "Bella",
  provider: "zavu",
  model: "openai/gpt-4o-mini",
  prompt: "You are Bella, host at the restaurant. Be brief.",
})

defineTool({
  name: "check_availability",
  description: "Get free reservation slots for a date.",
  parameters: {
    type: "object",
    properties: { date: { type: "string" }, partySize: { type: "number" } },
    required: ["date", "partySize"],
  },
  handler: async ({ date, partySize }) => {
    return { available: true, slots: ["19:00", "21:00"] }
  },
})
That's a full agent + tool.
zavu deploy
reconciles the live state.
Zavu Functions = Zavu Cloud上的无服务器TypeScript + AI Agent声明式框架。
ts
import { defineAgent, defineTool } from "@zavu/functions"

defineAgent({
  senderId: process.env.SENDER_ID!,
  name: "Bella",
  provider: "zavu",
  model: "openai/gpt-4o-mini",
  prompt: "You are Bella, host at the restaurant. Be brief.",
})

defineTool({
  name: "check_availability",
  description: "Get free reservation slots for a date.",
  parameters: {
    type: "object",
    properties: { date: { type: "string" }, partySize: { type: "number" } },
    required: ["date", "partySize"],
  },
  handler: async ({ date, partySize }) => {
    return { available: true, slots: ["19:00", "21:00"] }
  },
})
这就是一个完整的Agent + 工具。
zavu deploy
会同步线上状态。

When to use Functions vs the imperative AI Agent API

何时使用Functions vs 命令式AI Agent API

Use caseUse
Customer wants a code-first agent with custom tool handlers in their own languageFunctions
Tools need to query the user's database, call internal APIs, or transform data before returningFunctions
User wants reproducible config from a git repo (one source of truth)Functions
User wants no-code config via the dashboardimperative
senders.agent.create
API (see
ai-agent
skill)
User needs event-driven handlers (
message.inbound
,
broadcast.completed
) without dashboard wiring
Functions
If the user mentions writing code,
defineAgent
,
defineTool
,
zavu deploy
, or "serverless" — use this skill. Otherwise route to
ai-agent
.
使用场景选择方案
用户希望使用自己熟悉的语言,以代码优先的方式开发Agent并自定义工具处理器Functions
工具需要查询用户数据库、调用内部API,或在返回前转换数据Functions
用户希望通过Git仓库实现可复现的配置(单一可信数据源)Functions
用户希望通过控制台进行无代码配置命令式
senders.agent.create
API(参考
ai-agent
技能)
用户需要事件驱动处理器(
message.inbound
broadcast.completed
)且无需控制台配置
Functions
如果用户提到编写代码、
defineAgent
defineTool
zavu deploy
或"serverless"——使用此技能。否则请引导至
ai-agent

CLI as primary interface

以CLI为主要操作界面

Functions are managed entirely via the
zavu
CLI, not API calls. Install once:
sh
brew install zavudev/tools/zavu
Functions完全通过
zavu
CLI管理,无需API调用。只需安装一次:
sh
brew install zavudev/tools/zavu
zavu login

`zavu login` opens the browser and stores credentials in `~/.zavu/credentials.json`.
zavu login

`zavu login`会打开浏览器,并将凭证存储在`~/.zavu/credentials.json`中。

Full lifecycle

完整生命周期

1. Scaffold

1. 初始化项目

sh
zavu fn init order-bot --template blank
cd order-bot
Templates available:
blank
,
restaurant-booking
,
school-parent-notify
,
ecommerce-order-bot
.
The init writes
index.ts
,
package.json
, and a
.zavu/config.json
that links this directory to a Function record in the user's project. Once linked, every subsequent command auto-resolves the function.
sh
zavu fn init order-bot --template blank
cd order-bot
可用模板:
blank
restaurant-booking
school-parent-notify
ecommerce-order-bot
初始化命令会生成
index.ts
package.json
以及
.zavu/config.json
,该配置文件会将当前目录与用户项目中的Function记录关联。关联完成后,后续所有命令都会自动解析该函数。

2. Set secrets

2. 设置密钥

Secrets are encrypted env vars injected into the function at deploy time.
sh
zavu fn secrets set SENDER_ID jx7abc123def456
zavu fn secrets set DATABASE_URL "postgres://..."
zavu fn secrets list
zavu fn secrets unset OLD_KEY
Get the sender ID from
zavu senders list
.
密钥是加密的环境变量,会在部署时注入到函数中。
sh
zavu fn secrets set SENDER_ID jx7abc123def456
zavu fn secrets set DATABASE_URL "postgres://..."
zavu fn secrets list
zavu fn secrets unset OLD_KEY
可通过
zavu senders list
获取sender ID。

3. Author the agent + tools

3. 编写Agent + 工具

Edit
index.ts
:
ts
import { defineAgent, defineTool, defineFunction } from "@zavu/functions"

defineAgent({
  senderId: process.env.SENDER_ID!,
  name: "Bella",
  provider: "zavu",              // Zavu's AI gateway (charged from project balance)
                                  // Or "openai" / "anthropic" / "google" / "mistral" with BYOK + apiKey
  model: "openai/gpt-4o-mini",   // For "zavu" provider, prefix with the underlying provider
  prompt: "You are Bella…",       // System prompt
  channels: ["whatsapp"],         // Optional: default ["*"] = all channels the sender supports
  // apiKey: process.env.OPENAI_API_KEY  // only for non-zavu providers
})

defineTool({
  name: "lookup_order",
  description: "Get current status of an order. Use when the customer asks about an order they placed.",
  parameters: {
    type: "object",
    properties: { orderId: { type: "string" } },
    required: ["orderId"],
  },
  handler: async (args, ctx) => {
    // ctx: { projectId, functionId, slug, awsRequestId, messageId?, contactPhone?, sessionId?, log }
    const res = await fetch(`https://pos.example.com/orders/${args.orderId}`, {
      headers: { Authorization: `Bearer ${process.env.POS_API_KEY}` },
    })
    return await res.json()
  },
})

// Optional: handle raw events (message.inbound from triggers, HTTP calls).
// NOT needed if you only declare agent + tools.
export default defineFunction(async (event, ctx) => {
  ctx.log("got event", event.type)
})
编辑
index.ts
ts
import { defineAgent, defineTool, defineFunction } from "@zavu/functions"

defineAgent({
  senderId: process.env.SENDER_ID!,
  name: "Bella",
  provider: "zavu",              // Zavu的AI网关(从项目余额扣费)
                                  // 或选择"openai" / "anthropic" / "google" / "mistral",需自行提供密钥(BYOK)并配置apiKey
  model: "openai/gpt-4o-mini",   // 使用"zavu"提供商时,需添加底层提供商前缀
  prompt: "You are Bella…",       // 系统提示词
  channels: ["whatsapp"],         // 可选:默认值["*"]表示支持发送者的所有渠道
  // apiKey: process.env.OPENAI_API_KEY  // 仅非"zavu"提供商需要配置
})

defineTool({
  name: "lookup_order",
  description: "Get current status of an order. Use when the customer asks about an order they placed.",
  parameters: {
    type: "object",
    properties: { orderId: { type: "string" } },
    required: ["orderId"],
  },
  handler: async (args, ctx) => {
    // ctx: { projectId, functionId, slug, awsRequestId, messageId?, contactPhone?, sessionId?, log }
    const res = await fetch(`https://pos.example.com/orders/${args.orderId}`, {
      headers: { Authorization: `Bearer ${process.env.POS_API_KEY}` },
    })
    return await res.json()
  },
})

// 可选:处理原始事件(触发器触发的message.inbound、HTTP调用)。
// 仅声明agent + 工具时无需配置此项。
export default defineFunction(async (event, ctx) => {
  ctx.log("got event", event.type)
})

4. Deploy

4. 部署

sh
zavu deploy
Output:
✓ Deployed in 6.4s
  Agents:
    + Bella           (sender_abc, whatsapp)
  Tools:
    + lookup_order    → Bella
The reconcile is idempotent — re-running with no changes shows
0 created, 0 updated, 0 deleted
.
sh
zavu deploy
输出示例:
✓ Deployed in 6.4s
  Agents:
    + Bella           (sender_abc, whatsapp)
  Tools:
    + lookup_order    → Bella
部署操作是幂等的——如果代码无变更,重新执行会显示
0 created, 0 updated, 0 deleted

5. Test

5. 测试

Local invocation (skip cloud round-trip):
sh
undefined
本地调用(跳过云端往返):
sh
undefined

Call a tool handler with synthetic args

使用模拟参数调用工具处理器

zavu fn invoke --tool lookup_order --args '{"orderId":"ORD-001"}'
zavu fn invoke --tool lookup_order --args '{"orderId":"ORD-001"}'

Simulate an inbound event for defineFunction

为defineFunction模拟入站事件

zavu fn invoke --event message.inbound --data '{"from":"+14155551234","text":"hi"}'

**End-to-end:** send a real message to the sender's WhatsApp/SMS/Telegram number. The agent runs the LLM, calls tools, and replies via the same channel.
zavu fn invoke --event message.inbound --data '{"from":"+14155551234","text":"hi"}'

**端到端测试:** 向发送者的WhatsApp/SMS/Telegram号码发送真实消息。Agent会运行LLM、调用工具,并通过同一渠道回复。

6. Debug

6. 调试

When something fails, walk the chain top-down:
sh
undefined
出现故障时,按以下步骤自上而下排查:
sh
undefined

1. Did the inbound reach the agent?

1. 入站消息是否到达Agent?

zavu agents executions list --sender <senderId>
zavu agents executions list --sender <senderId>

2. Detail of any failed run

2. 查看失败运行的详细信息

zavu agents executions get <executionId> --sender <senderId>
zavu agents executions get <executionId> --sender <senderId>

3. Live tool handler logs (your console.log calls)

3. 实时查看工具处理器日志(你的console.log调用)

zavu fn logs --tail

The `--json` flag on `executions list` returns the full payload including `errorMessage` for parseable diagnostics.
zavu fn logs --tail

`executions list`命令添加`--json`标志会返回完整 payload,包括可解析诊断的`errorMessage`。

defineAgent reference

defineAgent 参考文档

ts
defineAgent({
  senderId: string,              // Required. The sender that receives inbound + dispatches the agent.
  name: string,                  // Required. Displayed in dashboard.
  provider: "zavu" | "openai" | "anthropic" | "google" | "mistral",
  model: string,                 // For "zavu": prefix with underlying provider e.g. "openai/gpt-4o-mini"
  prompt: string,                // System prompt.
  apiKey?: string,               // Required for non-"zavu" providers.
  channels?: string[],           // Default ["*"]. Subset of: sms, whatsapp, telegram, email, instagram, voice
  messageTypes?: string[],       // Default ["text"]. Filter by message type.
  temperature?: number,          // 0-2.
  maxTokens?: number,            // Cap on output tokens.
  contextWindowMessages?: number,// Past N messages included as context. Default 10.
  sessionTimeoutMinutes?: number,// Reset conversation context after N minutes. Default 60.
  includeContactMetadata?: boolean, // Inject contact's metadata into the system prompt. Default true.
  enabled?: boolean,             // Default true.
})
ts
defineAgent({
  senderId: string,              // 必填。接收入站消息并调度Agent的发送者。
  name: string,                  // 必填。在控制台中显示的名称。
  provider: "zavu" | "openai" | "anthropic" | "google" | "mistral",
  model: string,                 // 使用"zavu"时:需添加底层提供商前缀,例如"openai/gpt-4o-mini"
  prompt: string,                // 系统提示词。
  apiKey?: string,               // 非"zavu"提供商必填。
  channels?: string[],           // 默认值["*"]。可选渠道子集:sms, whatsapp, telegram, email, instagram, voice
  messageTypes?: string[],       // 默认值["text"]。按消息类型过滤。
  temperature?: number,          // 取值范围0-2。
  maxTokens?: number,            // 输出令牌上限。
  contextWindowMessages?: number,// 作为上下文包含的过往消息数量。默认值10。
  sessionTimeoutMinutes?: number,// N分钟后重置对话上下文。默认值60。
  includeContactMetadata?: boolean, // 将联系人元数据注入系统提示词。默认值true。
  enabled?: boolean,             // 默认值true。
})

defineTool reference

defineTool 参考文档

ts
defineTool({
  name: string,                  // Required. snake_case, max 64 chars.
  description: string,           // Required. The LLM reads this to decide WHEN to call the tool.
  parameters: {
    type: "object",
    properties: { /* JSON Schema */ },
    required?: string[],
  },
  handler: async (args, ctx) => any,  // Required. Return any JSON-serializable value.
  agent?: string,                // Optional: which agent owns this tool. Defaults to the only agent in the file.
  enabled?: boolean,             // Default true.
})
ts
defineTool({
  name: string,                  // 必填。使用蛇形命名法,最长64字符。
  description: string,           // 必填。LLM会读取此描述来决定何时调用工具。
  parameters: {
    type: "object",
    properties: { /* JSON Schema */ },
    required?: string[],
  },
  handler: async (args, ctx) => any,  // 必填。返回任何可JSON序列化的值。
  agent?: string,                // 可选:指定此工具所属的Agent。默认绑定文件中的唯一Agent。
  enabled?: boolean,             // 默认值true。
})

Handler
ctx
shape

处理器
ctx
结构

ts
{
  projectId: string,
  functionId: string,
  slug: string,
  awsRequestId: string,
  messageId?: string,            // ID of the triggering inbound (when called by agent)
  contactPhone?: string,
  sessionId?: string,            // Active flow session if any
  log: (...args) => void,        // console.log proxy that appears in `zavu fn logs --tail`
}
ts
{
  projectId: string,
  functionId: string,
  slug: string,
  awsRequestId: string,
  messageId?: string,            // 触发调用的入站消息ID(当由Agent调用时)
  contactPhone?: string,
  sessionId?: string,            // 当前活跃的流程会话(如有)
  log: (...args) => void,        // console.log代理,会显示在`zavu fn logs --tail`中
}

defineFunction reference (optional)

defineFunction 参考文档(可选)

Use only if you want to handle:
  • Raw HTTP requests (function exposed at a public URL — set
    httpEnabled: true
    via dashboard)
  • Native event triggers (
    message.inbound
    ,
    broadcast.completed
    , etc — configured via
    zavu fn triggers add
    )
ts
export default defineFunction(async (event, ctx) => {
  if (event.type === "message.inbound") {
    // event.data: { from, text, channel, messageId, ... }
  }
  return { ok: true }
})
仅在需要处理以下场景时使用:
  • 原始HTTP请求(函数会暴露在公共URL中——需通过控制台设置
    httpEnabled: true
  • 原生事件触发器
    message.inbound
    broadcast.completed
    等——通过
    zavu fn triggers add
    配置)
ts
export default defineFunction(async (event, ctx) => {
  if (event.type === "message.inbound") {
    // event.data: { from, text, channel, messageId, ... }
  }
  return { ok: true }
})

Triggers (event subscriptions)

触发器(事件订阅)

To make
defineFunction
react to Zavu events:
sh
zavu fn triggers list
zavu fn triggers add --events message.inbound --senders <senderId>
zavu fn triggers add --events broadcast.completed --senders any
zavu fn triggers toggle <triggerId>
zavu fn triggers rm <triggerId>
zavu fn triggers events       # list available event types
Triggers use signed internal invocations (no HMAC verification needed inside the handler).
要让
defineFunction
响应Zavu事件:
sh
zavu fn triggers list
zavu fn triggers add --events message.inbound --senders <senderId>
zavu fn triggers add --events broadcast.completed --senders any
zavu fn triggers toggle <triggerId>
zavu fn triggers rm <triggerId>
zavu fn triggers events       // 列出可用事件类型
触发器使用签名内部调用(处理器内无需HMAC验证)。

Versions + rollback

版本与回滚

Every
zavu deploy
creates an immutable version.
sh
zavu fn versions list           # alias: zavu fn history
zavu fn rollback 4              # go back to version 4
The function metadata in the dashboard tracks the active version + lets you rollback from the UI too.
每次执行
zavu deploy
都会创建一个不可变版本。
sh
zavu fn versions list           // 别名:zavu fn history
zavu fn rollback 4              // 回滚到版本4
控制台中的函数元数据会跟踪当前活跃版本,也支持从UI进行回滚操作。

Runtime versions

运行时版本

Each function pins to a specific runtime layer at first deploy. Subsequent deploys keep the same pin (immutable for stability).
sh
zavu deploy --update-runtime   # opt-in upgrade to latest runtime
Only opt in when there's a security advisory or feature you want —
zavu deploy
without the flag is safe forever.
每个函数在首次部署时会固定到特定的运行时层。后续部署会保持该固定版本(为稳定性设计,不可变)。
sh
zavu deploy --update-runtime   // 主动升级到最新运行时
仅在存在安全公告或需要新功能时才主动升级——不带该标志的
zavu deploy
操作永远是安全的。

Pricing model

定价模型

Functions are billed by invocation units, memory-weighted:
MemoryUnits per call
128 MB1
256 MB2
512 MB4
1024 MB8
Each plan includes a monthly quota; overage rolls into the next Stripe invoice via metered billing.
PlanIncluded unitsOverage rate
Free100kHard cap (invocations blocked)
Hobby1M$5 / 1M
Standard5M$4 / 1M
Growth10M$3 / 1M
Set memory at function creation or via dashboard. Lower memory = cheaper. Most tool handlers fit in 128 MB.
Functions按调用单元计费,计费与内存权重相关:
内存每次调用单元数
128 MB1
256 MB2
512 MB4
1024 MB8
每个套餐包含月度配额;超出部分会通过计量计费计入下一期Stripe账单。
套餐包含调用单元数超额费率
免费版10万硬限制(超出后调用会被阻止)
爱好者版100万$5 / 100万
标准版500万$4 / 100万
成长版1000万$3 / 100万
可在函数创建时或通过控制台设置内存。内存越低越便宜。大多数工具处理器只需128 MB即可运行。

Common patterns

常见模式

Take over a manual agent

接管手动创建的Agent

If the user already created an agent via the dashboard or
zavu agents create
, declaring it in code with the same
senderId + name
will TAKE OVER that agent — Zavu marks it
managedByFunctionId
and the dashboard locks manual edits. The function source becomes source-of-truth.
To go back to manual control: delete the function (
zavu fn delete
) and the agent is freed.
如果用户已通过控制台或
zavu agents create
创建了Agent,在代码中使用相同的
senderId + name
声明Agent会接管该Agent——Zavu会将其标记为
managedByFunctionId
,并锁定控制台的手动编辑权限。函数源码将成为唯一可信数据源。
要恢复手动控制:删除函数(
zavu fn delete
)后,Agent会解除锁定。

Per-environment senders

多环境发送者

ts
defineAgent({
  senderId: process.env.NODE_ENV === "production"
    ? process.env.PROD_SENDER_ID!
    : process.env.DEV_SENDER_ID!,
  // ...
})
Then
zavu fn secrets set NODE_ENV production
on prod,
... development
on dev. Same code, different agents.
ts
defineAgent({
  senderId: process.env.NODE_ENV === "production"
    ? process.env.PROD_SENDER_ID!
    : process.env.DEV_SENDER_ID!,
  // ...
})
然后在生产环境执行
zavu fn secrets set NODE_ENV production
,开发环境执行
... development
。同一代码可对应不同环境的Agent。

BYOK (Bring Your Own Key)

BYOK(自带密钥)

For OpenAI / Anthropic / Google / Mistral, pass
apiKey
directly:
ts
defineAgent({
  senderId: process.env.SENDER_ID!,
  provider: "openai",
  model: "gpt-4o-mini",
  apiKey: process.env.OPENAI_API_KEY,
  prompt: "...",
})
zavu fn secrets set OPENAI_API_KEY sk-...
. The agent uses the key directly — no Zavu balance consumed for LLM calls.
对于OpenAI / Anthropic / Google / Mistral,直接传入
apiKey
ts
defineAgent({
  senderId: process.env.SENDER_ID!,
  provider: "openai",
  model: "gpt-4o-mini",
  apiKey: process.env.OPENAI_API_KEY,
  prompt: "...",
})
执行
zavu fn secrets set OPENAI_API_KEY sk-...
。Agent会直接使用该密钥——LLM调用不会消耗Zavu账户余额。

Pinning a tool to a specific agent (multi-agent functions)

将工具绑定到特定Agent(多Agent函数)

When a function declares more than one
defineAgent
, tools default-attach to the first one. To pick explicitly:
ts
defineTool({
  name: "lookup_order",
  agent: "Bella",   // Match by agent's name field
  // ...
})
当一个函数声明多个
defineAgent
时,工具默认绑定到第一个Agent。如需显式指定:
ts
defineTool({
  name: "lookup_order",
  agent: "Bella",   // 匹配Agent的name字段
  // ...
})

Calling Zavu APIs from inside a handler

在处理器内调用Zavu API

Each function gets a scoped
ZAVU_API_KEY
injected automatically — use the SDK to call back:
ts
import { Zavudev } from "@zavudev/sdk"

const zavu = new Zavudev({ apiKey: process.env.ZAVU_API_KEY })

defineTool({
  name: "send_followup",
  handler: async (args, ctx) => {
    await zavu.messages.send({
      to: ctx.contactPhone!,
      text: "Thanks for your order!",
    })
    return { sent: true }
  },
})
The auto-provisioned key has
messages:send
,
messages:read
,
contacts:read
scopes. For broader access create a manual API key and inject as a secret.
每个函数会自动注入一个范围受限的
ZAVU_API_KEY
——可使用SDK进行回调:
ts
import { Zavudev } from "@zavudev/sdk"

const zavu = new Zavudev({ apiKey: process.env.ZAVU_API_KEY })

defineTool({
  name: "send_followup",
  handler: async (args, ctx) => {
    await zavu.messages.send({
      to: ctx.contactPhone!,
      text: "Thanks for your order!",
    })
    return { sent: true }
  },
})
自动生成的密钥拥有
messages:send
messages:read
contacts:read
权限。如需更广泛的访问权限,请创建手动API密钥并作为密钥注入。

Dashboard

控制台

https://dashboard.zavu.dev/functions/<id>
shows tabs:
  • Code — current draft source (editable in browser)
  • Triggers — event subscriptions
  • Agents & Tools — what this function manages, with deep-links to executions
  • Dependencies — npm packages used by the bundle
  • Secrets — encrypted env vars (values are write-only)
  • Versions — deploy history + rollback
  • Logs — runtime stdout/stderr of recent invocations
  • Settings — memory, timeout, httpEnabled, delete
访问
https://dashboard.zavu.dev/functions/<id>
可查看以下标签页:
  • 代码 — 当前草稿源码(可在浏览器中编辑)
  • 触发器 — 事件订阅
  • Agents & Tools — 此函数管理的资源,包含执行记录的深度链接
  • 依赖 — 打包使用的npm包
  • 密钥 — 加密环境变量(值仅可写入)
  • 版本 — 部署历史与回滚
  • 日志 — 最近调用的运行时标准输出/错误
  • 设置 — 内存、超时时间、httpEnabled、删除操作

Reference docs

参考文档

Constraints

约束条件

  • Slug: lowercase alphanumeric + hyphens, max 23 chars (Lambda name limit).
  • Source bundle: ≤ 900 KB compressed.
  • Total env size: 4 KB across all secrets.
  • Secret key format:
    [A-Z_][A-Z0-9_]*
    . Reserved prefixes:
    AWS_
    ,
    LAMBDA_
    ,
    _HANDLER
    ,
    _X_AMZN
    .
  • Timeout: ≤ 30 s (configurable, default 10 s).
  • Memory: 128 / 256 / 512 / 1024 MB.
  • Tools per agent: 16.
  • Agents per function: no hard cap, but typically 1.
  • Slug:小写字母数字+连字符,最长23字符(Lambda名称限制)。
  • 源码包:压缩后≤900 KB。
  • 环境变量总大小:所有密钥合计4 KB。
  • 密钥名称格式:
    [A-Z_][A-Z0-9_]*
    。保留前缀:
    AWS_
    LAMBDA_
    _HANDLER
    _X_AMZN
  • 超时时间:≤30秒(可配置,默认10秒)。
  • 内存:128 / 256 / 512 / 1024 MB。
  • 每个Agent可绑定工具数:16个。
  • 每个函数可声明Agent数:无硬性限制,但通常为1个。

Anti-patterns

反模式

  • Don't use the imperative
    senders.agent.create
    API in parallel with a managed function
    . If the function declares an agent, the function owns it — manual edits get blocked.
  • Don't hardcode the
    senderId
    in the source. Always read from
    process.env.SENDER_ID
    so the same code works across envs.
  • Don't import heavyweight deps you only use in one tool. Each call cold-starts; trim dependencies to keep latency down.
  • Don't
    console.log
    secrets
    . Function logs are visible to anyone with project access.
  • 不要同时使用命令式
    senders.agent.create
    API和托管函数
    。如果函数声明了Agent,则该Agent归函数所有——手动编辑会被阻止。
  • 不要在源码中硬编码
    senderId
    。始终从
    process.env.SENDER_ID
    读取,确保同一代码可在多环境运行。
  • 不要导入仅在单个工具中使用的重量级依赖。每次调用都会冷启动;精简依赖可降低延迟。
  • 不要在
    console.log
    中输出密钥
    。函数日志对所有拥有项目访问权限的用户可见。