首页
/ Multica Agent 创建全解析:从 CLI 到 `/api/agents` 的字段契约、校验链路与源码级事实

Multica Agent 创建全解析:从 CLI 到 `/api/agents` 的字段契约、校验链路与源码级事实

2026-09-07 11:13:53作者:裴麒琰

Multica 的 Agent 是一个「以 workspace 为作用域、以数据库行(agent 表)为唯一事实来源」的配置实体。本文以仓库内置技能文档 SKILL.md 为骨架,结合其配套的证据层 creating-agents-source-map.md,完整梳理 multica agent create / copy / update / skills / env 等入口的字段契约、服务端校验与拒绝条件、每条字段的持久化方式,以及 daemon 在领取任务(claim)时到底读取了哪些字段。读完你既能用 CLI 安全地创建、复制与调试 Agent,也能理解为什么 description 不等于提示词、为什么 agent update 不能改环境变量这类容易被误用的规则。

本文是「文档契约 + 源码证据」双层的说明:文档中的每一条陈述都以 file:line 指向源码,本文只引用当前仓库真实存在的文件路径与行号,可随时打开仓库交叉验证。

Agent 的核心模型:一次创建、claim 时重读

从源码结构看,一个 Agent 是 workspace 作用域内的一个数据库行(表 agent),创建行为单一入口:HTTP POST /api/agents(CLI 上对应 multica agent create)。

理解这条链路的重点是「两段式」:

  1. 创建:CLI 组装 JSON body → POST /api/agents → 服务端校验 → 落库。
  2. 领取任务(claim):daemon 在真正执行前会重新读取 Agent 行并组装运行时载荷(runtime payload),而不是直接使用创建时的返回结果。

因此「Agent 实际以什么配置运行」取决于持久化后的字段,而不是 create 命令的输出。这一行为在 daemon.go 中非常直白:GetAgent(task.AgentID) 先按任务取回最新 Agent 行,然后依次组装技能与载荷。任何在创建后被 agent update 修改的字段,都会在下一次任务领取时生效,无需重新创建 Agent。

Agent 的另一种状态:unbound(未绑定 runtime)

Agent 与 runtime 通过可空的 runtime_id 关联。当一个 Agent 的 runtime 被删除时,它不会被连带删除,而是进入 unbound 状态:

  • runtime_id 变为 NULL(对外以 "" 呈现,同时 runtime_bound: false,参见 agent.go 的注释与响应结构);
  • unbound 保留它拥有的一切(配置、历史、技能绑定),并且仍然可编辑;
  • 没有任何触发路径会运行它——所有触发都会以 agent_runtime_required 拒绝;
  • 重新绑定用 multica agent update <id> --runtime-id <runtime-id>

注意 unbound 与 archived(归档)是两个正交的状态,不要混为一谈。

快速上手:只读检查命令

下面三条命令都只读取状态、无副作用,适合先探测现有 Agent 的定义:

multica agent get <agent-id> --output json      # 完整的持久化 Agent 记录
multica agent skills list <agent-id> --output json   # 当前的技能绑定
multica agent env get <agent-id> --output json  # 明文 env(仅 agent 本人或 workspace owner/admin 可读;agent 参与者一律拒绝)

agent get 返回的是持久化字段,包括 runtime_idmodelthinking_levelservice_tiercustom_argshas_custom_envcustom_env_key_countskills。它永远不会返回明文 custom_env——这一点在 agent.goAgentResponse 定义里有注释依据(引用 MUL-2600)。

最容易被混淆的两个字段:descriptioninstructions

文档特别强调这两个都是文本字段但角色天差地别:

字段 定位 运行时行为
description 目录摘要(catalog summary),给人看的元数据 只用于列表/展示;daemon 不会把它注入运行时提示词。上限 255 个 Unicode code point(见 agent.go 常量 maxAgentDescriptionLength = 255,用 utf8.RuneCountInString 计数,与 Postgres char_length 一致)
instructions 运行时行为契约 daemon 在 claim 时读取并随任务载荷发给 provider,作为 Agent 的持久化指令。人格(persona)、职责边界、输出规范、升级规则都应写在这里

一句话:把「这个 Agent 是谁、该怎么做」写进 instructions,把「它叫什么、一句话简介」写进 description

CLI / API 入口:multica agent create

nameruntime-id 两者都必填,最小创建调用如下:

multica agent create --name <name> --runtime-id <runtime-id> \
  --description "<short catalog summary>" \
  --instructions "<runtime behavior contract>" \
  --output json

runAgentCreate 的组装规则:只发送「已变更」的键

CLI 侧的关键行为在 cmd_agent.gorunAgentCreate:它构建一个 JSON body 后 POST 到 /api/agents,但只有某个 flag 被显式提供时才往 body 里加对应键

  • description / instructions:仅当值非空时加入;
  • runtime-config / custom-args / model / thinking-level / service-tier / visibility / max-concurrent-tasks 等:仅当对应 flag 处于 Changed 状态时加入。

这样做的效果是:被省略的 flag 不会以空字符串的形式发出去,而是让服务端默认值生效。这与「显式传空字符串 = 清空/显式使用空值」的语义区分开。例如 agent update 上显式传 --model "" 表示清除并回落 runtime 默认,而省略 --model 表示保持不变。

--max-concurrent-tasks 在发起任何 HTTP 请求之前就做 1–50 的本地校验,校验函数见 cmd_agent_validation.go,它委托给 internal/agentconfig 的共享校验器(ValidateMaxConcurrentTasks)。

HTTP body(CreateAgentRequest)比 CLI 暴露的更多

POST /api/agents 接受这些字段:namedescriptioninstructionsconversation_startersavatar_urlruntime_idruntime_configcustom_envcustom_argsmodelthinking_levelservice_tiervisibilitymax_concurrent_tasksmcp_configskill_ids。请求结构定义在 agent.go

一个值得注意的差异:conversation_starters 没有对应的 agent create / agent update CLI flag。CLI 只能在 agent copy 时把它原样带过去。要为一个全新 Agent 设置 conversation starters,要么直接调用 /api/agents,要么让人在 Web UI 上配置(见下文「Conversation starters」小节的定位指引)。

复制 Agent:multica agent copy

multica agent copy <source-agent-id> 会把一个既有 Agent 的可移植配置复制成一个全新 Agent,源 Agent 不被触碰——它是 Web 端 "Duplicate" 动作的 CLI/headless 等价物,flag 注册见 cmd_agent_copy.go

值得强调的实现细节:copy 不经过任何专属服务端 APIrunAgentCopy 先用 GET /api/agents/<id> 读回源 Agent,然后 POST 一个 CreateAgentRequest——并且把源 Agent 的 skill id 放进 skill_ids,使技能绑定在同一个 create 事务里完成(这与 agent create 不同,后者不绑定任何技能)。因此整个复制是一个原子变更。

multica agent copy <source-agent-id> --name "My Agent (copy)"   # 保持同一 runtime
multica agent copy <source-agent-id> --runtime-id <target> --model <model>  # 跨 runtime fork

复制规则可以总结成三组:

默认复制、无专属覆盖 flag 的

  • conversation_starters

默认复制、但可用对应 flag 覆盖的

  • name(默认追加 " (copy)" 后缀)、descriptioninstructions、头像、custom_argsmax_concurrent_tasks、调用权限(permission_mode + 允许名单)、已分配的 workspace 技能。

永不复制的(秘密 / 机器本地数据,读接口本来就会脱敏或掩码)

  • custom_envmcp_configruntime_config。复制后用与 agent create 相同的秘密安全 flag(--custom-env*--mcp-config*--runtime-config)重新提供新值,或用 agent env set

三条边界规则:

  1. 并发上限的兼容:只有源值落在 1–50 范围内时 max_concurrent_tasks 才被复制;历史越界值会被省略,让新 Agent 落到服务端默认 6。显式传越界的 --max-concurrent-tasks 会在任何 API 请求前被拒绝。
  2. runtime 相关字段modelthinking_levelservice_tier 只在目标 runtime 不变时才复制。--runtime-id 选择不同 runtime 时会丢弃它们并强制要求 --model(传 --model "" 表示接受目标 runtime 默认值),这与 Web Duplicate 在切换 runtime 时清空 model 的行为一致。
  3. 技能--no-skills 跳过复制源 Agent 的技能绑定。

字段契约总表

SKILL.md 给出了一个逐字段的事实表,逐条完整继承如下:

字段 持久化为 是否校验 谁消费它
name agent.name 必填,为空返回 400 列表、运行时载荷
description agent.description 超过 255 code points 返回 400 仅目录/列表——不是运行时提示词
instructions agent.instructions daemon 在 claim 时 → provider
conversation_starters agent.conversation_starters(JSON 数组) 至多 3 项;每项 label ≤ 80 code points、prompt ≤ 4000 code points 仅供人类使用的 Chat 空状态;选中只预填输入框,不会启动一次运行
avatar_url agent.avatar_url 无;显式非空值保留,省略/为空则生成随机 emoji:<glyph> 头像 仅目录/列表 UI——不是运行时提示词
runtime_id agent.runtime_id(可空) 创建时必填(400)+ 必须解析到本 workspace 内的 runtime 选择 runtime/provider;NULL 即 unbound
model agent.model(可空) 无(除 runtime 支持性) daemon 读取;为空 = runtime 默认
thinking_level agent.thinking_level(可空) provider 层枚举 / 安全 token 门禁;未知字面量 → 400(详见下文) daemon;为空 = runtime 默认
service_tier agent.service_tier(可空) 仅 Codex 的安全 token;其他 provider 拒绝;精确 model/tier 配对由 daemon 校验 daemon → Codex app-server;为空 = 本地 Codex 配置
custom_args agent.custom_args(JSON 数组) JSON 形状在 CLI 侧校验;服务端原样存储 daemon(额外 CLI 开关);默认 []
runtime_config agent.runtime_config(JSON) JSON 形状在 CLI 侧校验;服务端原样存储 runtime 专属配置;默认 {}
custom_env agent.custom_env(JSON 对象) daemon(进程环境变量);见「Env 与秘密」
mcp_config agent.mcp_config(原始 JSON) CLI 校验必须是 JSON 对象或 null;服务端原样存储。创建时字面量 null 被丢弃(no-op);更新时 null 清空该列 daemon → provider(provider 专属 MCP 处理);读取时脱敏
visibility agent.visibility 访问控制;默认 private;决定谁能读取/路由私有 Agent——不是运行时提示词
max_concurrent_tasks agent.max_concurrent_tasks 整数 1–50;越界返回 400 调度器任务上限;默认 6

省略或显式 null 时的默认值max_concurrent_tasks6。其他「省略时」默认值:runtime_config{}custom_env{}custom_args[]avatar_url → 随机 emoji:<glyph>visibilityprivate(全部在 insert 前由服务端物化,见 agent.go 创建路径中的默认处理代码)。

两个值得单独说清的细节:

  • custom_args / runtime_config 在 Go 侧类型是 []string / any,按原样 marshal——JSON 形状的拒绝发生在 CLI,而不是 create handler
  • 1–50 的并发范围在 create 与 update 上一致。create 时省略字段默认 6,而显式传 0 会被拒绝;update 时省略保持现值。CLI 在发送 create/update 请求前做同样的范围检查(validateAgentMaxConcurrentTasksFlag)。

创建路径的服务端校验顺序

agent.go 的 create handler 中,校验顺序依次是:

  1. name 为空 → 400 "name is required"
  2. description 超过 255 code points → 400;
  3. runtime_id 为空 → 400 "runtime_id is required"
  4. conversation starters 归一化(trim + 校验至多 3 对完整 label/prompt);
  5. visibility 为空 → 默认 "private"
  6. max_concurrent_tasks 走共享的默认化与范围校验;
  7. runtime_id 必须能解析到本 workspace(GetAgentRuntimeForWorkspace),否则 400 "invalid runtime_id"
  8. runtime 私有性检查(只有 runtime owner 能在其上创建 Agent,否则 403);
  9. thinking_level / service_tier 的 provider 层门禁。

thinking_level:provider 层词表 + daemon 逐模型校验的两段式

thinking_level 是本契约中最复杂的字段,核心原则是分两层校验

第一层(服务端 create/update handler)只做 provider 级校验IsKnownThinkingValue):

  • 固定词表 provider(如 Pi)只接受自己的枚举字面量,未识别的直接 400。Pi 的枚举是 off|minimal|low|medium|high|xhigh|max
  • 动态词表 provider(如 Codex/OpenCode)接受语法上安全的 token(safe-token),这样新目录值不必等 Multica 发版就能落库。

第二层(daemon 执行前)做精确的 model/level 配对检查:某个值对所选 model 不支持时,daemon 检查本地 model 目录,记一条警告并省略该不兼容覆盖,而不是让任务失败(对应 daemon.go 中「invalid-combination 处理」逻辑)。

由此可以解释几个文档强调的边界情况:

  • Pi 的 provider 词表是固定的七档,但逐 model 的支持子集来自本地 Pi RPC model 目录(discoverPiModelsRPC),所以「Pi 上某档对当前 model 不可用」不会在创建时被拒,而是由 daemon 在执行时省略。
  • ACP runtime 里,目前只有会通过 session/new 通告 effort 选择器的 runtime(当前是 reasonixhermes)走安全 token 路径,由 daemon 对照发现出的目录校验。该目录只覆盖 discovery 会话所在的那个 model,所以其他 model 在逐 model 探测机制出现前看不到选择器。
  • hermes 一个 provider 名下其实有两个二进制:jcode 通告并施加 effort,Hermes Agent 不通告、因此没有选择器——答案来自 runtime 自己发现出的目录,而不是 provider 名。而该目录只有在有人请求过一次 model 列表后才会写入,因此一个从未被 discovery 的 hermes runtime 会收到一个独立的 400("has not reported a model catalog yet"),而不是被假定为有能力。reasonix 的 provider 名能唯一决定二进制,处于该状态时反而被放行。
  • 完全没有推理控制的 runtime(例如 copilot——它虽然在 ACP 上 discovery,却通过自己的 CLI 执行、没有可供携带 effort 的实时 ACP 会话)会拒绝每一个非空值——这个 400 是能力答案,不是 token 写错了。

CLI 端设置用 agent create / agent update--thinking-level,与 --model 行为一致:它是顶层 thinking_level 字段的薄透传;update 时 --thinking-level "" 清空并回到 runtime 默认。CLI 刻意不枚举合法档位——它们是 runtime/model 相关的(Claude 当前用 low|medium|high|xhigh|max;Pi 用 off|minimal|low|medium|high|xhigh|max;Codex 的值要从 runtime 的 model 目录发现)。

service_tier:Codex 的一等速度控制

service_tier 是匹配 Codex 的一等速度控制字段,用法与 thinking_level 完全镜像:

  • create/update 用 --service-tier <catalog-id> 设置;
  • update 用 --service-tier "" 清除并回到本地 Codex 配置;
  • 可用性与展示文案都由 runtime 的 model 目录决定(当前是 priority,展示为 Fast);
  • 服务端接受未来的安全 Codex 目录 id,daemon 在执行前验证精确的 model/tier 配对,过期不兼容的覆盖会被省略;
  • 没有显式 model 的 Agent 会 fail closed,因为有效的 config.toml model 未知,无法验证 tier。

Conversation starters(对话开场建议)

产品内叫 Conversation starters(中文:对话开场建议)——与真人沟通时请用这个名字,线上的 conversation_starters 只是实现细节。配置位置在 Agent 的 Instructions 标签页,深链接为:

/<workspace>/agents/<id>?view=instructions&focus=conversation_starters
  • 最多 3 对 label + prompt,在用户打开与该 Agent 的新 Chat 时显示在输入框上方;
  • 选中一条只填充输入框,绝不启动运行——它们是建议,不是动作;
  • create 时省略该字段默认 [];update 时省略保持存量值,显式 [] 清空;
  • 一个完全没配置的 Agent 的空状态仍会展示三个内置的通用默认建议,所以「Chat 里有建议」不代表该 Agent 有自己的配置。

校验常数在 agent.go:最多 3 项、label ≤ 80、prompt ≤ 4000。

model vs custom_args:谁负责选模型

model 是一等持久化列,daemon 直接读取。custom_args 通常是传给 provider CLI 的原始参数。CLI 帮助文本明确提示部分 provider(codex app-server、openclaw)会拒绝出现在 custom_args 里的 --model——但那是文档化的 CLI 建议,不是服务端强制的不变量,create handler 不会去检查 custom_args 里有没有 model 字样。

另一方面,provider 后端确实会在启动前消费某些协议选择器:

  • Pi 会过滤 custom_args 中的 --thinking,因为一等字段 thinking_level 独占该 flag 且必须是它的唯一来源;
  • ZeroClaw 会消费 --agent <alias> / --agent-alias <alias>(含 =value 形式),把值作为 ACP session/new.agentAlias 参数发送——zeroclaw acp 本身没有这个 CLI flag。ZeroClaw 有多个 agent 且没有 [acp].default_agent 时应设置其中一个;单 agent 配置则应省略,让 ZeroClaw 自动选中那个 agent。

绝对不要把凭据或其他秘密放进 custom_args。daemon 的启动日志会脱敏参数值,但后端未消费的值仍会留在 provider 进程的 argv 里,可能被本机其他进程通过 ps/proc 看到。provider 凭据应放 custom_env,并尽可能用 stdin 或 0600 文件输入。

Env 与秘密:三条写入通道与读取侧事实

custom_env 属于秘密材料。CLI 提供三条输入通道,其中两条能把秘密挡在 shell history 与进程列表之外:

multica agent create --name <name> --runtime-id <runtime-id> --custom-env-stdin --output json
multica agent create --name <name> --runtime-id <runtime-id> --custom-env-file <0600-json> --output json
  • --custom-env-stdin:从 stdin 读 JSON 对象;
  • --custom-env-file:从文件读(建议 mode 0600);
  • 第三条 --custom-env <json> 把值放在命令行上,shell history 和 ps 都能看到——真秘密不要用它

读取侧事实(这些是容易踩错的假设)

  • Agent 资源永远不暴露明文 custom_envagent list/get/create/update 以及 WS 事件只返回 has_custom_env(bool)与 custom_env_key_count(int)。
  • 读取明文值必须走专门的 GET /api/agents/{id}/env(即 multica agent env get)。它的门禁实现在 agent_env.goauthorizeAgentEnv
    • 只放行 Agent 本人的人类 owner 或 workspace 的 owner/admin
    • agent 参与者一律拒绝agents may not access env management endpoints,403)——一个正在运行的 Agent 读不了另一个 Agent 的秘密,即使那个 Agent 正是它的人类 owner 拥有的(MUL-2600 伪装防护,判断在 agent actor 分支里最先执行);
    • 纯谓词 canManageAgentEnv:workspace owner/admin,或 agent.owner_id == member.user_idNULLowner_id 永不匹配。
  • 创建之后的写入不经过 agent update。通用 update handler 一见到 body 里的 custom_env 就 400(提示 "use PUT /api/agents/{id}/env")。明文 env 写入由 PUT /api/agents/{id}/envmultica agent env set)处理,携带同样门禁并写入一条审计记录。路由在 router.go 中注册(GET /envGetAgentEnvPUT /envUpdateAgentEnv),对应 SQL 写路径是 UpdateAgentCustomEnvSET custom_env = $2)——它是 env 值唯一的写入路径。

CLI 注释里也明确写了设计取舍:custom_env 有意不作为 agent update 的 flag,因为它需要走那条审计化的 env 端点。

mcp_config:也是秘密,但行为与 custom_env 不同

mcp_config 是 Agent 的 MCP server 配置(JSON 对象,如 {"mcpServers": {…}})。它同样属于秘密材料——MCP 条目常内嵌 API token——因此在 agent createagent update 两端都提供与 custom_env 相同的三条通道:

multica agent create --name <name> --runtime-id <runtime-id> --mcp-config-file <0600-json> --output json
multica agent update <agent-id> --mcp-config-stdin --output json
multica agent update <agent-id> --mcp-config 'null'   # 清空配置

--mcp-config-stdin / --mcp-config-file 把值挡在 shell history 与 ps 之外;内联 --mcp-config <json> 不行。CLI 要求 JSON 对象或字面量 null:顶层数组或原始值会在客户端被拒,空的 stdin/文件输入会报错而不是静默清空。

mcp_configcustom_env 有两条关键区别:

  1. 它可以通过 agent update 设置。custom_env 不同,mcp_config 没有专属的审计端点——通用 PUT /api/agents/{id} 就接受它。按原始 body 做三态:字段省略 → 不变;字面量 null → 清空;对象 → 整体替换。对应 handler 在 agent.go 的 update 路径(专门清空用 ClearAgentMcpConfig)。所以 agent update--mcp-config null 即可清空。
  2. 读取时会序列化但脱敏。 agent get/list 只对「有权限查看 Agent 秘密」的调用者返回 mcp_config,否则该字段为 nullmcp_config_redacted: true。agent 参与者永远看不到它;workspace 还可以对所有人强制脱敏。

provider 支持并不统一:Qwen Code 接受托管式 mcp_config——daemon 会把它写进自己拥有的 0600 临时 JSON 文件并以 --mcp-config 传入,进程退出即删除;该字段留空(null)则继承 Qwen Code 原生设置。

Workspace MCP servers:库、分配与合并

workspace 维护一个 MCP server (workspace Settings → MCP,或 multica workspace mcp list|add|update|remove)。加入库不会自动给任何 Agent 使用——与 workspace skill 形态一致。只有当有人把它分配给某 Agent 时才到达该 Agent:

multica workspace mcp list --output table        # 找到 server id
multica agent mcp add <agent-id> <server-id>     # 给某一个 Agent
multica agent mcp disable <agent-id> <server-id> # 停止发送但保留分配
multica agent mcp remove <agent-id> <server-id>  # 移除分配

claim 时生效的集合是三层的并集:

何时到达 Agent
runtime 本地 servers 总是(daemon 合并 runtime 自己的文件)
workspace servers 已分配给本 Agent 且保持 enabled
Agent 自己的 mcp_config 总是;名字冲突时它获胜

写配置前值得知道两个推论:分配共享 server 不需要再在 mcp_config 里重列(它们是合并的);mcp_config 现在只关乎「这个 Agent 私有的 servers」——一个托管但为空的 {} 不再代表 workspace 层的任何含义,因为本来就没有继承。

还有一条隐私设计:库里存储的条目是 write-only 的——任何角色的读取都只返回 server 的 name 与 transport,永远不返回 urls、commands、headers 或 env。

Skill 绑定:addset 是两个动词

创建 Agent 不会绑定任何 workspace skill——绑定是 Agent 存在之后的独立调用。两个动词不可互换:

  • add 是累加式:把给定 id 与既有绑定合并(POST /api/agents/{id}/skills/add);
  • set 是整体替换:用恰好给定的 id 覆盖整个绑定列表(PUT /api/agents/{id}/skills);--skill-ids '' 清空全部。
multica agent skills add <agent-id> --skill-ids <skill-id> --output json
multica agent skills list <agent-id> --output json

这两条命令的 HTTP 路由可以从 cmd_agent.go 的 skills 子命令定义中看到(setPUT /skillsaddPOST /skills/add)。

claim 时 daemon 组装技能的次序是:workspace 绑定的技能在前,随后追加平台内置技能LoadAgentSkills 加载每个绑定技能的内容及其支持文件(实现见 task.goLoadAgentSkills 与技能文件遍历逻辑);内置技能在编译期通过 go:embed builtin_skills 嵌入(见 builtin_skills.go),从 <name>/SKILL.md + 同级文件加载。两者最终都以技能内容(skill content)的形式到达 provider——这就是为什么「能力」要放进绑定的技能里,而不是贴进 instructions:你正在读的这份 SKILL.md 本身就是 builtin_skills/multica-creating-agents/ 下的一个内置技能。

副作用清单:哪些命令需要明确授权

只读(安全,可放心跑)agent getagent skills listagent env get

会改状态的(需要显式指令,不要投机执行)

  • multica agent create —— 插入一条新 Agent 行;
  • multica agent copy —— 插入一条新 Agent 行(既有 Agent 的 fork),源不被触碰;
  • multica agent skills add / set —— 变更绑定(set 有破坏性:会删掉不在新列表里的绑定);
  • multica agent env set —— 整体覆盖 custom_env 并写一条审计行。

常见错误假设清单(给 Agent 与人的防呆列表)

SKILL.md 最后给出的这张清单非常值得保留,它总结了整套契约最容易踩的坑:

  • description 就是提示词。」 不是——只有 instructions 会到达 runtime。一个 description 很丰富但 instructions 为空的 Agent,等于一个「有名字的 shell,没有行为契约」。
  • 「create 会绑定 Agent 的技能。」 不会——事后要显式绑定。
  • agent update 能轮换 env。」 不能——碰到 custom_env 就 400,请走 env 端点。
  • 「update 时 mcp_config 的表现和 custom_env 一样。」 不一样——mcp_config 可以通过 agent update 设置(--mcp-config--mcp-config null 清空);只有 custom_env 被锁在专属 env 端点后面。
  • agent get 会显示 env 值。」 它只显示 has_custom_envcustom_env_key_count
  • 「每个被接受的 body 字段都有 CLI flag。」 conversation_starters 没有——agent create/agent update 都设不了它,agent copy 只能把存量值带过去。
  • 「非法的 thinking_level/model 组合会在 create 时被发现。」 只有未知的 provider 级字面量会——model 级的不兼容要到运行期才暴露(daemon 记警告并省略该覆盖)。
  • setadd 对技能来说可互换。」 set 替换全部绑定;在你想用 add 时用了 set,会静默移除已有能力。

深入阅读:源码证据与一致性测试

本文所有契约背后都有可验证的源码锚点,最直接的入口是配套证据层文档 creating-agents-source-map.md,它把上文每条契约映射到 file:line、运行时效果和一条安全的只读验证命令,主要源码锚点包括:

  • CLI 入口cmd_agent.go(create/update/skills/env 子命令与 flag 注册、runAgentCreate/runAgentUpdate 的 body 组装)、cmd_agent_copy.go(copy 语义)、cmd_agent_validation.go(1–50 范围校验);
  • 创建/更新 handleragent.go(字段校验、默认值物化、thinking_level/service_tier 门禁、UpdateAgentcustom_env 的 400);
  • Env 门禁agent_env.go
  • 路由注册router.go/api/agents/{id}/env 等);
  • claim 时注入daemon.go(claim 重读 Agent 行、技能装载顺序、运行时载荷);
  • 技能装载task.gobuiltin_skills.gogo:embed 内置技能);
  • 字段持久化server/pkg/db/generated/agent.sql.go(由 queries/agent.sql 生成的 CreateAgent / UpdateAgent / UpdateAgentCustomEnv);
  • provider 模型/推理目录server/pkg/agent/ 下的 models.gothinking.goacp_effort.gopi.gozeroclaw.goqwen.go 等(逐 model 校验、Pi 的 --thinking 过滤、ZeroClaw 的 agentAlias 伪参数、Qwen Code 的托管 MCP 注入)。

本技能与共享模板的一致性由 internal/service 下的 Go 测试守护(例如针对该技能覆盖 Agent 创建契约的一致性测试),可在 server 目录运行 go test ./internal/service 中相关用例验证文档与实现没有漂移。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388