arcjet

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Arcjet

Arcjet

Contents

目录

Add Arcjet Protection to Your App

为你的应用添加Arcjet防护

Checklist

检查清单

  • Step 1: Verify language support (JS/TS, Python, or Go only — stop if unsupported)
  • Step 2: Connect to Arcjet platform (CLI → MCP → manual Console setup)
  • Step 3: Detect protection type and read the appropriate reference file
  • Step 4: Implement protection (separate client file, correct SDK, correct patterns)
  • Step 5: Verify decisions are firing correctly (trigger a real call, then check CLI / MCP / Console)
  • 步骤1:验证语言支持(仅支持JS/TS、Python或Go——若不支持则停止操作)
  • 步骤2:连接到Arcjet平台(CLI → MCP → 手动控制台设置)
  • 步骤3:检测防护类型并阅读对应的参考文档
  • 步骤4:实现防护(独立客户端文件、正确的SDK、正确的模式)
  • 步骤5:验证决策是否正确触发(发起真实调用,然后检查CLI / MCP / 控制台)

Step 1: Check Language Support

步骤1:检查语言支持

If the project's server-side code is not JavaScript, TypeScript, Python, or Go → tell the user in chat that Arcjet doesn't support their language yet. Don't modify the project, don't write a
NOTES.md
, don't invent a package. Just say it and stop.
如果项目的服务端代码不是JavaScript、TypeScript、Python或Go → 在聊天中告知用户Arcjet目前不支持他们的语言。不要修改项目、不要编写
NOTES.md
、不要自行创建包。只需告知用户并停止操作。

Step 2: Get an ARCJET_KEY into the project's env file

步骤2:将ARCJET_KEY添加到项目的环境文件中

Before writing any code, the project needs a real
ARCJET_KEY
in its env file. Don't write Arcjet code first and "leave the key as a TODO" — that just produces dead code. Get the key first, then wire it up.
In order of preference:
  1. Arcjet CLI (preferred). Check whether you're already signed in, then retrieve a key.
  2. Arcjet MCP server (endpoint:
    https://api.arcjet.com/mcp
    ) — for clients with built-in MCP. See references/mcp.md.
  3. Manual (last resort): tell the user to grab a key from https://app.arcjet.com.
在编写任何代码之前,项目的环境文件中需要一个真实的
ARCJET_KEY
。不要先编写Arcjet代码然后“将密钥留作TODO”——这只会产生无效代码。先获取密钥,再进行配置。
优先顺序:
  1. Arcjet CLI(首选)。检查是否已登录,然后获取密钥。
  2. Arcjet MCP服务器(端点:
    https://api.arcjet.com/mcp
    )——适用于内置MCP的客户端。请参阅references/mcp.md
  3. 手动方式(最后手段):告知用户从https://app.arcjet.com获取密钥。

CLI bootstrap (the normal path)

CLI引导(常规流程)

bash
npx -y @arcjet/cli@latest auth status        # is the user already signed in?
bash
npx -y @arcjet/cli@latest auth status        # 用户是否已登录?

if not signed in:

若未登录:

npx -y @arcjet/cli@latest auth login # browser device flow, see references/cli.md
npx -y @arcjet/cli@latest teams list --output json --fields id,name npx -y @arcjet/cli@latest sites list --team-id <team_id> --output json --fields id,name
npx -y @arcjet/cli@latest auth login # 浏览器设备流,请参阅references/cli.md
npx -y @arcjet/cli@latest teams list --output json --fields id,name npx -y @arcjet/cli@latest sites list --team-id <team_id> --output json --fields id,name

if no suitable site exists:

若不存在合适的站点:

npx -y @arcjet/cli@latest sites create --team-id <team_id> --name "<project>"
npx -y @arcjet/cli@latest sites get-key --site-id <site_id> --output json --fields key

Write the `key` value to the project's env file as `ARCJET_KEY=ajkey_...`. Match whatever the project already does — filename, `.env.example` companion, `.gitignore` entry. If the project doesn't have a convention yet, default to whatever the framework expects and add the env file to `.gitignore`. Never hardcode the key in source.

See [references/cli.md](references/cli.md) for install options beyond `npx`, agent-mode flags, and the full command reference.
npx -y @arcjet/cli@latest sites create --team-id <team_id> --name "<project>"
npx -y @arcjet/cli@latest sites get-key --site-id <site_id> --output json --fields key

将`key`值写入项目的环境文件,格式为`ARCJET_KEY=ajkey_...`。遵循项目已有的约定——文件名、`.env.example`配套文件、`.gitignore`中的条目。如果项目尚无约定,则默认采用框架期望的方式,并将环境文件添加到`.gitignore`中。绝对不要在源代码中硬编码密钥。

有关`npx`之外的安装选项、代理模式标志和完整命令参考,请参阅[references/cli.md](references/cli.md)。

Install the SDK with the project's package manager

使用项目的包管理器安装SDK

Once you know which SDK you need (Step 3 below), install it via the package manager the project already uses —
npm install
,
pnpm add
,
yarn add
,
bun add
,
pip install
,
uv add
,
poetry add
,
go get
, etc. Don't hand-edit
package.json
/
requirements.txt
/
go.mod
and guess a version: typed versions tend to be wrong (
arcjet>=1.0.0
doesn't exist for the Python SDK;
^1.0.0
is stale for
@arcjet/next
; Go should use the module tag, not a copied pseudo-version), and the lockfile/module metadata won't get updated. Let the package manager pick the real version and pin it.
一旦确定所需的SDK(如下文步骤3),使用项目已有的包管理器进行安装——
npm install
pnpm add
yarn add
bun add
pip install
uv add
poetry add
go get
等。不要手动编辑
package.json
/
requirements.txt
/
go.mod
并猜测版本:手动输入的版本往往不准确(Python SDK不存在
arcjet>=1.0.0
@arcjet/next
^1.0.0
已过时;Go应使用模块标签而非复制的伪版本),且锁文件/元数据不会更新。让包管理器选择真实版本并固定。

Step 3: Detect Protection Type and Read Reference

步骤3:检测防护类型并阅读参考文档

Determine which protection type applies:
Request-basedGuard
When to useCode has an HTTP request object (Express
req
, Next.js
Request
, FastAPI
Request
, etc.)
No HTTP request (tool calls, MCP handlers, queue workers, background jobs, agent loops)
JS/TS SDK
@arcjet/next
,
@arcjet/node
,
@arcjet/fastify
, etc.
@arcjet/guard
Python SDK
arcjet
(with
arcjet()
/
arcjet_sync()
)
arcjet
(with
launch_arcjet()
/
launch_arcjet_sync()
)
Go SDK
github.com/arcjet/arcjet-go
(with
NewClient
)
github.com/arcjet/arcjet-go
(with
NewGuardClient
)
Entry point
protect(request)
/
Protect(ctx, r)
guard(label, rules)
/
Guard(ctx, request)
A single project can use both — e.g. request-based on API routes and guard on agent tool calls.
Common misclassifications to watch for:
  • MCP servers: the word "server" is misleading. MCP tools don't receive HTTP requests — they're invoked by an MCP client over stdio or SSE. Use Guard, not request-based.
  • Background jobs / queue consumers: no HTTP request at the protection site. Use Guard.
  • Server actions / RPC over HTTP (Next.js server actions, tRPC, etc.): there is an HTTP request underneath. Use request-based.
  • Agent tool calls inside a request handler: if you want to limit per-user-per-route, request-based is fine. If you want per-tool budgets independent of any HTTP boundary, use Guard at the tool call site.
Read the appropriate reference:
  • Request-based JS/TS: references/requests_javascript.md
  • Request-based Python: references/requests_python.md
  • Request-based Go: references/requests_go.md
  • Guard JS/TS: references/guards_javascript.md
  • Guard Python: references/guards_python.md
  • Guard Go: references/guards_go.md
These references explain architectural decisions and patterns that can't be inferred from the source code alone. For exact API signatures, read the installed package's types and doc comments.
确定适用的防护类型:
基于请求的防护Guard防护
适用场景代码包含HTTP请求对象(Express
req
、Next.js
Request
、FastAPI
Request
等)
无HTTP请求(工具调用、MCP处理器、队列工作器、后台任务、Agent循环)
JS/TS SDK
@arcjet/next
@arcjet/node
@arcjet/fastify
@arcjet/guard
Python SDK
arcjet
(搭配
arcjet()
/
arcjet_sync()
arcjet
(搭配
launch_arcjet()
/
launch_arcjet_sync()
Go SDK
github.com/arcjet/arcjet-go
(搭配
NewClient
github.com/arcjet/arcjet-go
(搭配
NewGuardClient
入口方法
protect(request)
/
Protect(ctx, r)
guard(label, rules)
/
Guard(ctx, request)
单个项目可以同时使用两种防护——例如,API路由使用基于请求的防护,Agent工具调用使用Guard防护。
需要注意的常见误分类:
  • MCP服务器:“服务器”一词具有误导性。MCP工具不接收HTTP请求——它们由MCP客户端通过stdio或SSE调用。请使用Guard防护,而非基于请求的防护。
  • 后台任务/队列消费者:防护位置无HTTP请求。请使用Guard防护
  • 服务器操作/基于HTTP的RPC(Next.js服务器操作、tRPC等):底层存在HTTP请求。请使用基于请求的防护
  • 请求处理器内的Agent工具调用:如果要按用户按路由限制,基于请求的防护即可。如果要实现独立于任何HTTP边界的按工具预算限制,请在工具调用位置使用Guard防护。
阅读对应的参考文档:
  • 基于请求的JS/TSreferences/requests_javascript.md
  • 基于请求的Pythonreferences/requests_python.md
  • 基于请求的Goreferences/requests_go.md
  • Guard JS/TSreferences/guards_javascript.md
  • Guard Pythonreferences/guards_python.md
  • Guard Goreferences/guards_go.md
这些参考文档说明了无法从源代码中推断的架构决策和模式。有关确切的API签名,请阅读已安装包的类型和文档注释。

Step 4: Implement Protection

步骤4:实现防护

Follow the patterns in the reference file from Step 3. Key principles:
遵循步骤3中参考文档的模式。核心原则:

Request-based (HTTP routes):

基于请求的防护(HTTP路由):

  • Create shared clients outside handlers and include Shield as a base rule. Use the exact constructor and rule names from the language reference.
  • In JavaScript/TypeScript, use
    withRule()
    for route-specific rules and
    decision.isDenied()
    for the result.
  • In Python, pass the complete rule list to
    arcjet()
    /
    arcjet_sync()
    ; there is no
    with_rule()
    client method. Check
    decision.is_denied()
    .
  • In Go, create one
    NewClient
    at package scope.
    WithRule()
    derives route-specific clients and returns
    (*Client, error)
    , so handle initialization errors. Check
    decision.IsDenied()
    .
  • Call
    protect()
    /
    Protect()
    inside each route handler (not in app-level middleware), once per request.
  • Map denial reasons to HTTP responses. Only branch on reasons that produce a different response — there is no point in a Shield-specific arm that returns the same status as the default 403.
  • Put the language's
    userId
    characteristic selector on the specific rule that needs it, then pass a trusted, authenticated user ID at protection time. Never rate limit by a client-controlled header unless a trusted proxy strips and rewrites it.
  • 在处理器外部创建共享客户端,并将Shield作为基础规则。使用语言参考中确切的构造函数和规则名称。
  • 在JavaScript/TypeScript中,使用
    withRule()
    添加路由特定规则,并使用
    decision.isDenied()
    判断结果。
  • 在Python中,将完整的规则列表传递给
    arcjet()
    /
    arcjet_sync()
    ;不存在
    with_rule()
    客户端方法。请检查
    decision.is_denied()
  • 在Go中,在包级别创建一个
    NewClient
    WithRule()
    派生路由特定客户端并返回
    (*Client, error)
    ,因此需要处理初始化错误。请检查
    decision.IsDenied()
  • 在每个路由处理器内部调用
    protect()
    /
    Protect()
    (不要在应用级中间件中调用),每个请求调用一次。
  • 将拒绝原因映射到HTTP响应。仅对会产生不同响应的原因进行分支处理——如果Shield特定分支返回的状态码与默认403相同,则没有意义。
  • 将语言的
    userId
    特征选择器添加到需要它的特定规则中,然后在防护时传递可信的、已认证的用户ID。除非可信代理会剥离并重写客户端控制的标头,否则绝不要按此类标头进行速率限制。

Guard (non-HTTP code):

Guard防护(非HTTP代码):

  • Client at module scope with
    launchArcjet()
    (JS) or
    launch_arcjet()
    /
    launch_arcjet_sync()
    (Python — pick async vs sync to match the function you're protecting).
  • In Go, create one
    NewGuardClient
    at package scope.
  • Rules declared at module scope. Give each rule a meaningful
    label
    so they show up usefully in the Console.
  • One
    guard()
    call per specific operation, with a hardcoded
    label
    like
    "tools.get-weather"
    or
    "queue.summarize"
    . Put it wherever you already know exactly what's happening — that can be inside the tool/task function itself, or right before calling it from a dispatch arm. Both work; pick whichever makes error propagation cleaner. What to avoid is the generic-dispatcher pattern (
    handleToolCall(name, args)
    calling
    guard(label=f"tools.{name}")
    ) — interpolated labels break grep and produce messy Console groupings.
  • Label naming rules: labels are validated server-side as slugs — lowercase letters, digits, dash (
    -
    ), and dot (
    .
    ) only
    , must start and end with a letter or digit, max 256 bytes. Underscores, uppercase, and slashes are rejected even though some SDK TSDoc comments claim otherwise. Use
    tools.get-weather
    , not
    tools.get_weather
    or
    Tools.GetWeather
    .
  • Pass
    metadata
    on the
    guard()
    call
    when you have useful auditing context (
    metadata={"user_id": user_id, "request_id": ...}
    ). It appears in the Console alongside the decision.
  • Branch on which rule denied, not just on
    DENY
    . Use the per-rule accessors (e.g.
    userLimit.deniedResult(decision)
    for retry-after info) or the flat reason string (
    decision.reason === "PROMPT_INJECTION"
    in JS,
    decision.reason == "PROMPT_INJECTION"
    in Python) so the error you surface to the caller tells them why — "rate limited, retry in 12s" vs "input flagged as prompt injection" — instead of a generic "blocked." Note: guard's
    decision.reason
    is a flat string literal, unlike the request-based SDK's tagged-helper API.
  • Every rate-limit rule needs a
    key
    and a
    bucket
    :
    • Per-user context (agent tool calls inside a logged-in session, queue jobs with a
      user_id
      ): use the user/session id as the key.
    • No user context (stdio MCP server, single-tenant worker): use a stable identifier you control — instance id, deployment name, or a literal like
      "default"
      . Just be explicit.
  • Check
    decision.conclusion === "DENY"
    (JS),
    decision.conclusion == "DENY"
    (Python), or
    decision.IsDenied()
    /
    decision.Conclusion == arcjet.ConclusionDeny
    (Go) before proceeding.
  • 在模块级别使用
    launchArcjet()
    (JS)或
    launch_arcjet()
    /
    launch_arcjet_sync()
    (Python——根据要防护的函数选择异步或同步版本)创建客户端。
  • 在Go中,在包级别创建一个
    NewGuardClient
  • 在模块级别声明规则。为每个规则赋予有意义的
    label
    ,以便在控制台中清晰显示。
  • 每个特定操作调用一次
    guard()
    ,并使用硬编码的
    label
    ,例如
    "tools.get-weather"
    "queue.summarize"
    。将其放置在你确切知道操作内容的位置——可以在工具/任务函数内部,也可以在从调度分支调用它之前。两种方式都可行;选择错误传播更清晰的方式。要避免的是通用调度器模式(
    handleToolCall(name, args)
    调用
    guard(label=f"tools.{name}")
    )——插值标签会破坏grep功能,并在控制台中产生混乱的分组。
  • 标签命名规则:标签在服务器端会被验证为slug——仅允许小写字母、数字、连字符(
    -
    )和点号(
    .
    )
    ,必须以字母或数字开头和结尾,最大长度为256字节。即使某些SDK的TSDoc注释声称允许,下划线、大写字母和斜杠也会被拒绝。请使用
    tools.get-weather
    ,而非
    tools.get_weather
    Tools.GetWeather
  • guard()
    调用中传递
    metadata
    (当你有有用的审计上下文时,例如
    metadata={"user_id": user_id, "request_id": ...}
    )。它会与决策一起显示在控制台中。
  • 根据哪个规则被拒绝进行分支处理,而不仅仅是
    DENY
    。使用每个规则的访问器(例如,
    userLimit.deniedResult(decision)
    获取重试信息)或扁平的原因字符串(JS中
    decision.reason === "PROMPT_INJECTION"
    ,Python中
    decision.reason == "PROMPT_INJECTION"
    ),以便向调用者显示错误的原因——例如“速率限制,12秒后重试” vs “输入被标记为提示注入”——而非通用的“已拦截”。注意:Guard的
    decision.reason
    是扁平的字符串字面量,与基于请求的SDK的标记辅助API不同。
  • 每个速率限制规则都需要
    key
    bucket
    • 按用户上下文(登录会话内的Agent工具调用、带有
      user_id
      的队列任务):使用用户/会话ID作为key。
    • 无用户上下文(stdio MCP服务器、单租户工作器):使用你控制的稳定标识符——实例ID、部署名称或文字值如
      "default"
      。请明确指定。
  • 在继续操作前检查
    decision.conclusion === "DENY"
    (JS)、
    decision.conclusion == "DENY"
    (Python)或
    decision.IsDenied()
    /
    decision.Conclusion == arcjet.ConclusionDeny
    (Go)。

Conventions outside the Arcjet flow

Arcjet流程之外的约定

For everything that isn't an Arcjet-specific decision — dev scripts, file/module layout, named-vs-default exports, comment style, env-file naming, type hints, error class patterns — match the project's existing conventions. If the project has no convention yet, default to modern best practice for the language. This skill is opinionated about where Arcjet goes and how its API is used; it shouldn't reach further than that.
对于所有Arcjet特定的决策——开发脚本、文件/模块布局、命名导出vs默认导出、注释风格、环境文件命名、类型提示、错误类模式——请遵循项目已有的约定。如果项目尚无约定,则默认采用该语言的现代最佳实践。此技能对Arcjet的放置位置其API的使用方式有明确要求;不应超出此范围。

Step 5: Verify Decisions

步骤5:验证决策

After wiring up protection, confirm it's actually firing. Three steps:
1. Type-check / build first. Run
tsc
,
next build
,
python -m py_compile
, or whatever check command the project uses. Catches wrong imports, wrong rule names, and stale type signatures before the user does.
2. Trigger a real call so a decision exists to check. Without one, the Console and CLI are empty and you can't tell whether protection is actually wired up.
  • Request-based: start the dev server (
    npm run dev
    ,
    uvicorn main:app --reload
    , etc.) and
    curl
    the protected route. To trip a rate limit, loop the call:
    for i in {1..50}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/api/your-route; done
    — you should see a mix of 200s and 429s once the limit is hit.
  • Guard: invoke the protected function directly. A tiny script that imports the tool/task function and calls it twice (once to allow, once to exceed the limit) is usually the fastest path — e.g.
    node -e "import('./src/tools.js').then(m => m.getWeather('SF', 'user_123'))"
    or
    python -c "from worker import process_job; process_job({'user_id': 'user_123'})"
    . For MCP servers, send a tool call via the MCP client / inspector. For queue workers, enqueue a real job. Don't try to test guard by
    curl
    ing anything — there's no HTTP surface.
3. Confirm the decision in the Arcjet platform.
  • CLI:
    npx -y @arcjet/cli@latest requests list --site-id <id>
    (request-based) or
    ... guards list --site-id <id>
    (Guard)
  • MCP:
    list-requests
    /
    list-guards
  • Console: https://app.arcjet.com
For deeper investigation:
arcjet requests explain --site-id <id> --request-id <id>
or
arcjet guards explain --site-id <id> --guard-id <id>
.
If you can't run the app in the current environment, tell the user exactly what to do (which command to run, what to look for in the output) instead of silently skipping verification.
配置好防护后,确认它实际触发。分为三个步骤:
1. 先进行类型检查/构建。运行
tsc
next build
python -m py_compile
或项目使用的任何检查命令。在用户发现之前捕获错误的导入、错误的规则名称和过时的类型签名。
2. 发起真实调用以生成可检查的决策。没有决策的话,控制台和CLI为空,无法判断防护是否已正确配置。
  • 基于请求的防护:启动开发服务器(
    npm run dev
    uvicorn main:app --reload
    等),并使用
    curl
    调用受保护的路由。要触发速率限制,循环调用:
    for i in {1..50}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/api/your-route; done
    ——当达到限制时,你应该会看到200和429状态码混合出现。
  • Guard防护:直接调用受保护的函数。一个导入工具/任务函数并调用两次(一次允许,一次超出限制)的小脚本通常是最快的方式——例如
    node -e "import('./src/tools.js').then(m => m.getWeather('SF', 'user_123'))"
    python -c "from worker import process_job; process_job({'user_id': 'user_123'})"
    。对于MCP服务器,通过MCP客户端/检查器发送工具调用。对于队列工作器,入队一个真实任务。不要尝试通过
    curl
    测试Guard防护——它没有HTTP接口。
3. 在Arcjet平台中确认决策
  • CLI
    npx -y @arcjet/cli@latest requests list --site-id <id>
    (基于请求的防护)或
    ... guards list --site-id <id>
    (Guard防护)
  • MCP
    list-requests
    /
    list-guards
  • 控制台https://app.arcjet.com
如需深入调查:
arcjet requests explain --site-id <id> --request-id <id>
arcjet guards explain --site-id <id> --guard-id <id>
如果无法在当前环境中运行应用,请明确告知用户要执行的操作(运行哪个命令,在输出中查找什么内容),而非跳过验证。

Gotchas

常见陷阱

  • Wrong SDK/client:
    @arcjet/guard
    ,
    arcjet.guard
    , and Go's
    NewGuardClient
    are for non-HTTP code.
    @arcjet/node
    /
    @arcjet/next
    / Python
    arcjet()
    / Go
    NewClient
    are for HTTP routes. Using the wrong one is the most common mistake.
  • Wrong placement:
    protect()
    must not be called in Express middleware or Next.js middleware. Call it inside each route handler.
  • Wrong layer for
    guard()
    : don't put
    guard()
    in a
    handleToolCall(name, args)
    dispatcher — put it inside each specific tool / task function so the
    label
    and metadata can be hardcoded.
  • Hand-edited dependency manifests: don't append
    "arcjet": "^1.0.0"
    to
    package.json
    or
    arcjet>=1.0.0
    to
    requirements.txt
    . Run the project's package manager so the version is real and the lockfile updates.
  • Double-counting: Calling
    protect()
    or
    guard()
    multiple times for the same operation counts against rate limits multiple times.
  • Never hardcode
    ARCJET_KEY
    — always use environment variables.
  • 错误的SDK/客户端
    @arcjet/guard
    arcjet.guard
    和Go的
    NewGuardClient
    用于非HTTP代码。
    @arcjet/node
    /
    @arcjet/next
    / Python
    arcjet()
    / Go
    NewClient
    用于HTTP路由。使用错误的客户端是最常见的错误。
  • 错误的放置位置
    protect()
    不得在Express中间件或Next.js中间件中调用。请在每个路由处理器内部调用。
  • 错误的
    guard()
    层级
    :不要在
    handleToolCall(name, args)
    调度器中放置
    guard()
    ——请将其放在每个特定的工具/任务函数内部,以便硬编码
    label
    和元数据。
  • 手动编辑依赖清单:不要在
    package.json
    中追加
    "arcjet": "^1.0.0"
    或在
    requirements.txt
    中追加
    arcjet>=1.0.0
    。运行项目的包管理器以获取真实版本并更新锁文件。
  • 重复计数:对同一操作多次调用
    protect()
    guard()
    会多次消耗速率限制额度。
  • 绝不要硬编码
    ARCJET_KEY
    ——始终使用环境变量。

Choosing Protections

选择防护类型

When you need to pick which rules address the user's concern — bot abuse, rate limits, prompt injection, signup spam, PII, IP filtering, etc. — load references/choosing_protections.md. It maps common problems to Arcjet rules and explains the tradeoffs between strategies (e.g. token bucket vs sliding window). The mapping doesn't need to be in your context for the rest of the workflow.
当你需要选择哪些规则来解决用户的问题——机器人滥用、速率限制、提示注入、注册垃圾信息、PII、IP过滤等——请查看references/choosing_protections.md。它将常见问题映射到Arcjet规则,并解释不同策略之间的权衡(例如令牌桶vs滑动窗口)。此映射无需在后续工作流程中保留在你的上下文里。

Resources

资源

For exact API signatures, parameter names, and the full set of rules and helpers, read the installed SDK's source — types and docstrings are the source of truth:
有关确切的API签名、参数名称以及完整的规则和助手列表,请阅读已安装SDK的源代码——类型和文档字符串是权威来源: