关于 cloudpin
cloudpin 是命令行防护工具,可检查云命令是否作用于项目 .cloudpin.yml 中固定的账户和项目。它面向使用多个云身份的团队和编码 Agent,在命令执行前拦截目标不匹配或无法确认的操作。
主要功能
- 01在 .cloudpin.yml 中固定账户
- 02执行前检查命令目标
- 03拦截目标不匹配或未知的命令
- 04支持受保护环境
- 05防护终端和编码 Agent
- 06通过 MCP 进行只读账户检查
适用场景
- 01防止部署到错误账户
- 02防护 Agent 执行的云命令
- 03区分暂存与生产环境的固定配置
- 04在 CI 部署前检查账户目标
MCP 相关
cloudpin 包含供 Agent 使用的 MCP 服务,可针对项目固定的云账户执行只读检查。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
2收录的工具列表 · 更新于 1 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cwd | string | 否 | 项目文件夹;默认为当前文件夹。 |
详细介绍

cloudpin
将云账户固定到项目,并阻止任何会在错误账户上运行的命令(无论是你运行的,还是 AI Agent 运行的)。
az、aws、gcloud、vercel、gh、kubectl、helm、supabase 和 wrangler 会使用你上次使用的账户、集群或项目。在同一台机器上同时使用工作账户、个人账户和一两个客户账户,迟早会把内容部署到错误的位置,或从错误的位置删除内容。编码 Agent 会让这种情况更容易发生:它们会替你运行这些命令,却从不询问当前使用的是哪个账户。cloudpin 会在命令运行前进行检查。
安装
pnpm add --global cloudpin
在 macOS 和 Linux 上,也可以使用 Homebrew,从 paureis/homebrew-tap 安装(它使用 Homebrew 自带的 Node.js;若尚未安装,会先安装):
brew install paureis/tap/cloudpin
在 Windows 上,也可以使用 Scoop,从 paureis/scoop-bucket 安装。
如有需要,它会安装 Scoop 自带的 Node.js(nodejs-lts),cloudpin 始终使用该版本运行。全局安装(scoop install -g)也需要全局安装 nodejs-lts。nodejs-lts 会将其文件夹放在用户 PATH 的最前面,因此在新 shell 中,node 和 npm 会使用 Scoop 的版本(npm install --global 也会安装到该位置),优先于用户 PATH 中的其他 Node.js;但系统 PATH 中的版本(由 nodejs.org 安装程序放置)仍会排在最前面。卸载 nodejs-lts 后,cloudpin 将无法运行,直到你再次运行 scoop install nodejs-lts;此外,不支持 Scoop 的 no_junction 设置。
scoop bucket add paureis https://github.com/paureis/scoop-bucket
scoop install paureis/cloudpin
npm、Yarn、Bun,或无需安装
npm install --global cloudpin
yarn global add cloudpin
bun add --global cloudpin
# try it without installing
npx cloudpin --help
需要 Node.js 22 或更高版本。支持 Windows、macOS 和 Linux。.cloudpin.yml 格式从 1.0 版起保持稳定(参见配置),也非常欢迎你提供反馈。
最新版本:1.2.1(2026-10-29):Agent hook 现在可以找到隐藏在 $( ) 中的 heredoc、运行时值、PowerShell 语法以及 xargs、sudo、npx 或 cmd /c 等包装器中的调用,gcloud 也会检查模拟身份的账户;请升级。1.2.0(2026-10-29)实现了随处运行。GitHub Action
(paureis/cloudpin-action)会在部署任务前检查账户,基于新增的 cloudpin check --only 和 --json;支持 Homebrew 和 Scoop 安装;为每个 Agent 提供的 MCP 服务,已列入官方 MCP Registry(文档);Codex 和 Copilot CLI hook 可绕过 PowerShell 执行策略在 Windows 上的限制;并修复了命令使用的 Vercel 团队和 Wrangler 账户相关问题。请参阅更新日志。1.1 版新增 Claude Code 插件,1.0 版则确定了 .cloudpin.yml 格式。
快速开始
cd your-project
cloudpin init # pin the accounts you are logged into now
cloudpin install-hook claude # protect your AI agent (or codex, cursor, copilot, antigravity, gemini)
echo 'eval "$(cloudpin shell-init bash)"' >> ~/.bashrc # protect your terminal
将 .cloudpin.yml 提交到项目中,让所有人都受到相同的保护。cloudpin status 会显示每个 CLI 的当前账号,以及配置中固定的账号。若要在不冒任何风险的情况下查看拦截效果,可以在临时文件夹中固定一个错误的账号(编辑 .cloudpin.yml 中的 ID),然后运行只读命令,例如 gh repo list。
若要撤销所有更改:运行 cloudpin uninstall-hook claude,从配置文件中移除 shell-init 行,并删除 .cloudpin.yml。除此之外,cloudpin 只会写入以下内容:用户缓存文件夹中的短期身份缓存、运行 cloudpin use 后生成的 .git/cloudpin-env,以及它编辑过的 Agent 设置文件旁的 *.cloudpin-backup 副本。
用法
# Write .cloudpin.yml from the accounts you are logged into now
cloudpin init
# ...or add them as one environment of the file (see Environments)
cloudpin init --env production --protected
# Show the environments, or choose the one to use in this clone
cloudpin use [<env> | --clear]
# Check every pinned account; exit 1 on a mismatch (handy in CI and scripts)
cloudpin check
# Check only these clouds; each must be pinned, installed and logged in to the pinned
# account, so a CLI missing on the runner fails, not skipped. --json prints an overall "result" (match,
# mismatch, unpinned or error) and each cloud's status, reason and fix. Exit codes stay the same.
cloudpin check --only azure,aws [--json]
# See each CLI's active account, what this folder pins, and which agent hooks are installed (--json for tools)
cloudpin status
# Why was a command blocked, or would it be? See the pin, the account it would use, and the verdict, without
# running it. One quoted argument is read as a full line; --agent shows what an agent hook decides; --json for tools.
cloudpin explain -- vercel deploy --prod
cloudpin explain "cd ../web && vercel deploy"
# Something looks off? Check the whole setup and get the fix for each problem; exit 1 if anything fails.
# --json shortens account IDs and hides your home folder, so it is safe to paste in a bug report.
cloudpin doctor [--json]
# Run one command only if it would act on the pinned account; exit 3 if blocked
cloudpin exec -- vercel deploy --prod
# Shell functions that route az, aws, gcloud, vercel, gh, kubectl, helm, supabase and wrangler through cloudpin
cloudpin shell-init bash|zsh|pwsh
# Add or remove the hook in an agent's settings (this project, or yours with --user)
cloudpin install-hook <agent> [--user]
cloudpin uninstall-hook <agent> [--user]
工作原理
项目中的 .cloudpin.yml 列出了项目所用的账号。cloudpin init 会为你创建该文件,并以注释形式写入易读的名称:
azure:
subscription: "3f2a0000-0000-0000-0000-000000000c91" # Acme Prod
tenant: "8b1d0000-0000-0000-0000-00000000044e"
aws:
account: "123456789012"
gcloud:
account: "[email protected]"
project: "acme-prod"
vercel:
team: "team_x9KqZr" # acme
github:
user: "acme-bot"
kubernetes:
server: "https://acme-prod.hcp.westeurope.azmk8s.io:443" # acme-prod-admin
namespace: "payments"
supabase:
project: "abcdefghijklmnopqrst" # Acme prod
org: "acme"
cloudflare:
account: "0123456789abcdef0123456789abcdef" # Acme
在受保护的命令运行前,cloudpin 会确定该命令将使用哪个账号(向 CLI 查询,或读取 Kubernetes 的 kubeconfig),同时考虑命令自身的标志和环境变量,然后将结果与文件中的配置进行比较:
| CLI | 固定的内容 | cloudpin 会考虑的因素 |
|---|---|---|
az | 订阅 ID、租户 ID | --subscription、AZURE_CONFIG_DIR |
aws | 账号 ID | --profile、AWS_PROFILE、访问密钥变量、SSO |
gcloud | 账号、项目 | --account、--project、--configuration、--impersonate-service-account、--access-token-file、CLOUDSDK_* |
vercel / vc | 团队 ID | --scope、--team、--token、VERCEL_TOKEN、VERCEL_ORG_ID、已关联的项目(.vercel/project.json 或仓库的 .vercel/repo.json) |
gh | 用户、主机 | --hostname、GH_HOST、GH_TOKEN、GITHUB_TOKEN |
supabase | 项目引用、组织(可选) | --project-ref、SUPABASE_PROJECT_ID、项目保存的 supabase link、--workdir、SUPABASE_WORKDIR、--profile、SUPABASE_ACCESS_TOKEN |
wrangler(Cloudflare) | 账号 ID | wrangler.json、wrangler.jsonc 或 wrangler.toml 中的 account_id(以及配合 --env / CLOUDFLARE_ENV 使用的 [env.NAME])、--config、--cwd、CLOUDFLARE_ACCOUNT_ID、项目的账号缓存、凭据中唯一的账号 |
kubectl、helm | API 服务器 URL、命名空间(可选) | --kubeconfig、KUBECONFIG、--context、--cluster、--server、-n、-A、kuberc;helm 的 --kube-context、--kube-apiserver、HELM_* |
对于 Kubernetes,固定的是服务器 URL,而不是上下文名称,因为上下文名称因人而异:同一个集群在一台笔记本上叫 prod,在另一台上则叫 acme-prod-admin。init 会将你的上下文名称写为注释,且只有在你的上下文设置了命名空间时才会固定该命名空间。固定了命名空间后,使用 -A / --all-namespaces 就会不匹配。不会连接集群的命令(kubectl config、kubectl kustomize、helm template、helm repo 等)永远不会被拦截,独立的 kustomize 也完全不受保护。cloudpin 无法查看你所应用清单文件中写入的 namespace:,因此如果你在意这一点,请固定命名空间,并确保清单文件中不指定命名空间。
对于 gcloud,如果使用了模拟服务账号(委派链中的最后一个账号),则会将该账号与固定配置进行比较;如果使用访问令牌或令牌文件,则无法获知账号,因此固定账号时会显示“无法判断”。
对于 Supabase,项目引用的确定方式与 CLI 相同,且不会发起网络调用:先检查 --project-ref,再检查 SUPABASE_PROJECT_ID,然后检查项目保存在 supabase/.temp/ 中的 supabase link。已关联的分支会视为其父项目。组织信息来自 supabase projects list。本地堆栈(start、stop、status、functions serve,以及不带 --linked 的 db reset、db diff 或 migration up)永远不会被拦截。如果 --db-url 指向你自己的机器以外的位置,则会被阻止,因为 cloudpin 无法判断该 URL 属于哪个项目。
对于 Cloudflare,cloudpin 遵循 Wrangler 自身的查找顺序:先查 Wrangler 会读取的配置文件中的 account_id(优先于 CLOUDFLARE_ACCOUNT_ID),然后查该变量,再查 Wrangler 缓存的账户,最后查凭据可访问的唯一账户(wrangler whoami --json)。如果检测到多个账户且未指定账户,Wrangler 会提示选择或报错,因此 cloudpin 会停止命令。Wrangler 从项目的 .env 文件加载的变量也会计入。不会拦截本地命令(dev,以及未带 --remote 的 d1、kv key 或 r2 object);带有 remote: true 绑定的 dev 会访问你的账户,因此不会检查。此功能根据 Wrangler 的源代码和文档构建,尚未在真实的 Cloudflare 登录环境中测试;欢迎反馈。
- **匹配:**命令的执行效果与未使用 cloudpin 时相同。
- **不匹配:**命令会被停止,并告知当前使用的账户以及切换方式。
- 无法判断(登录已过期、令牌失效或网络不可用):命令也会被停止,cloudpin 会明确说明原因,提供 CLI 自身的错误信息以及用于检查问题的命令。
登录、登出、切换账户、--help 和 --version 从不受阻止(如果 CLI 仍会执行命令,例如 vercel deploy -v,则会检查该命令)。不含 .cloudpin.yml 的文件夹不受影响。Monorepo 也能正常工作:当前文件夹上方最近的 .cloudpin.yml 优先。
环境
一个文件可以分别固定暂存环境和生产环境。将某个环境标记为 protected 后,即使账户正确,任何可能更改内容的命令也会先询问:
environments:
staging:
vercel: { team: "team_staging" }
aws: { account: "111111111111" }
production:
protected: true
vercel: { team: "team_prod" }
aws: { account: "222222222222" }
branches: # optional: which environment a git branch uses
main: production
"release/*": production
"*": staging
read_only: # optional: more commands that never need confirmation
azure: ["webapp log tail"]
适用的环境按以下顺序确定,以首个匹配项为准:
- 环境中的
CLOUDPIN_ENV=<name>。 cloudpin use <name>:此设置会保存在此克隆的.git目录中,因此不会被提交。- 已检出的分支对应的
branches映射,或CLOUDPIN_BRANCH=<name>: 先匹配完全相同的名称,再匹配第一个符合条件的模式。 - 列出的第一个环境。
未知名称会报错,因此命令会被停止,而不会依据错误的固定配置进行检查。cloudpin status 和每条消息都会说明适用的环境及原因。
在受保护的环境中,只读命令照常运行。其他所有命令都会先询问:
- 在终端中:
Continue? [y/N]。 - 没有终端时(CI、脚本):除非设置了
CLOUDPIN_CONFIRM=<name>,否则命令会停止。 - Claude Code、Copilot CLI、Antigravity 和 Cursor 会通过 Agent 自带的提示词向你询问。Codex 和 Gemini CLI 的钩子中没有可用的“询问”功能,因此命令会被阻止,并提示 Agent 将其交给你处理。
内置只读命令列表特意设得较短(az ... list|show、aws <service> describe-*|list-*|get-* 和 s3 ls、gcloud ... list|describe、vercel ls|inspect|logs 和 <group> ls、gh <group> list|view|status、kubectl get|describe|logs|top|explain、helm list|status|history|get),因此任何无法识别的命令都会询问。read_only 可以添加命令,按其开头的词语匹配,但无法移除任何命令。账户不匹配时,命令仍会被直接阻止,不受是否受保护的影响。
**从扁平格式升级:**无需任何操作;不含 environments 的文件仍会与之前完全一样地工作。若要拆分配置,请将提供商配置部分移到 environments: 下的某个名称之下,或者使用 cloudpin init --env <name> 新建文件,并在切换账户后针对每个环境重新运行。
保护你的终端
在 shell 配置文件中添加一行。删除该行即可卸载。
eval "$(cloudpin shell-init bash)" # ~/.bashrc
eval "$(cloudpin shell-init zsh)" # ~/.zshrc
cloudpin shell-init pwsh | Out-String | Invoke-Expression # $PROFILE
如果 cloudpin 被卸载,函数会回退到实际的 CLI,因此绝不会妨碍你。若想有意地运行某条命令:CLOUDPIN_SKIP=1 <command>。
别名。 调用 CLI 本身的别名仍会受到保护,例如 alias kubectl='kubectl --context dev'。运行其他程序的别名则会绕过 cloudpin,例如 alias kubectl=kubecolor 或 alias gh='command gh',因此每个新 shell 都会打印一条指出该别名的警告(bash 4+、zsh 和 PowerShell;PowerShell 会先运行任何别名,再运行包装器)。将 cloudpin shell-init 这一行放在别名之后,这样它才能检测到这些别名。
保护你的 AI Agent
cloudpin install-hook claude
此钩子会写入项目的 Agent 设置(个人设置请使用 --user)。cloudpin 会在写入前显示文件内容、保留备份,而 uninstall-hook 只会移除它自己的条目。当命令被拦截时,Agent 会收到原因说明,并被要求向你确认。Agent 不能使用 CLOUDPIN_SKIP 或 CLOUDPIN_CONFIRM,不能在自己的命令中通过设置 CLOUDPIN_ENV 选择环境,运行 cloudpin use 也需要你批准。
| Agent | 设置文件 | 状态 |
|---|---|---|
| Claude Code | .claude/settings.json | 已在 Agent 内测试 |
| Codex | .codex/hooks.json | 已在 Agent 内测试 |
| Cursor | .cursor/hooks.json | 已在 Agent 内测试(Cursor CLI) |
| GitHub Copilot CLI | .github/hooks/cloudpin.json | 已在 Agent 内测试 |
| Antigravity (CLI, IDE and 2.0) | .agents/hooks.json | 已在 Antigravity CLI 内测试 |
| Gemini CLI | .gemini/settings.json | 按照文档中的钩子格式构建 |
Google 于 2026-06-18 用 Antigravity CLI 替代了免费和个人账户的 Gemini CLI;Gemini CLI 仍服务于付费 API 密钥和企业许可证,因此两者均受支持。
cloudpin 会读取 Agent 即将运行的完整命令行,因此也能检测到
cd ../other && npx vercel deploy、bash -c "..."、管道、$( )、xargs、find -exec、传给 shell 的 heredoc(bash <<EOF)、保存在变量中的命令(CLI=vercel; $CLI deploy)以及 PowerShell 赋值($prs = gh pr list)。在该行前面设置的变量也会纳入检查(export AWS_PROFILE=other; aws ...、$env:AWS_PROFILE = 'other');如果决定账户的变量取值来自只有运行时才知道的内容(GH_TOKEN=$(cat file) gh ...),命令会被拦截并说明原因。但它无法检查 Agent 写入并在之后运行的脚本文件内部(bash deploy.sh)。
在 Windows 上,Codex 和 Copilot CLI 通过 PowerShell 运行钩子,而 PowerShell 的 Restricted 和 AllSigned 执行策略会阻止 npm 的 cloudpin.ps1。因此,对这两个 Agent,install-hook 还会在仅适用于 Windows 的字段中写入一条通过 cmd.exe 启动 cloudpin 的 Windows 命令(Codex 0.131.0 或更高版本)。1.2.0 之前安装的钩子不包含该字段:升级后重新运行 cloudpin install-hook <agent>(Codex 会在你于 /hooks 中审核更改后的钩子后运行它)。Gemini CLI 没有此类字段,因此其钩子需要使用允许运行本地脚本的执行策略,例如 RemoteSigned。cloudpin doctor 会针对这些情况、PATH 中的 . 或其他相对路径条目,以及早于 2.1.47 的 Claude Code 发出警告。
Claude Code 插件
安装一次即可为 Claude Code 添加钩子、两个可在执行操作前调用的只读工具,以及一段简短技能,告知它先进行检查,并在 cloudpin 拦截命令时停止并询问你。必须先安装 cloudpin:
npm install --global cloudpin
claude plugin install cloudpin --marketplace paureis/cloudpin
该插件会取代 cloudpin install-hook claude:启用插件后,install-hook claude 会拒绝执行;如果两者同时存在,cloudpin doctor 会发出警告(Claude Code 会同时运行两者)。
MCP 服务
cloudpin mcp 是适用于任何 Agent 的 MCP 服务(stdio);Claude Code 插件会为你启动它。它的两个工具 cloudpin_status 和 cloudpin_check 会报告正在使用的账号,以及某条命令是否会被允许。它们都不会运行、切换或更改任何内容:能够切换账号的 Agent 可能会切换到错误的账号。
docs/mcp.md 介绍了如何将它添加到 Codex、Cursor、VS Code 等。它提供建议,而非强制执行:如果 Agent 支持钩子,也要安装钩子。
配置
| 变量 | 作用 |
|---|---|
CLOUDPIN_SKIP=1 | 运行一条命令时跳过检查(仅限终端;对 Agent 无效) |
CLOUDPIN_ENV=<name> | 使用此环境(参见 Environments) |
CLOUDPIN_BRANCH=<name> | 像在 CI 中一样,为分支映射使用此分支;对 Agent 无效 |
CLOUDPIN_CONFIRM=<name> | 在此受保护环境中,无提示确认会更改内容的命令(仅限终端和 CI;对 Agent 无效) |
CLOUDPIN_NO_CACHE=1 | 始终询问 CLI,而不使用身份缓存 |
CLOUDPIN_CACHE_DIR | 身份缓存(以及上次更新检查时间)的存放位置 |
CLOUDPIN_NO_UPDATE_CHECK=1 | 不再向 npm 查询是否有更新版本的 cloudpin(NO_UPDATE_NOTIFIER 也可用) |
向 CLI 查询当前身份需要 0.5 到 2 秒,因此 cloudpin 会记住成功的查询结果,最长五分钟。
一旦任何会影响账号判定的内容发生变化,缓存就会立即失效:命令标志、相关环境变量或 CLI 自身的账号文件(az account set、gh auth switch 和
vercel switch 会重写这些文件)。cloudpin check 始终会向 CLI 查询。
从 1.0 版本开始,.cloudpin.yml 只会扩展:新版本可以添加配置段和键,但不会更改或删除它们。如果文件使用了当前 cloudpin 不认识的名称,程序会拒绝读取,而不是只读取一部分,因此像 azrue: 这样的拼写错误不会关闭保护。提示信息会指出你的版本,并建议更新,以防文件是用较新版本编写的。
| 退出代码 | 含义 |
|---|---|
0 | 正常 |
1 | 用法错误,或 check 发现问题 |
3 | 命令被阻止,或在受保护环境中未获确认 |
安全与隐私
cloudpin 只读取当前活动的账号,使用各 CLI 自带的身份命令(az account show、
aws sts get-caller-identity、gcloud config list、vercel teams ls、gh api user)。它绝不会登录或
切换账号,不会读取 kubeconfig 之外的凭据文件(且只从中获取服务器和命名空间),也不会读取 Wrangler 加载的
.env 文件之外的文件(且只获取账号变量),并且绝不会打印或存储令牌:错误消息会提及 GH_TOKEN 之类的变量,
但绝不会显示其值;缓存只存储敏感信息的加盐哈希。它会直接运行 CLI,而不会通过 shell 运行。cloudpin 没有遥测功能,
不会发送任何关于你或你账号的信息;上面的身份命令只会与各自的服务提供商通信,就像你亲自运行它们一样。cloudpin 自己发出的唯一请求是向
registry.npmjs.org 查询最新的 cloudpin 版本,最多每天一次,且仅在你于终端中运行 cloudpin 命令时发出
(绝不会通过 shell 包装器、exec 或 Agent 钩子发出),以便告知你有可用更新。设置
CLOUDPIN_NO_UPDATE_CHECK=1 或 NO_UPDATE_NOTIFIER=1 可关闭此功能;在 CI 中默认关闭。报告问题请参阅 SECURITY.md。
常见问题
它会拖慢我的命令吗? 在未固定项目中,耗时不超过 Node 启动所需的时间(约 0.1 s)。 在已固定的项目中,首次检查会调用一次身份命令,之后的检查则使用缓存。
如果未安装某个 CLI,会怎样? 未安装的已固定 CLI 会被跳过;反正该命令也无法运行。
cloudpin check --only 是例外:它要求列出的每个云平台都已安装。
我可以在 CI 中使用它吗? 可以。在 GitHub Actions 上,将 paureis/cloudpin-action@v1
添加到作业的云平台登录步骤之后。在其他环境中,部署前运行 cloudpin check;如果任何已固定账号不匹配,该命令会以状态码 1 退出。
托管运行器通常预装了许多云 CLI,因此请使用
cloudpin check --only azure,aws 指定作业要部署到的云平台:此时每个平台都必须已安装,并且已登录到固定的账号。在拉取
请求或标签中没有分支;请设置 CLOUDPIN_BRANCH,例如设为 GITHUB_HEAD_REF,
这样 branches 才能选择正确的环境。
为什么无法判断时要阻止操作? 因为“可能是正确的账号”正是 cloudpin 要防止的情况。 提示消息会明确告知你它无法判断的原因。
路线图
ROADMAP.md 中列出了想法和后续计划。欢迎通过 issues 提出建议。
开发
贡献者命令
git clone https://github.com/paureis/cloudpin.git
cd cloudpin
npm ci
npm run build
npm test
| 命令 | 说明 |
|---|---|
npm run build | 编译到 dist/ |
npm test | 运行测试套件 |
npm run typecheck | 执行类型检查,不生成输出 |
node scripts/smoke.mjs | 检查各云服务提供商是否能通过你机器上已登录的 CLI 正常工作(构建后运行) |
node scripts/demo.mjs | 重新生成 assets/demo.svg(构建后运行) |
设计决策及其原因见 DESIGN.md。提交拉取请求前,请参阅 CONTRIBUTING.md。
关于
由 Alvaro Reis (LinkedIn) 制作,Claude Code 担任结对编程助手。每项行为都有测试覆盖,每项 CLI 集成都根据工具自身文档和实际 CLI 进行验证。项目缘起:云 CLI 在不告知你的情况下选错账号的 5 种方式。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。