functions
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseZavu 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. reconciles the live state.
zavu deployZavu 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 deployWhen to use Functions vs the imperative AI Agent API
何时使用Functions vs 命令式AI Agent API
| Use case | Use |
|---|---|
| Customer wants a code-first agent with custom tool handlers in their own language | Functions |
| Tools need to query the user's database, call internal APIs, or transform data before returning | Functions |
| User wants reproducible config from a git repo (one source of truth) | Functions |
| User wants no-code config via the dashboard | imperative |
User needs event-driven handlers ( | Functions |
If the user mentions writing code, , , , or "serverless" — use this skill. Otherwise route to .
defineAgentdefineToolzavu deployai-agent| 使用场景 | 选择方案 |
|---|---|
| 用户希望使用自己熟悉的语言,以代码优先的方式开发Agent并自定义工具处理器 | Functions |
| 工具需要查询用户数据库、调用内部API,或在返回前转换数据 | Functions |
| 用户希望通过Git仓库实现可复现的配置(单一可信数据源) | Functions |
| 用户希望通过控制台进行无代码配置 | 命令式 |
用户需要事件驱动处理器( | Functions |
如果用户提到编写代码、、、或"serverless"——使用此技能。否则请引导至。
defineAgentdefineToolzavu deployai-agentCLI as primary interface
以CLI为主要操作界面
Functions are managed entirely via the CLI, not API calls. Install once:
zavush
brew install zavudev/tools/zavuFunctions完全通过 CLI管理,无需API调用。只需安装一次:
zavush
brew install zavudev/tools/zavuor grab a standalone binary from https://github.com/zavudev/zavu-cli/releases
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-botTemplates available: , , , .
blankrestaurant-bookingschool-parent-notifyecommerce-order-botThe init writes , , and a that links this directory to a Function record in the user's project. Once linked, every subsequent command auto-resolves the function.
index.tspackage.json.zavu/config.jsonsh
zavu fn init order-bot --template blank
cd order-bot可用模板:、、、。
blankrestaurant-bookingschool-parent-notifyecommerce-order-bot初始化命令会生成、以及,该配置文件会将当前目录与用户项目中的Function记录关联。关联完成后,后续所有命令都会自动解析该函数。
index.tspackage.json.zavu/config.json2. 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_KEYGet 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可通过获取sender ID。
zavu senders list3. Author the agent + tools
3. 编写Agent + 工具
Edit :
index.tsts
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.tsts
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 deployOutput:
✓ Deployed in 6.4s
Agents:
+ Bella (sender_abc, whatsapp)
Tools:
+ lookup_order → BellaThe reconcile is idempotent — re-running with no changes shows .
0 created, 0 updated, 0 deletedsh
zavu deploy输出示例:
✓ Deployed in 6.4s
Agents:
+ Bella (sender_abc, whatsapp)
Tools:
+ lookup_order → Bella部署操作是幂等的——如果代码无变更,重新执行会显示。
0 created, 0 updated, 0 deleted5. Test
5. 测试
Local invocation (skip cloud round-trip):
sh
undefined本地调用(跳过云端往返):
sh
undefinedCall 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
undefined1. 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处理器ctx
结构
ctxts
{
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 via dashboard)
httpEnabled: true - Native event triggers (,
message.inbound, etc — configured viabroadcast.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 }
})仅在需要处理以下场景时使用:
- 原始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 react to Zavu events:
defineFunctionsh
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 typesTriggers use signed internal invocations (no HMAC verification needed inside the handler).
要让响应Zavu事件:
defineFunctionsh
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 creates an immutable version.
zavu deploysh
zavu fn versions list # alias: zavu fn history
zavu fn rollback 4 # go back to version 4The function metadata in the dashboard tracks the active version + lets you rollback from the UI too.
每次执行都会创建一个不可变版本。
zavu deploysh
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 runtimeOnly opt in when there's a security advisory or feature you want — without the flag is safe forever.
zavu deploy每个函数在首次部署时会固定到特定的运行时层。后续部署会保持该固定版本(为稳定性设计,不可变)。
sh
zavu deploy --update-runtime // 主动升级到最新运行时仅在存在安全公告或需要新功能时才主动升级——不带该标志的操作永远是安全的。
zavu deployPricing model
定价模型
Functions are billed by invocation units, memory-weighted:
| Memory | Units per call |
|---|---|
| 128 MB | 1 |
| 256 MB | 2 |
| 512 MB | 4 |
| 1024 MB | 8 |
Each plan includes a monthly quota; overage rolls into the next Stripe invoice via metered billing.
| Plan | Included units | Overage rate |
|---|---|---|
| Free | 100k | Hard cap (invocations blocked) |
| Hobby | 1M | $5 / 1M |
| Standard | 5M | $4 / 1M |
| Growth | 10M | $3 / 1M |
Set memory at function creation or via dashboard. Lower memory = cheaper. Most tool handlers fit in 128 MB.
Functions按调用单元计费,计费与内存权重相关:
| 内存 | 每次调用单元数 |
|---|---|
| 128 MB | 1 |
| 256 MB | 2 |
| 512 MB | 4 |
| 1024 MB | 8 |
每个套餐包含月度配额;超出部分会通过计量计费计入下一期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 , declaring it in code with the same will TAKE OVER that agent — Zavu marks it and the dashboard locks manual edits. The function source becomes source-of-truth.
zavu agents createsenderId + namemanagedByFunctionIdTo go back to manual control: delete the function () and the agent is freed.
zavu fn delete如果用户已通过控制台或创建了Agent,在代码中使用相同的声明Agent会接管该Agent——Zavu会将其标记为,并锁定控制台的手动编辑权限。函数源码将成为唯一可信数据源。
zavu agents createsenderId + namemanagedByFunctionId要恢复手动控制:删除函数()后,Agent会解除锁定。
zavu fn deletePer-environment senders
多环境发送者
ts
defineAgent({
senderId: process.env.NODE_ENV === "production"
? process.env.PROD_SENDER_ID!
: process.env.DEV_SENDER_ID!,
// ...
})Then on prod, on dev. Same code, different agents.
zavu fn secrets set NODE_ENV production... developmentts
defineAgent({
senderId: process.env.NODE_ENV === "production"
? process.env.PROD_SENDER_ID!
: process.env.DEV_SENDER_ID!,
// ...
})然后在生产环境执行,开发环境执行。同一代码可对应不同环境的Agent。
zavu fn secrets set NODE_ENV production... developmentBYOK (Bring Your Own Key)
BYOK(自带密钥)
For OpenAI / Anthropic / Google / Mistral, pass directly:
apiKeyts
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-...对于OpenAI / Anthropic / Google / Mistral,直接传入:
apiKeyts
defineAgent({
senderId: process.env.SENDER_ID!,
provider: "openai",
model: "gpt-4o-mini",
apiKey: process.env.OPENAI_API_KEY,
prompt: "...",
})执行。Agent会直接使用该密钥——LLM调用不会消耗Zavu账户余额。
zavu fn secrets set OPENAI_API_KEY sk-...Pinning a tool to a specific agent (multi-agent functions)
将工具绑定到特定Agent(多Agent函数)
When a function declares more than one , tools default-attach to the first one. To pick explicitly:
defineAgentts
defineTool({
name: "lookup_order",
agent: "Bella", // Match by agent's name field
// ...
})当一个函数声明多个时,工具默认绑定到第一个Agent。如需显式指定:
defineAgentts
defineTool({
name: "lookup_order",
agent: "Bella", // 匹配Agent的name字段
// ...
})Calling Zavu APIs from inside a handler
在处理器内调用Zavu API
Each function gets a scoped injected automatically — use the SDK to call back:
ZAVU_API_KEYts
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 , , scopes. For broader access create a manual API key and inject as a secret.
messages:sendmessages:readcontacts:read每个函数会自动注入一个范围受限的——可使用SDK进行回调:
ZAVU_API_KEYts
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 }
},
})自动生成的密钥拥有、、权限。如需更广泛的访问权限,请创建手动API密钥并作为密钥注入。
messages:sendmessages:readcontacts:readDashboard
控制台
https://dashboard.zavu.dev/functions/<id>- 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
参考文档
- Overview: https://docs.zavu.dev/concepts/functions
- Quickstart: https://docs.zavu.dev/guides/functions/quickstart
- CLI reference: https://docs.zavu.dev/guides/functions/cli
- defineAgent: https://docs.zavu.dev/guides/functions/defining-agents
- defineTool: https://docs.zavu.dev/guides/functions/defining-tools
- Debugging guide: https://docs.zavu.dev/guides/functions/debugging
- Examples: https://docs.zavu.dev/guides/functions/examples/restaurant
- 概述:https://docs.zavu.dev/concepts/functions
- 快速开始:https://docs.zavu.dev/guides/functions/quickstart
- CLI参考:https://docs.zavu.dev/guides/functions/cli
- defineAgent:https://docs.zavu.dev/guides/functions/defining-agents
- defineTool:https://docs.zavu.dev/guides/functions/defining-tools
- 调试指南:https://docs.zavu.dev/guides/functions/debugging
- 示例:https://docs.zavu.dev/guides/functions/examples/restaurant
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: . Reserved prefixes:
[A-Z_][A-Z0-9_]*,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 API in parallel with a managed function. If the function declares an agent, the function owns it — manual edits get blocked.
senders.agent.create - Don't hardcode the in the source. Always read from
senderIdso the same code works across envs.process.env.SENDER_ID - Don't import heavyweight deps you only use in one tool. Each call cold-starts; trim dependencies to keep latency down.
- Don't secrets. Function logs are visible to anyone with project access.
console.log
- 不要同时使用命令式API和托管函数。如果函数声明了Agent,则该Agent归函数所有——手动编辑会被阻止。
senders.agent.create - 不要在源码中硬编码。始终从
senderId读取,确保同一代码可在多环境运行。process.env.SENDER_ID - 不要导入仅在单个工具中使用的重量级依赖。每次调用都会冷启动;精简依赖可降低延迟。
- 不要在中输出密钥。函数日志对所有拥有项目访问权限的用户可见。
console.log