关于 use-semantius
use-semantius 是通过 Semantius 官方 CLI 操作语义数据模型和业务数据的技能,面向使用命令行或 Agent 管理数据的场景。它按建模、单表记录操作和跨表分析划分工作层级。
主要功能
- 01管理实体、字段、关系与权限
- 02读写 PostgreSQL 业务记录
- 03跨表分析与指标查询
- 04CSV 检查及主机间迁移
适用场景
- 01创建或调整数据模型及访问规则
- 02查询或修改单表业务记录
- 03汇总多个表的数据并分析趋势
MCP 相关
该技能通过 `semantius` CLI 为 shell 和 Agent 提供对 `crud`、`cube` 与 `utils` 三个服务器的访问。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ semantius/ semantius-cli --skill use-semantius安装后在 Claude Code 中输入/use-semantius确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/cli-usage.mdcrud-tools.mdcube-queries.mdcube-tools.mddata-modeling.mdentity-families.mdjsonlogic.mdlucide-icon-checker.tslucide-icon-finder.tslucide-icon-tags.jsonrbac.mdselect-rule.mdvendor-names.tswebhooks.md详细介绍
use-semantius Skill
Semantius 是一个低代码平台,可让你定义语义数据模型、实体、字段、关系和访问规则,并立即获得完全托管的 PostgreSQL 数据库、REST API、自动生成的 UI,以及背后的分析层。你定义数据的结构(第 1 层),Semantius 负责存储、查询(第 2 层)和跨表分析(第 3 层)。
semantius 是官方 CLI,可通过 Shell 和 Agent 访问三个服务:crud(架构管理 + 记录操作)、cube(兼容 CubeJS 的分析),以及内置的 utils(CSV 解析、在主机之间迁移实体和模块)。
架构:三个不同的层
了解你正在使用哪一层,才能确定应该使用哪些工具:
┌─────────────────────────────────────────────────────────────┐
│ Layer 1: Semantic Data Model │
│ Defines entities, fields, modules, relationships, RBAC │
│ Tables: entities, fields, modules, permissions, roles... │
│ Tools: create_entity, create_field, create_permission... │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: Business Data (PostgreSQL via PostgREST) │
│ Actual records in your entity tables: /products, /orders │
│ Tools: postgrestRequest (GET/POST/PATCH/DELETE) │
│ sqlToRest for SQL→PostgREST conversion │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: Analytics (CubeJS-compatible API) │
│ Multi-table queries, aggregations, metrics, time-series │
│ Tools: cube discover → validate → load / chart │
└─────────────────────────────────────────────────────────────┘
经验法则:
- 定义存在什么(架构、权限、角色)→ 第 1 层类型化工具
- 操作单个表中的实际记录 → 第 2 层 postgrestRequest
- 跨表查询或需要聚合/指标 → 第 3 层 cube
参考文件
| 文件 | 阅读时机 |
|---|---|
references/cli-usage.md | CLI 命令及其级别、凭据和主机、选项、Shell 模式、命令串联、安装;§“在主机之间迁移实体和模块” |
references/data-modeling.md | 第 1 层、实体、字段、模块、关系、安全演进;§“枚举值和标签” |
references/entity-families.md | 第 1 层、子类型和扩展(id_type: is_a / has_a、id_refentity):何时使用、创建顺序、跨层级读写、限制、删除、错误代码。首次对这类实体调用 create_entity 前请先阅读 |
references/jsonlogic.md | 第 1 层、JsonLogic 规则:computed_fields、validation_rules、扩展运算符、跨实体查找、动态 input_type_rule(条件式只读/隐藏/必填) |
references/select-rule.md | 第 1 层、行级安全:select_rule、谁能看到哪些行、REPLACE 与 AND 语义、管理员锁定风险 |
references/rbac.md | 第 1 层、权限、角色、用户分配、层级结构 |
references/crud-tools.md | 第 1 层类型化工具 + 第 2 层 postgrestRequest/sqlToRest 参考;§“批量操作”(数组 data / id,每组记录调用一次) |
references/cube-queries.md | 第 3 层、CubeJS 查询 DSL、日期筛选、分析模式 |
references/cube-tools.md | 第 3 层、发现/验证/加载/图表工具签名 |
references/webhooks.md | 通过已签名的 Webhook 接收器接收外部系统的记录:设置、签名、日志 |
references/lucide-icon-finder.ts | 运行它(bun),不要阅读它:<query…>(每个查询包含一个或多个词,按具体程度从高到低排列)按顺序列出每个查询对应的 Lucide 图标名称;参见 data-modeling.md →“图标使用 Lucide 图标” |
references/lucide-icon-checker.ts | 运行它(bun),不要阅读它:<name…> 会在写入图标前确认 Lucide 图标名称,退出码为 1 时会列出未知名称;参见 data-modeling.md →“图标使用 Lucide 图标” |
references/vendor-names.ts | 运行它(bun),不要阅读它:entity:<Name>… 和 field:<Name>… 会将你所跟踪产品的记录名称和字段名称(使用单数形式,拼写方式与产品一致)转换为 table_name 和标签,或 field_name 和标签;切勿手动转换。由 semantius-architect(stage-2-naming.md)和 semantius-analyst(stage-4-fields.md)使用 |
快速决策指南
管理架构、创建/修改实体、字段或模块?
→ 第 1 层,阅读 references/data-modeling.md,遵循强制创建顺序
同一事物有多种类型(“电子邮件和电话都是活动”),或者某个记录也可以是另一种事物(“业务合作伙伴也可以是客户”)?
→ 第 1 层,创建任何内容前先阅读 references/entity-families.md:它会决定使用 is_a、has_a、枚举字段还是独立实体,并会改变创建顺序(每个层级调用一次 create_entity,先创建基类)。创建时即会锁定此选择,因此请与用户确认
计算字段、验证规则或条件字段行为(根据记录设置只读/隐藏/必填)?
→ 第 1 层,阅读 references/jsonlogic.md,了解实体级和字段级 JsonLogic、运算符及跨实体查询
只有部分用户可以对记录执行某项操作(删除、关闭、批准记录或修改某个字段)?
→ 第 1 层,阅读 references/jsonlogic.md § 检测操作。实体的 edit_permission 会同时涵盖插入、更新和删除,因此,针对单项操作或状态转换的限制应使用验证规则:检查 $mode(或变更的字段),再检查调用者身份。如果是所有者匹配,例如 $old.owner_user_id == $user_id,则无需权限;如果使用 has_permission,则需要先根据 references/rbac.md 创建权限
配置权限、角色或用户?
→ 第 1 层,阅读 references/rbac.md
限制用户可见的行(通过 select_rule 实现行级安全)?
→ 第 1 层,阅读 references/select-rule.md。注意:非空规则会在读取时替代 view_permission——不含 has_permission 子句的规则会将管理员拒之门外
在单个表中插入、读取、更新或删除记录?
→ 第 2 层,使用 postgrestRequest,参见 references/crud-tools.md
创建、更新或删除多个同类记录(许多字段、许多权限或许多行)?
→ 一次调用,绝不循环:create_* 的 data 使用数组;update_*/delete_* 的 id/table_name 使用数组;postgrestRequest POST 使用数组 body(键保持一致)。参见黄金规则 7 和 references/crud-tools.md §“批量操作”
跨多个表查询、聚合、分析趋势、查找前 N 项或指标?
→ 第 3 层,使用 cube,阅读 references/cube-queries.md + references/cube-tools.md
编写 shell 脚本或串联 CLI 命令?
→ 阅读 references/cli-usage.md
导入 CSV 文件?
→ semantius-importer 技能是入口:它会检查文件(utils/get_csvschema),创建或复用实体,并分批批量加载数据。
将实体或模块迁移到另一台主机、备份或还原导出内容?
→ 使用 semantius-transfer 技能执行工作流;references/cli-usage.md §“在主机之间迁移实体和模块”介绍具体操作。
发送事务性电子邮件?
→ 第 2 层工具,使用 crud sendEmail,参见 references/crud-tools.md §“sendEmail”
基于现成配方(例如由 semantius-skill-maker 生成的技能)执行时,遇到意外的 409/422 错误,并怀疑架构已发生变化?
→ 使用 read_entity/read_field 实时检查,参见 references/data-modeling.md §“运行时架构检查(实时外键/结构查询)”。不要悄悄调整配方;应中止操作、说明架构变化,并建议重新生成领域技能。
环境设置
1. 是否已安装 semantius? 运行 semantius --version。如果 shell 找不到该命令(POSIX 下会显示 command not found / 退出码 127,PowerShell 下会显示 CommandNotFoundException),可能是已经安装,但尚未加入当前会话的 PATH。请检查 %LOCALAPPDATA%\Programs\Semantius\semantius.exe(Windows)或 /usr/local/bin/semantius 和 ~/.local/bin/semantius(Linux / macOS)。如果文件存在,在这些技能写明 semantius 的地方都使用它的完整路径(references/cli-usage.md § "Installing from an agent")。如果这些位置都没有,请停止:不要运行任何 semantius 命令,并告知用户尚未安装,同时提供 references/cli-usage.md § "Installation" 中适用于其 shell 的安装命令,以及指南 **https://www.semantius.com/docs/cli/use-semantius/**。
2. 是否已连接? 按照 references/cli-usage.md § "Checking the connection" 操作。简而言之:
- 探测(运行
semantius whoami,或调用你本来就需要的getCurrentUser)。退出码为0:已连接。需要确认使用的是哪个凭据时,请指出主机、其host_source和auth_method;退出码为0仍可能存在 § "Credential, first match wins" 中的两个陷阱之一。 - 退出码为
3: 重试一次,然后显示错误并停止。 MISSING_ENV_VAR或退出码为5: 使用semantius use <host>为用户登录;除非whoami显示主机为current,否则先询问用户要使用哪个主机。尚无实例的用户请前往 https://app.semantius.com 注册;该网站会提供其主机(<org>.semantius.app)及连接步骤。例外:如果在有意配置密钥或令牌时,错误中提到SEMANTIUS_API_KEY或SEMANTIUS_JWT,则显示错误并停止。- 其他任何情况: 显示错误并停止。
为用户登录(§ "Signing the user in"):semantius use <host> 会为所有目录中的后续命令切换主机,因此只能对用户指定要操作的主机运行;semantius login --host <host> 会登录,但不切换主机。绝不要运行 logout。在后台运行登录,并将 URL 转发给用户;如果用户不在这台机器的屏幕前操作,则始终添加 --login-flow device。
whoami、ping 和 hosts 是安全的只读诊断命令。命令、层级、主机和凭据优先级:references/cli-usage.md。
核心 CLI 命令
semantius # List all servers and tools
semantius -d # List with descriptions
semantius info <server> # Show tools for a server
semantius info <server> <tool> # Get tool JSON schema
semantius grep "<pattern>" # Search tools by glob
semantius call <server> <tool> '{}' # Call tool with inline JSON
semantius call <server> <tool> # Call tool — reads JSON from stdin
Windows(PowerShell):始终传入内联 JSON;如果工具不接受参数,则通过管道传入空输入。 省略 JSON 参数会使 CLI 阻塞并持续从 stdin 读取,直到遇到 EOF。在持久化 PowerShell 会话中(某些 Agent 运行环境会在多次调用间保留状态),stdin 管道永远不会关闭,因此调用会无限期挂起,既不报错也不超时——这不是网络或身份验证问题,重试也无济于事。始终显式提供 JSON,即使内容为空:
semantius call crud getCurrentUser '{}' # inline JSON, never blocks
"" | semantius call crud getCurrentUser # or explicitly pipe stdin closed
在 Windows / PowerShell 上,调用不带参数的 semantius call ... 时,绝不要直接裸调用;必须使用上述两种形式之一。
info <server> <tool> 和 info <server>/<tool> 两种写法可互换。
两个服务
crud:架构管理 + 记录操作(第 1 层和第 2 层)
第 1 层类型化工具用于管理语义数据模型:create_entity、create_field、create_module、create_permission、create_role 等。它们操作的是 Semantius 自身的架构表。每个 create_* 的 data 都可以是单个对象,也可以是对象数组(一次调用即可创建多个字段、权限或角色);每个 update_* / delete_* 的 id(实体使用 table_name,权限使用 permission_name)都可以是单个值,也可以是数组。
**第 2 层 postgrestRequest**用于操作实际业务数据。你定义的任何实体都会成为可通过 PostgREST 访问的 PostgreSQL 表:
# Read records from your 'products' entity
semantius call crud postgrestRequest '{"method":"GET","path":"/products?status=eq.active&order=name.asc"}'
# Insert a new order record
semantius call crud postgrestRequest '{"method":"POST","path":"/orders","body":{"customer_id":"123","total":99.99}}'
# Insert several records in ONE call — array body; every row carries the same keys (raw PostgREST rule)
semantius call crud postgrestRequest '{"method":"POST","path":"/orders","body":[{"customer_id":"123","total":99.99},{"customer_id":"124","total":15.00}]}'
# Update matching records
semantius call crud postgrestRequest '{"method":"PATCH","path":"/products?category=eq.electronics","body":{"on_sale":true}}'
完整参考:references/crud-tools.md
cube:兼容 CubeJS 的分析(第 3 层)
Cube 服务实现了兼容 CubeJS 的 API。如果你熟悉 CubeJS,查询 DSL 是相同的。对于需要连接、聚合或 PostgREST 无法高效表达的指标,请使用它。
始终先调用 discover,它会返回架构、完整的查询语言参考和日期筛选指南。
完整参考:references/cube-queries.md、references/cube-tools.md
链接到 Web UI
每当你想在 Semantius Web 应用中向用户展示某条记录或记录列表时——例如创建后、查找后、报告查询结果时,或任何可点击链接优于原始 JSON 的场景——请根据 getCurrentUser 的 ui_baseurl 构建链接。无论是否涉及架构工作,这条规则都适用:既适用于第 2 层记录操作,也适用于第 1 层架构变更。
- 某个实体的记录列表:
{ui_baseurl}/{module_slug}/{table_name} - 某条特定记录:
{ui_baseurl}/{module_slug}/{table_name}/{id}
示例:https://mytest.semantius.app/it-ops-starter/service_requests/5
- 从
getCurrentUser获取ui_baseurl(semantius call crud getCurrentUser '{}')——绝不要将组织主机名硬编码。 - 路径中使用小写的
module_slug,切勿使用显示名称module_name。
完整说明:references/crud-tools.md § getCurrentUser。
黄金规则
- 先读后写:在执行任何
create_*之前,先调用read_*检查是否存在重复项。务必先读。- 执行
create_module前 → 先运行read_module - 执行
create_entity前 → 先运行read_entity - 执行
create_permission前 → 先运行read_permission - 执行
create_role前 → 先运行read_role - 如果读取返回结果,请使用这些 ID,而不是创建重复项。只有在结果为空时才创建。
- 批量创建时,一个带有
in.(...)过滤条件的read_*就能涵盖所有项("filters": "field_name=in.(description,cost)&table_name=eq.services");切勿对每条记录分别执行一次--single读取。
- 执行
- 先处理架构:模块 → 权限 → 所有实体 → 字段。绝不跳过步骤;先创建某个模型的所有实体,再创建其中任何字段,这样每个字段的
reference_table(包括自引用)都已存在。**例外:**对于is_a/has_a实体,先创建基类,再按层级创建基于它们的实体;每层调用一次create_entity。所有层级的实体都创建完后,再创建字段(references/entity-families.md)。 - 绝不创建自动生成的字段:
id、label、created_at、updated_at和label_column字段由create_entity自动创建。对于is_a/has_a实体,也绝不要创建其基类中的字段;只创建该实体自身的字段。create_field中也不要设置field_order:平台会按数组顺序追加新字段,而手动指定的值可能会与自动创建的字段意外相同(标签字段位于 20)。只有在用户需要特定位置时才设置;设置前先读取实体当前的field_order值。 reference_table必须使用关系格式:任何带有reference_table的字段都必须使用format: "reference"或format: "parent"。没有例外。- 高风险变更前先警告:重命名
table_name/field_name,以及删除实体或字段,都需要用户明确确认。 - 在有帮助时始终提供 UI 链接:架构变更后,以及记录操作(创建 / 查找 / 更新)后。格式:
{ui_baseurl}/{module_slug}/{table_name};单条记录则追加/{id}。有关规则,请参阅上文的“链接到 Web UI”(从getCurrentUser获取ui_baseurl;使用小写的module_slug)。 - **始终批量处理:每组记录调用一次,绝不循环逐条调用。**待处理的同类记录超过一条时(某个实体的多个字段、某个模块的多个权限、多个
role_permission行、多个待更新或删除的 ID、某个表的多行记录),都要在一次调用中发送:向create_*的data传入数组('{"data": [{...}, {...}]}'),或向update_*/delete_*的id传入数组(实体使用table_name,权限使用permission_name),例如'{"id": [4, 5, 6]}';相同的data会应用于每个 ID。数组项不必包含相同的键(某项省略的键会采用列默认值)。一次调用就是一个请求和一个事务(要么全部成功,要么全部失败);响应始终是受影响记录的数组。每次调用控制在约 100 行 / 个 ID。明明可以用一次数组调用,却发出 N 次单条记录调用,是错误做法。唯一的顺序例外是实体族:每层调用一次create_entity,先创建基类。postgrestRequest也接受数组body,但须遵循原始 PostgREST 规则(每项的键必须相同,或者在路径中使用?columns=,省略的键会变为 NULL)。请参阅references/crud-tools.md中的 §“批量操作”。
响应处理:仅凭退出码还不够
默认情况下,即使查询恰好匹配一行,crud 服务也会返回 JSON 数组。若 GET 未找到任何行,则退出码为 0,响应体为 []。这在协议层面表示成功,在领域层面则表示“未找到”。仅将退出码视为成功信号,会悄无声息地将空结果传递到下游,并破坏所有依赖它的写入操作。
这适用于每个 crud 工具,而不只是 postgrestRequest。
类型化的 Layer-1 工具也会返回数组:read_entity、
read_module 和所有 create_* / update_* / delete_* 工具都会
输出 [{...}],而不是单个对象;批量调用(数组 data、数组
id)则会在该数组中输出每条受影响的记录。因此,在
create_role 响应上运行 jq -r '.id' 会失败,并报错
Cannot index array with string——应对数组进行索引:jq -r '.[0].id',或者传入 --single 以获取单个对象(仅限单条记录调用;若 data /
body / id / table_name 是数组,则会拒绝 --single)。更好的做法是,不要直接从新行自身的创建响应中读取其 id:回显的表示形式并不是可靠的 id / 自然键载体。创建后按自然键重新读取(建模器的 ensure /
ensureMany 辅助函数正是这样做的——对整个批次执行一次 in.(...) 读取),这样数组与对象的形状就不会传到你的 jq。
针对 crud 读取有两种方式。请选择符合调用意图的方式:
模式 A:预期恰好一行时使用 --single
对于任何必须恰好解析出一行的读取(按 id、唯一列或
该配方已证明唯一的复合键查询),都向 postgrestRequest 传入
--single。CLI 会在底层设置 PostgREST 的 Accept: application/vnd.pgrst.object+json 标头,并将响应转换为符合 Agent shell
约定的格式:
| 结果 | 退出码 | 标准输出 |
|---|---|---|
| 恰好一行 | 0 | {"id":"...", ...}(单个对象,不是数组) |
| 零行 | 1 | 标准错误上输出错误 |
| 两行或更多 | 2 | 标准错误上输出错误 |
| 参数 / 配置 / JSON 无效 | 1 | 标准错误上输出错误信息 |
| 网络 / 传输(暂时性、可重试) | 3 | 标准错误上输出错误信息 |
| 工具执行失败(RLS、重复键、架构) | 4 | 标准错误上输出错误信息 |
| 身份验证失败(缺少 / 无效的 API 密钥、401、403) | 5 | 标准错误上输出错误信息 |
请注意,退出码 1 涵盖两种不同情况——“零行”和“参数
无效”。对于格式正确且处于稳定状态的脚本,运行时只会触发零行这一情况,因此规范的防护逻辑(“未找到或存在歧义”)是明确的;参数无效导致的 1 表示配方存在错误,绝不应出现在最终用户面前。
退出码 3 和 5 是有意区分的:3 表示暂时性错误(重试
一两次),5 表示永久性错误(立即告知用户,以便他们修复凭据)。根据这些情况分支的配方可以直接使用 case $? in 3) retry ;; 5) abort ;; esac,而无需解析标准错误。
现在,退出码会直接表示未找到的情况。规范脚本模式可简化为一个防护逻辑:
row=$(semantius call crud postgrestRequest --single "{\"method\":\"GET\",\"path\":\"/<table>?<unique-filter>\"}") \
|| { echo "step N: <entity> '<value>' not found or ambiguous" >&2; exit 1; }
# $row is the bare object: {"id":"...", ...}
# Parse with jq '.id' or grep -oE '"id":"[^"]+"' (no head -n1, no [0] index).
对于领域技能中的绝大多数读取,--single 都是正确的模式:每次“按 id 查询”、每次通过 eq.<unique-column> 解析,以及关联表配方中的每次父行读取都应使用它。如果零行或多行结果属于领域错误,而不是正常分支,就应使用 --single。
模式 B:数组(默认),适用于预期返回零行或多行的情况
对于结果数量本身就是答案的读取操作,请省略 --single:
去重检查(“这条关联表记录是否已存在?”)、列表
查询、批量读取。在这种情况下,响应是一个数组,
Agent 必须检查响应内容才能知道返回了什么。
| 结果 | 退出码 | stdout | 操作 |
|---|---|---|---|
| 找到记录 | 0 | [{...}, ...] | 使用这些记录 |
| 未找到记录 | 0 | [] | 去重/列表查询的答案是“无”;据此采取相应操作 |
| 参数/配置/JSON 错误 | 1 | stderr 中的错误消息 | 修正参数;不要重试 |
| 网络/传输错误(暂时性) | 3 | stderr 中的错误消息 | 重试一到两次,然后反馈错误 |
| 工具执行失败(RLS、重复键、架构) | 4 | stderr 中的错误消息 | 向用户反馈;这通常是实际错误或写入冲突 |
| 身份验证失败(缺少/无效 API 密钥、401、403) | 5 | stderr 中的错误消息 | 中止并向用户反馈;不要重试 |
以下是数组读取的标准模式,其业务含义取决于结果是否为空:
rows=$(semantius call crud postgrestRequest "{\"method\":\"GET\",\"path\":\"/<table>?<filter>&select=id\"}") \
|| { echo "step N (<what>) failed" >&2; exit 2; }
if ! printf '%s' "$rows" | grep -q '"id"'; then
# zero rows, the recipe's "go ahead and create / no duplicate" branch
...
else
# one or more rows, the recipe's "already exists / use existing" branch
...
fi
如何选择
| 读取意图 | 模式 |
|---|---|
将 <title> 解析为功能记录 | --single(标题必须存在,否则无法继续执行该方案) |
按 id 读取父记录 | --single |
检查 (feature_id, user_id) 关联表记录是否存在 | 数组(零行是正常的“创建”分支) |
| 列出某个状态下的所有功能 | 数组 |
| 验证写入是否生效 | --single(该记录必须存在;我们刚刚写入了它) |
| 检查批量清理是否完成(残留记录为零) | 数组(你要统计记录数,而不是断言只有一条) |
写入(POST / PATCH / DELETE)
成功的 POST 或 PATCH 会返回插入/更新的记录
(如果设置了 Prefer: return=minimal,则返回 [],但平台
默认不会设置该选项)。DELETE 会返回已删除的记录。因此,
对于未匹配任何记录的写入操作,同样适用“退出码为 0 且 [] 表示未执行任何操作”的规则:带有过滤条件且未匹配任何记录的 PATCH
会静默成功。单条记录写入也适用 --single
(必须恰好影响一条记录的 POST/PATCH),这是断言更改已生效的最简洁方式。如果操作本应更改状态,务必读取数据进行验证。
批量写入的响应始终是数组,绝不能使用 --single。 带有数组 data 的
create_*、带有数组 id(或 table_name)的 update_* / delete_*,或带有数组 body 的
postgrestRequest,始终返回受影响记录的数组——每条成功写入的记录对应一个元素。
CLI 会在发送请求前拒绝此类调用中的 --single(退出码为 1,错误码为 SINGLE_ARRAY_INPUT)。数组调用也绝不要显式传入
"accept": "application/vnd.pgrst.object+json"。通过计数断言批量写入结果(jq 'length' 等于发送的记录数),或通过后续带有 in.(...) 过滤条件的 read_* 调用进行验证。批量调用是一个事务:如果失败,其中的任何记录都不会写入——修复原因后重新发起这一次调用;不要退而采用循环逐条调用的方式。