类型系统
类型是 Agent Flow 的契约层:expect 的类型会编译成 JSON Schema
并在运行时强制;字段访问、投影、返回值都在编译期检查。
类型表达式
TypeRef := PrimaryTypeRef Suffix*
PrimaryTypeRef := 'member' '<' Id '>' | Id
Suffix := '[' RangeBounds? ']' // 有 Suffix 即为数组
RangeBounds := NUMBER '..' NUMBER // 闭区间界
示例:text、path[]、WorkItem[1..6]、path[][]、member<engineering>[]。
可选字段写作 field?: Type。读取它得到内部 T?,必须通过
value ?? fallback 消除缺失可能;null 是显式空值。
类型种类
| 类型 | 语法 | JSON Schema | 说明 |
|---|---|---|---|
| 文本 | text | string | |
| 数值 | number | number | |
| 布尔 | bool | boolean | |
| 路径 | path | string | 静态上与 text 同构;语义上用于权限/写入范围 |
| 时长 | duration | number(毫秒) | number <: duration 双向可赋值 |
| 对象 | type Name { ... } | object | 字段集合,字段有名字、类型、可选性 |
| 数组 | T[]、T[min..max] | array(可带 minItems/maxItems) | 界只在运行时强制;静态可赋值不比较界 |
| 可选字段/值 | field?: T / expr ?? fallback | 属性不进入 required | 读取结果不可直接当 T 使用 |
| 成员 | member<Team> | string + x-flow-member 标注 | 团队成员 id;调用时由 Runtime 做成员资格校验 |
| 验证 | Verification(内建) | {passed, failed, checks} | 只能由 verify 表达式产生 |
| 外部 | 未声明的具名类型 | 任意(接受一切) | 仅允许出现在 workflow 的 input/output/context 边界,产生 info 诊断 |
名字解析顺序
类型名按以下顺序解析:
- 基本类型名(
text/number/bool/path/duration) - 内建
Verification - 本 workflow 内的
type声明(声明顺序无关,允许前向引用) - 在 workflow input/output/context 边界视为外部类型;其他位置报
unknown-type
expect、stage 返回类型和字段引用中的未声明类型都会报错,避免契约静默退化。
可赋值性(assignability)
S <: T 的规则:
any(context)、外部类型:与任意类型双向可赋值- 基本类型:同名可赋值;
number <: duration且duration <: number member<T> <: text;member<T> <: member<T>仅当同别名- 数组:元素可赋值即可(不比较 min/maxItems —— 界由运行时 Ajv 强制)
- 对象是结构化的:
S <: T当且仅当 T 的每个必填字段在 S 中同名且类型 可赋值;T 的可选字段可缺省;多余字段不报错(运行时校验以 Schema 为准, Schema 侧additionalProperties: false) Verification<S_checks> <: Verification<T_checks>:checks 可赋值- 递归类型(直接或间接引用自身)不允许:
recursive-type
常用模式
用数组界表达业务约束
type Plan {
summary: text
work: WorkItem[1..6] // 编译进 Schema:Ajv 强制 1..6 个
}
界是运行时语义(静态不比较),所以它和 require ... in 1..6 是互补的:
界用于 Schema 校验(把坏数据挡在门外),require 用于** workflow 逻辑断言**
(带可读错误信息、产生 require.failed 事件)。
用 member<Team> 让"人"成为类型
use team "engineering-team" as engineering
type WorkItem {
id: text
owner: member<engineering> // 值必须是该团队成员 id
writes: path[]
}
member<engineering> 在 Schema 中是
{"type":"string","x-flow-member":"engineering"}。当它作为
team.member(expr) 的实参时,Runtime 校验成员资格,不是成员则抛
CapabilityViolationError——"把任务派给团队里真实存在的人"由运行时保证。
对象可赋值是结构化的
parallel 的匿 名对象结果可以直接 return 给同构的具名类型:
stage evidence -> Evidence { // type Evidence { style: Findings ... }
let found = parallel {
style = agent(styler) { /*...*/ expect Findings }
accuracy = agent(facter) { /*...*/ expect Findings }
}
return found // {style: Findings, accuracy: Findings} <: Evidence
}
JSON Schema 映射
| Flow 类型 | JSON Schema |
|---|---|
text / path | {"type":"string"} |
number / duration | {"type":"number"} |
bool | {"type":"boolean"} |
member<T> | {"type":"string","x-flow-member":"<teamId>"} |
T[] | {"type":"array","items":<T>} |
T[min..max] | 上者 + minItems/maxItems |
| 对象(具名嵌套) | properties + required + additionalProperties:false,嵌套具名类型内联展开 |
Verification / 外部类型 / any | {}(接受任意) |
expect Verification 被禁止(expect-invalid-type):验证结论必须是
Runtime 计算的,不能让 Agent 生产——见 verify。
下一步
- agent() 调用 —— expect 如何变成运行时契约
- 语言参考 —— 完整文法与规则