策略
这页写给用管理台的管理员:怎么在「策略」页给组织、团队、设备下发约束,配完之后员工的 sid-code 什么时候、以什么方式变化。
客户端怎么执行这些约束(deny 为什么绕不过去、静态防护层、本地 managed-settings.json 放哪),写在企业 policy 与安全边界,这页不重复。两页的分工是:这页管「怎么下发」,那页管「下发之后客户端怎么执行」。
远程策略和本地 managed-settings.json 是同一个形状。区别是远程策略不用往每台机器分发文件,改完不用重装;代价是员工必须配好 backend.url 并登录过一次。
只取一层,不合并
求值时按 设备 > 团队 > 组织 的顺序,取第一份生效中的策略,字段不合并。
给某台设备单独加一份只写了一条 deny 的策略,组织层的所有约束(禁 bypass、禁 MCP、插件白名单……)对这台设备就全部不再生效。团队层同理。
要在下层「加一条」,正确做法是先把上层内容复制过来,再增改。新建弹窗里有「从组织 acme复制内容」这样的按钮,见在管理台里操作。
联动:配了之后员工那边会怎样
| 你在管理台做了什么 | sid-code 什么时候知道 | 拉取失败时 | 员工看到什么 |
|---|---|---|---|
| 新建 / 修改 / 启用一份策略 | 下次启动;或执行 /login;或交互会话里的低频轮询(约 30 分钟一次) | 启动时:10 分钟内的权威缓存继续用,否则按无远程策略处理;轮询时:保留会话里现有的策略 | 被拦的操作给出拒绝提示;policyLimits 关掉的功能显示你填的禁用理由;轮询拿到新策略时状态栏提示「企业策略已更新」 |
| 停用 / 删除一份策略 | 同上。服务端改回 204(没有策略)或命中上一层 | 同上 | 约束消失,或换成上一层的约束 |
| 什么都没配 | —— | —— | 只受本地 managed-settings.json 约束(如果有) |
几个细节:
- 鉴权:下发端点是
GET /api/v1/ctl/policy,必须带设备凭据。没登录的员工拉不到远程策略。 - 超时与重试:单次 15 秒,最多两次;401 不重试(凭据不会自己变好),状态栏提示重新
/login。 - ETag:策略没变时服务端回 304、不传 body,所以轮询几乎不产生流量。
- 轮询只采纳权威结果:200 / 204 / 304 才算数。碰上超时、5xx、401,会话里已经生效的策略保持不变——不会因为一次网络抖动把 deny 撤掉。
sid-code -p无头调用不轮询,下次启动时生效。- 最迟约 33 分钟:30 分钟间隔加 ±10% 抖动。急的话让员工重启或执行
/login。
版本
低频轮询从 v0.1.610 之后的版本开始提供。更早的客户端只在启动和 /login 时拉取,改完策略要等员工重启。
隐私级别不影响策略通道:员工开 no-telemetry 或 essential-traffic 都照常拉取(见隐私与数据流向)。
出处:packages/core/src/config/policy.ts、policy-poll.ts;agent-backend: backend/app/modules/policy/router/serve.py。
在管理台里操作
页面在顶栏「策略」。页面顶部的说明框写着「策略按 device > team > org 生效,不合并」,和上面的警告是同一件事。
新建一份策略
- 点右上角「新建策略」。
- 「层」选 组织 / 团队 / 设备,填「组织 ID」;选团队或设备时,再填「团队 ID」或「设备 ID」。
- 选团队层或设备层时,如果上层已经有生效中的策略,弹窗顶部会出现提示: 「此层生效后,上层 X 对这些设备不再生效」,下面每一份上层策略对应一个按钮,例如「从组织 acme复制内容」「从团队 platform复制内容」。先点复制,再改。
- 按需填写约束字段(见字段说明)。
- 填「变更原因(进审计,不是用户看到的禁用理由)」。必填。
- 展开「即将下发的 settings(不含 source)」,核对一遍最终会发给客户端的 JSON。
- 确定。
改、停用、启用、删除
列表每行的「操作」列:
| 按钮 | 作用 | 要填什么 |
|---|---|---|
| 改 | 改约束内容。层和对象不能改,要换对象就新建一份 | 变更原因 |
| 停用 | 不再下发,记录保留。可以再启用 | 原因 |
| 启用 | 重新进入下发 | 原因 |
| 审计 | 看这一份策略的变更记录:谁、什么时候、改了什么、为什么 | —— |
| 删除 | 真删。审计记录保留 | 原因 |
「下发」列显示「下发中」或「已停用」。「约束」列是摘要,例如「禁 bypass · 禁全部 Hook · 插件仅限 2 个市场」;有告警时旁边出现橙色「告警」标签,鼠标悬停看内容。
右上角「全部审计」看所有策略的变更记录。
预览某台设备会命中哪一份
列表下方输入设备 ID,点「预览命中」:
- 「将命中 设备 / 团队 / 组织
xxx· 摘要」:这台设备现在拿到的就是这一份; - 「三层都没有生效策略」:服务端会回 204,客户端只受本地文件约束;
- 下方出现黄色框「被遮蔽的上层策略(对这台设备整份不生效,字段不合并)」:说明这台设备命中了下层,框里列出的上层策略对它完全不生效。如果这不是你想要的,回去把上层内容复制进下层那份。
设备 ID 在「设备」页可以查到。想一次看清某台设备的策略、预算和 Flag,用设备页每行的「生效配置」抽屉。
写入规则
| 情况 | 结果 |
|---|---|
| 同一层、同一对象已经有一份生效中的策略 | 409「同层已有生效策略」。改内容请更新那一份,或先停用再新建 |
| 组织 / 团队 / 设备不存在 | 404 |
| 组织层的对象 ID 和组织 ID 不一致 | 422 |
| 一项约束都没有(空策略) | 422。空的远程策略会盖掉员工本地的 managed-settings.json,所以不允许 |
出现未知字段,或 policyLimits 里写了客户端不支持的功能 | 422,提示里说明为什么不行 |
| 原因为空或只有空白 | 422 |
所有写操作都校验失败即拒绝,不会「先存进去、下发时再过滤」。
字段说明
弹窗里的每个控件对应下发 JSON 里的一个字段。这些字段和本地 managed-settings.json 同名同义,客户端执行细节见企业 policy 与安全边界。
| 弹窗里的名字 | settings 字段 | 取值 | 员工端效果 |
|---|---|---|---|
| permissions.deny | permissions.deny | 一行一条规则,例如 Bash(curl *) | 命中即拒绝,用户侧任何 allow 和权限模式都翻不过来 |
| 高级:allow / ask | permissions.allow / permissions.ask | 同上 | 企业来源的 allow 不会被「危险自我授权剥离」去掉;ask 强制确认 |
| 关掉的功能(policyLimits) | policyLimits | 勾选 禁止 MCP / 禁止子代理 / 禁止自定义命令 / 禁止扩展/技能 | 对应功能不可用,员工看到你填的禁用理由 |
<功能> 禁用理由(用户可见) | policyLimits.<功能>.reason | 文本,勾了就必填 | 原样展示给员工,例如「未审计的 MCP 不允许」 |
| 禁用全部 Hook | disableAllHooks | 开关 | 任何来源的 hook 都不执行 |
| 只允许托管 Hook | allowManagedHooksOnly | 开关 | 只执行企业托管的 hook,用户级、项目级、插件的 hook 被屏蔽 |
| 只允许策略里的权限规则 | allowManagedPermissionRulesOnly | 开关 | 只认企业策略里的权限规则 |
| 禁用 bypass 权限模式 | disableBypassPermissionsMode: "disable" | 开关 | --dangerously-skip-permissions 和 always-allow 直接报错退出 |
| 禁用的权限模式 | disabledModes | 多选,见下 | 对应模式不可用 |
| 禁止 Bridge 远程控制 | bridgeEnabled: false | 开关 | 这些设备不再接受遥控,见遥控。不打开等于不限制 |
| 限制插件来源(strictKnownMarketplaces) | strictKnownMarketplaces | 开关 + 市场 index URL 列表 | 只能从列出的市场安装 / 加载插件,见下 |
| 锁定全部定制化面 / 锁定部分定制化面 | strictPluginOnlyCustomization | true,或从 commands skills agents hooks mcp-servers 里多选 | 被锁的面只认企业托管、插件和内置来源,员工自带的同类扩展不加载 |
policyLimits 只有这四项真的会拦:mcp、sub_agent、custom_commands、extensions。其他名字写进去会 422,提示里会告诉你该用哪个字段(例如 hooks 用「禁用全部 Hook」,bypass 用「禁用 bypass 权限模式」)。
disabledModes 的 9 个有效值:default、manual、always-allow、deny-write、acceptEdits、plan、dontAsk、auto、dangerously-skip-permissions。
disableBypassPermissionsMode 是最该配的一项。不配它,--dangerously-skip-permissions 会跳过全部检查,上面所有约束都有一个总开关(见企业 policy 与安全边界第 1 条)。
限制插件来源
打开「限制插件来源」后:
- 列表里有 URL:只能从这些市场安装、加载插件;
- 列表留空:除内置插件外禁一切插件。这是最严的一档,不是「未配置」;
- 开关不打开:不限制插件来源;
- 无论列表写了什么,本地目录安装和
--plugin-dir一律被拒。
「锁定全部 / 部分定制化面」也会收住插件这个口子:只要锁了任意一个面,即使没打开「限制插件来源」,本地目录和 --plugin-dir 的插件同样被拒,市场插件只放行员工 backend.url 对应的那个企业市场。
| 插件来源 | 都不配 | 只锁定制化面 | 配了插件来源白名单 |
|---|---|---|---|
| 内置插件 | 放行 | 放行 | 放行 |
| 企业市场 | 放行 | 只放行本企业市场 | 在名单里才放行 |
本地目录 / --plugin-dir | 放行 | 拒绝 | 拒绝 |
出处:packages/core/src/config/plugin-only-policy.ts。
URL 规则(写入时校验,不合规 422):
- 必须是
https://;只有本机回环(127.0.0.1、localhost、[::1])可以用http://; - 不能带账号密码、query(
?)或 fragment(#); - 一行一个,去重后最多 32 个;尾斜杠会被去掉。
别把自己的企业市场漏掉
客户端收到白名单后只认名单,不再默认放行本企业市场。要让员工继续从企业市场装插件,名单里必须写上它的 index URL:
https://agent.example.com/traj/api/v1/ctl/marketplace/index漏写时保存不会被拒,但列表里这一行会出现「告警」标签,提示「白名单里没有本企业市场」。只想用官方市场、或者有意禁掉企业市场时,忽略这个告警即可。
市场怎么上架插件,见插件市场。
只能在本地文件里设的字段
blockedCommands、blockedUrls、maxHookTimeout、allowedHookSources 这四个字段只在本地 managed-settings.json 里生效,管理台不接受(写进去会 422)。需要它们时按企业 policy 与安全边界分发文件。
远程策略和本地文件同时存在时,远程优先,只取一个来源,同样不合并。
怎么确认真的生效了
- 管理台「预览命中」看这台设备命中哪一份、有没有被遮蔽的上层;
- 员工端执行
sid-code auth status --verify,「策略」一行显示通道连通; - 拿一条该被拦的命令跑一次
sid-code -p,看是否被拒; - 「审计」页的「策略与护栏是不是在拦东西」表格:每台设备的
policy applied和policy none/error两列。none/error不为零,说明这台设备有过拉不到策略的启动,按排障与常见问题查。
能力边界(如实说)
1. 员工不用 sid-code,策略就管不到。 策略约束的是 sid-code 客户端,不是员工的电脑或账号。
2. 拉不到策略时是 fail-open。 后端挂了、网络不通、员工没登录,客户端都按「没有远程策略」继续工作(启动时有 10 分钟内的缓存则用缓存)。这是有意的:策略通道是「施加约束」,不能因为它出故障就让全员停工。要求必须受控的环境,同时在系统级路径部署一份本地 managed-settings.json 兜底。
3. 生效不是实时的。 交互会话最迟约 33 分钟、无头调用要等下次启动。紧急撤权限(比如员工离职)用设备页的「吊销」,见设备与注册码。
4. 只取一层。 见页首警告。这是设计,不会改成字段合并。
5. 飞书登录的设备默认没有团队。 想让团队层策略生效,先在「设备」页用「调整归属」把设备分进团队,见组织与团队。
常见问题
改了组织层策略,有一台设备没变化
用「预览命中」查这台设备。最常见的原因是它命中了设备层或团队层的一份策略,组织层被整份遮蔽了。
想给某个团队在组织规则上「多加一条 deny」
新建团队层策略时,先点「从组织 acme复制内容」,再在 permissions.deny 里加一行。直接只写那一条,组织层的其他约束对这个团队就全没了。
保存时报 422「空策略」
至少要有一项约束。只填了 allow,或者开关都是关的,都算空策略。空的远程策略会盖掉员工本地的 managed-settings.json,等于给员工松绑。
员工说没看到禁用理由
禁用理由只在员工触发了被禁的功能时显示。「变更原因」是进审计的,员工看不到,两个别填反了。
相关
- 企业 policy 与安全边界 —— 客户端怎么执行这些约束;本地
managed-settings.json - 预算 —— 同样是 设备 > 团队 > 组织 只取一层
- 组织与团队 —— 把设备分进团队,团队层策略才有对象
- 插件市场 —— 配合「限制插件来源」使用
- 企业后端概览 —— 全部通道的联动总表