关于 stigg-governance
stigg-governance 是用于在 Stigg 中建模和配置实体级用量限制的技能,面向管理自定义单位及层级的团队。它说明实体类型、实体、权益、用量上报与执行,并区分通过 MCP 配置和运行时检查。
主要功能
- 01建模客户自定义实体层级
- 02配置实体类型和归因键
- 03设置功能或额度用量限制
- 04在树结构中上报并归因用量
- 05区分 MCP 配置与运行时执行
适用场景
- 01按项目、租户等单位限制用量
- 02让 Stigg 实体与源模型保持同步
- 03将上报用量归因到实体及其祖先
- 04通过 Stigg MCP 探索治理配置
MCP 相关
该技能使用 Stigg MCP 的 `execute` 和 `search_docs` 等工具进行治理配置、探索和测试检查。实时请求的执行检查则通过 Stigg SDK 或 edge 单独运行。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ stiggio/ skills --skill stigg-governance安装后在 Claude Code 中输入/stigg-governance确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/enforcement-and-usage.mdenforcement-vs-observability.mdentity-entitlements.mdentity-lifecycle.mdentity-model.md详细介绍
Stigg 治理 — 按实体设置使用量限制
治理功能在 Stigg 积分和功能之上,提供按实体执行限制。积分回答的是“这个客户可以消耗多少?”,而治理回答的是“这个客户自己的子单元可以消耗多少?”——无论供应商需要限制什么,都支持层级汇总和硬限制执行。实体模型由客户自行定义,完全灵活——Stigg 不强制使用固定层级,因此不要预设任何层级(参见步骤 1)。
你通过 Stigg MCP 使用 Stigg 治理功能——execute 工具运行 SDK 代码,search_docs 用于查询准确的结构。这就是 Agent 探索、配置和测试治理功能的方式:实体类型、实体、实体权益、树查询和单次检查都通过 execute 使用 SDK 的 v1 命名空间(client.v1.…)。**生产环境的运行时执行则另行处理:**用于控制真实客户请求的实时权益检查,会通过供应商热路径上的 Stigg SDK/edge 执行,而不是通过 MCP——MCP 用于 Agent 侧的设置和探索,不用于请求时的门控。本技能负责提供思维模型;不涵盖连接、密钥或设置,这些属于 stigg-mcp 技能。
治理功能已在
v1API 上正式发布。请使用client.v1.*调用。client.v1Beta.*治理调用仍可使用,但已弃用。只有一个例外:治理树查询没有 v1 版本,仍需使用client.v1Beta。现有 v1-beta 代码的迁移方法,请参阅下文的从 v1-beta 迁移。
步骤 1 — 了解模型:询问,不要假设(定义实体类型前先完成此步骤)
治理实体模型完全灵活,由客户自行定义。没有默认层级——Stigg 不提供任何预设层级,部门/团队/Agent 等结构都只是一种可能性,并非模板。定义任何实体类型之前,先询问客户想要治理什么,并严格根据他们的回答构建。不要提出或假设任何层级。请询问:
- 要限制哪些单元?(使用客户自己的术语——团队、项目、区域、租户、子账户、成本中心、Agent、工作区……)
- 它们如何嵌套/汇总?(哪些包含哪些,以及层级有多深——树最多支持 8 层)
- 哪些层级实际需要设置限制?(只有需要设置限制或进行汇总的层级才应纳入树中;其余层级应省略)
- 使用量事件通过什么标识单元?(事件已发送的维度键——这些键将成为归属键)
根据客户的回答建模:“我们按项目设置限制,项目属于某个客户” → 构建 client → project。下文及参考资料中的每个完整示例都只是一种可能的模型——它们展示的是 API 的结构,而不是应该采用的模型。
**顺序:**了解模型(本步骤)→ 实体类型 → 实体 → 实体权益 → 运行时。
前置条件 — 取决于你要限制的对象
治理限制建立在现有功能或额度货币之上,不会取代它们。功能与额度货币的要求不同——两者遵循不同路径,因此请阅读与你的实体权益(featureId 或 currencyId)相对应的条目。
-
功能(
featureId)— 需要有授予该功能权益的有效订阅。 只有当客户拥有授予该功能权益的 ACTIVE 订阅时,门控检查才可能通过;否则会以标准原因拒绝(NoActiveSubscription;NoFeatureEntitlementInSubscription= 已订阅,但套餐不包含该功能)。治理仍会运行,chains仍可能返回,但检查无法通过。必须先通过有效订阅授予该功能权益,检查才能通过。 实体权益 upsert 不会验证权益——即使功能没有权益,也会接受其限制,因此只有到检查时才会暴露这一缺口。请按以下顺序操作:先设置目录和订阅(参见stigg-pricing-modeling/stigg-subscriptions),再设置限制。 -
额度货币(
currencyId)— 不需要订阅。 额度遵循不同的路径:检查会直接读取客户的额度池,即使没有有效订阅或已分配的套餐,也可以授予和消耗额度。额度限制需要的是已存在的额度货币和有资金的额度池(通过授予额度实现——周期性、预付、促销或手动)。通过stigg-credits设置货币,然后添加每个实体的限制。
设置功能目录(套餐、功能、订阅——FREE 套餐必须在发布前设置 charges.pricingType)不是治理的职责:请通过 stigg-pricing-modeling(目录)和 stigg-subscriptions(配置)完成;额度货币和授予额度则由 stigg-credits 管理。然后添加每个实体的限制。
开始之前
根据总览 stigg 技能的要求:先搜索。 在编写内容前,通过 search_docs(或 Mintlify Stigg 文档 MCP)确认操作名称、字段名称和请求体格式。此技能负责提供思维模型;实际接口负责定义具体格式。
四个组成部分
entity type → entity → entity entitlement → governance tree — 类型(用于声明归因键)在每个环境中定义一次,并作为实体在每个客户下创建实例;实体权益限制一个 (entity, featureId|currencyId) 配对,可选择按范围进一步缩小;树报告用量与限制的对比,绝不会执行门控。实体权益就是 v1-beta 中所称的 assignment。下文将详细介绍每个组成部分。
实体类型
实体类型声明一种子客户单元——也就是客户在步骤 1 中命名的任何对象(项目、区域、租户、成本中心、Agent,……)——最重要的是,它声明归因键:事件维度的键,其值用于标识一条用量事件属于哪个实体。实体类型在每个环境中定义一次,并在该环境中的所有客户之间共享。操作包括:list、upsert(批量 PUT,幂等)、archive 和 checkActiveEntities。只要该类型仍有任何处于活动状态的实体(无论属于哪个客户),archive 就会以 400 失败:请先调用 checkActiveEntities(id),归档这些实体,然后再归档类型。对已归档类型执行 upsert 会将其恢复;除非传入 includeArchived: 'true',否则 list 会隐藏已归档的类型。请在报告任何用量前设计好归因键;无法为旧事件追溯补充归因。
实体
实体是这些类型的实例,按客户创建(归属于某个客户)——每个客户可以有多个,最多深达 8 层,形状由第 1 步确定(例如 client → project 或 region → tenant → workspace)。要在树中放置或移动节点,请在实体权益 upsert 中设置 parentId(client.v1.customers.entities.entitlements.upsert)——它有三种状态:省略 = 保持父级不变,null = 设为根节点,实体 ID = 设置或更改父级。parentId 是实体的唯一父级(每个实体只有一个位置),在实体权益上设置,而不是按功能或货币设置。(实用提示:实体 upsert 会拒绝 parentId,而且 metadata 不具有结构作用,因此父子关系应通过实体权益 upsert 设置。)操作:list / get / upsert(批量 PUT)/ archive。没有 unarchive 操作:对已归档实体执行 upsert 会将其恢复。不能对已归档实体类型下的实体执行 upsert(400)。只有叶节点可以更改父级(移动非叶节点会被拒绝,已归档的子节点仍计为子节点);archive 不受叶节点限制——归档父节点会使其仍处于活动状态的子节点成为孤立节点,因此请自行从下至上归档或重新安置后代节点。完整规则:references/entity-model.md。
让实体保持同步
实体是对供应商事实来源的持续镜像,而不是一次性导入——层级结构首先存在于你的系统中;树只是它的投影。将治理操作接入会变更模型的代码路径:注册 → entity upsert;重命名/属性变更 → 幂等地重新执行 upsert;停用/删除 → archive(从下至上);重新激活 → 对已归档实体重新执行 upsert;重构 → 在实体的实体权益 upsert 中设置 parentId,以移动节点(仅限叶节点)。由于 upsert 是幂等的批量 PUT,采用声明式的“每次同步时推送所需树”模式即可。完整映射及尚未发布的分配返还注意事项:references/entity-lifecycle.md。
实体权益 — 限制
实体权益为一个 (entity, featureId|currencyId) 对设置使用量限制:
entityId— 受限实体(位于客户树的任意层级)。featureId或currencyId— 受限对象——必须且只能是featureId(计量功能)或currencyId(额度货币)之一。两者互斥。usageLimit— 周期窗口的限制。null= 不限量:没有上限,但仍会跟踪使用量。cadence— 用于重置窗口的单一单位 ISO-8601 时长,例如'P1M'(每月)、'P10D'(每 10 天)或'PT1H'(每小时)。必须只有一个单位——不允许使用'P1M10D'(1 个月加上 10 天)这样的组合。scopeEntityIds— 可选 — 定义按维度限定的子限制;它会缩小限制的适用范围。[](空)= 始终适用的节点级限制。非空(例如['model-gpt4o'])= 仅当请求解析出的实体集合(归因得到的祖先实体 + 维度匹配实体)包含所有列出的实体时,限制才适用。最多 5 个 ID,不能重复。对于特定实体(通常是维度实体),请使用此项,而不是将限制应用于该实体下的所有内容。
操作:list / upsert,每次 upsert 最多 100 行。upsert 请求体的键为 entityEntitlements(v1-beta 使用 assignments)。一行按 (entityId, featureId|currencyId, scopeEntityIds) 匹配:匹配到的行会更新(省略的 usageLimit / cadence 保持不变),其他行会新建(两者均为必填)。因此,同一功能在两个不同范围下会形成两个独立的限制。currencyId 实体权益限制的是额度消耗,与计费货币(USD/EUR)无关。示例:references/entity-entitlements.md。
Usage 上报——按计量器类型选择接口
数据摄取不会进行拦截;它会记录用量并沿树汇总。端点取决于目标功能的计量器类型:
- 计算型/增量型计量器(由你的应用计算数值)→
client.v2.usage.report:同步调用。其响应会列出每项测量的用量,并在data.entities中列出每个被计入的实体权益的用量。必填项:customerId、featureId(功能 ID;信用额度货币 ID 会报错FeatureNotFound)、value。(client.v1.usage.report已弃用。) - 原始事件计量器(Stigg 聚合原始事件——计数/求和/去重计数)→
client.v1.events.report(reportEvent):目前这是必需的上报路径(v2.usage.report无法上报按原始事件计量的功能——请改用events.report/reportEvent);适用于高吞吐量,数据最终一致。reportEvent 没有featureId——计量器通过eventName(以及idempotencyKey)匹配。
两者都通过 dimensions 传递归属信息(实体类型的 attributionKey 值,例如 { "projectId": "proj-atlas", "regionId": "eu-west" })→ 归属到匹配的实体及其所有祖先。
读取功能的计量器以选择上报路径。 Feature 类型会公开
hasMeter/meter/meterType——检查meter配置,以区分原始事件计量器(→events.report)和计算型/增量型计量器(→v2.usage.report)。请注意,单靠meterType无法判断是否为“原始事件”(原始事件功能可能会读取INCREMENTAL),因此应读取meter配置,并通过search_docs确认字段。请保留明确的备用方案:如果v2.usage.report返回CannotReportUsageForEntitlementWithMeterError,说明这是原始事件计量器——请切换到events.report。结构和示例:references/enforcement-and-usage.md。
权限校验与用量读取
这是两种不同的读取方式——不要混淆。二者分别对应热路径(权限校验)与冷路径(可观测性);完整说明见 references/enforcement-vs-observability.md:
- 访问权限(拦截请求): 标准权益检查——
client.v1.customers.checkEntitlement(customerId, { ... }),传入featureId或currencyId、可选的requestedUsage(默认值为 1)以及归属信息dimensions。传入dimensions后,也会检查治理限额。只要至少有一个实体权益适用,响应的data.chains就会列出路径上的每项限额;治理校验拒绝请求时会返回RequestedUsageExceedingLimit。只要任何祖先达到硬性限额,实体就会被拦截——即使子实体仍有剩余限额,只要其任一父实体已耗尽,子实体仍会被拦截。检查功能(featureId)还需要有效的订阅来授予该权益;检查信用额度(currencyId)则不需要(参见前置条件)。 - 用量与限额(可观测性): 治理树查询——
client.v1Beta.customers.governance.list(customerId, { ... }),仍处于 v1-beta 阶段且采用分页——会返回实体节点;剩余限额 =usageLimit − currentUsage。默认情况下,该查询仅返回树结构:usageLimit/currentUsage/utilization/cadence均为null;传入featureIds和/或currencyIds(数组)即可加载这些功能/信用额度货币的配置和用量。其用量数据可能会延迟几秒更新(原始事件的延迟更长)——请用于仪表板和警报,切勿用于拦截访问。完整语义说明:references/enforcement-and-usage.md。
接口概览
通过 MCP execute 工具执行操作,调用 @stigg/typescript SDK(批量 upsert 操作具有幂等性;批量 upsert 和归档操作每次最多处理 100 个条目)。每项操作 → 对应的 SDK 调用(通过 MCP execute):
- 实体类型 — 列表 / 批量 upsert / 归档 / checkActiveEntities —
client.v1.entityTypes.* - 实体 — 列表 / 检索 / 批量 upsert(同时恢复已归档实体)/ 归档 —
client.v1.customers.entities.*(retrieve(entityId, { id: customerId })) - 实体权益 — 列表 / upsert(请求体键为
entityEntitlements) —client.v1.customers.entities.entitlements.* - 权益检查(不受治理功能启用状态限制 — 但仍会限制访问) —
client.v1.customers.checkEntitlement(customerId, { ... }) - 治理树查询(传入
featureIds/currencyIds以填充数据;支持分页;仅 v1-beta) —client.v1Beta.customers.governance.list(customerId, { ... }) - 摄取 — 计算型 / 增量计量器 —
client.v2.usage.report - 摄取 — 原始事件计量器(按
eventName) —client.v1.events.report
不要猜测操作名称或参数结构 — 请通过 search_docs 确认准确的操作。
API 与 UI — 按设计采用不同的实体权益模型。 API 针对的是每项实体权益对应一个功能或信用货币((entity, featureId|currencyId))。在仪表板 UI 中创建子实体时,系统会为你选择的每项功能或信用货币写入一条无限制实体权益记录(usageLimit: null),用于保留该实体的位置(你可以逐行编辑限制)。顶层实体不会获得任何实体权益。因此,通过 UI 和 API 创建的实体看起来不同 — 不必惊讶,也不要试图“修复”其中一种,使其与另一种保持一致。
**通过 Stigg MCP 使用:**MCP 仅公开 execute(通过 SDK 执行沙箱化 TypeScript)和 search_docs — 不会为每个端点分别提供一个工具。治理操作通过 execute 使用上述 SDK 命名空间执行。连接、密钥和环境设置由 stigg-mcp skill 负责 — 如果 execute 或 search_docs 无法连接,请在该 skill 中查找故障排除方法,而不是在这里查找。
从 v1-beta 迁移
client.v1Beta 治理调用已弃用。每项调用都对应一个 v1 调用,且每行中的字段名称保持不变:
v1Beta.entityTypes.list / upsert→v1.entityTypes.list / upsert(v1 新增了archive和checkActiveEntities)v1Beta.customers.entities.list / retrieve / upsert / archive→v1.customers.entities上的同名操作v1Beta.customers.entities.unarchive→ 使用已归档实体的 id 调用v1.customers.entities.upsertv1Beta.customers.assignments.list / upsert→v1.customers.entities.entitlements.list / upsert;upsert 请求体的键从assignments改为entityEntitlementsv1Beta.customers.entitlements.check→v1.customers.checkEntitlement(参数仍为featureId/currencyId/requestedUsage/dimensions)v1Beta.customers.governance.list→ 不变(没有 v1 版本)v1.usage.report(已弃用)→v2.usage.report,其响应新增了data.entities
原始 REST 接口也以相同方式迁移,/api/v1-beta/... → /api/v1/...,只有一个重命名:/api/v1-beta/customers/{id}/assignments → /api/v1/customers/{id}/entities/entitlements。
何时不应使用此技能
- 账户级信用货币、授予额度、池、账本、自动充值 →
stigg-credits。 - 不涉及单个实体限制的功能门控 / 用量报告 →
stigg-entitlements。 - 在产品目录中建模功能 / 计划 / 信用货币 →
stigg-pricing-modeling。 - 开通 / 取消订阅 →
stigg-subscriptions。
常见错误
每个错误——对应的修正方法:
- 在
client.v1Beta上编写新代码——这些治理调用已弃用。请使用 v1 调用(参见从 v1-beta 迁移);只有树查询仍使用client.v1Beta。 - 向 v1 upsert 发送
assignments——v1 请求体的键是entityEntitlements。 - 调用
unarchive——v1 没有此方法。使用相同 id 重新 upsert 已归档的实体,即可恢复它。 - 归档仍有活跃实体的实体类型——整个请求会以 400 失败。先检查
checkActiveEntities(id),然后先归档该类型下的实体,再归档类型。 - 根据树查询控制访问权限——其中的用量数据可能会延迟几秒。只能通过权益检查来控制访问权限。
- 把“子级还有剩余限额但被阻止”当作 bug 来调试——这是祖先节点语义:任意祖先节点的限额耗尽,都会阻止整个子树。沿树向上检查。
- 构建超过 8 层的层级——这是硬性限制,放置到更深层级会被拒绝。请重新设计模型(例如,将一层折叠到
scopeEntityIds中)。 - 报告用量时不提供归属维度——用量不会归属到任何实体,限额永远不会累积。请提前设计好维度。
- 总是调用
v2.usage.report,或总是调用events.report——这取决于计量类型。计算型/增量型 →v2.usage.report;原始事件型 →events.report(按eventName调用 reportEvent)。如果v2.usage.report返回CannotReportUsageForEntitlementWithMeterError,请切换到 reportEvent。 - 将额度货币 id 作为用量报告的
featureId传入——它只接受功能 id,并会报FeatureNotFound。请直接通过额度 API 提取额度(stigg-credits)。 - 向 reportEvent 传入
featureId——reportEvent 通过eventName(以及idempotencyKey)定位计量器,而不是通过featureId;归属信息放在dimensions中。 - 创建 功能(
featureId)实体权益,并期待检查通过——upsert 不会验证权益。必须先通过活跃订阅授予该功能权益,否则检查会以NoActiveSubscription/NoFeatureEntitlementInSubscription拒绝。 - 误以为 额度(
currencyId)限额也像功能一样需要订阅——并不需要;额度走另一条路径。检查会直接读取额度池;无需订阅即可发放/消耗额度。它需要额度货币和已注资的额度池,而不是订阅(stigg-credits)。 - 将
usageLimit: null理解为零——null表示无限制;用量仍会累积并向上汇总。 - 读取树时得到
null限额/用量——这是仅查询树的模式。传入featureIds/currencyIds以填充配置和用量。 - 把 MCP 连接错误当作治理问题——连接/设置问题(密钥错误、环境错误)属于
stigg-mcp的范畴;先在那里修复,再重新运行治理操作。 - 重新设置仍有子节点的节点的父级——重新设置父级仅适用于叶节点;移动非叶节点会被拒绝。先将子节点移动到其他父节点,或自底向上将它们与父节点分离(
parentId: null),然后再移动原父节点。归档子节点没有帮助:已归档的子节点仍会被计入。此拒绝不是暂时性的,因此不要重试。 - 误以为只能归档叶节点——并非如此;归档父节点会使其活跃子节点成为孤儿节点。请自行自底向上归档/重新安置后代节点;平台不会阻止你。
- 在实体 upsert 上(或在
metadata中)设置parentId——实体 upsert 会拒绝parentId,而metadata不承担结构性作用。请在实体权益 upsert 上设置parentId,以放置/移动节点。 - 把实体当作一次性导入数据——实体是你事实来源的持续镜像;请将 upsert/归档/重新设置父级接入创建/更新/删除/重组流程(
references/entity-lifecycle.md)。 - 将
currencyId理解为计费货币——它是额度货币(参见stigg-credits),不是 USD/EUR。 - 期待治理功能提供按端点划分的 MCP 工具——MCP 只有
execute+search_docs。请通过execute驱动 SDK。