Schema as Prompt
语言:English · 中文
Agently 的 .output(...) 是 prompt-native:你写的结构既会被渲染成给模型的文本提示,也会作为返回的 parser/validator。无需另外维护 JSON Schema —— 同一份嵌套 dict 同时驱动两端。
叶子
叶子是元组:
(TypeExpr, "description", True)| 槽 | 含义 |
|---|---|
1. TypeExpr | Python 类型、typing 表达式、Enum、BaseModel,或字符串 token 如 "str"、"list[str]" |
| 2. description | 给模型与人的软提示 |
| 3. ensure | True 表示路径/key 必填,会写入 ensure_keys;"not_null" 还要求值可用 |
第三槽是 ensure 标记,不是默认值。旧的「第三槽 = default value」约定已不再支持,YAML 的
$default也已移除。
简写形式:
(str,) # 仅类型
(str, "简短描述") # 类型 + 描述
"仅描述" # 等价于 (Any, "仅描述")Object 与 array 节点
dict 与 list 嵌套组合:
{
"title": (str, "文章标题", True),
"tags": [(str, "标签", True)],
"sections": [
{
"heading": (str, "标题", True),
"body": (str, "正文", True),
}
],
}| 容器 | 含义 |
|---|---|
dict | object 节点——字段顺序保留且有语义 |
list 单个元素 | 同质数组——只写一个 prototype |
list 多个元素 | 例子/示意;标准写法只放一个 prototype |
字段顺序是契约的一部分
模型按你定义的顺序输出字段。如果你显式暴露 notes、analysis 这类字段,它们会排在 answer 前面并被下游消费。换序就是换行为——不存在「模型自己摸出来」的最佳顺序。不要要求模型输出隐藏推理过程;只暴露业务上确实要保存的字段。
ensure 编译为 ensure_keys
第三槽每个 True 或 "not_null" 都把对应叶子的路径写进解析时的 ensure_keys:
{
"title": (str, "标题", True),
"items": [
{
"name": (str, "名称", True),
"value": (str, "值"), # 不强制
}
],
}编译为:
ensure_keys = ["title", "items[*].name"]数组通配 items[*] 是路径语法的一部分。如果解析后 title 缺失或任意 items[i].name 缺失就触发重试(受 max_retries 限制)。value 允许缺失。True 只检查路径存在,所以空字符串、None、False、0 或空列表仍可作为合法业务值。若字段遇到 None、空白字符串、空列表或空 wildcard 匹配,以及列表中包含缺失必填值时应重试,使用 "not_null"。
{
"ready": (bool, "planner 是否可以继续", True),
"questions": (list, "需要追问的问题", True), # [] 合法
"reply": (str, "ready 时的最终回复", "not_null"), # 空白文本会重试
}要求「整套 schema 都必须回来」时,agent 上设 ensure_all_keys: True,或 YAML/JSON prompt 顶层 $ensure_all_keys: true —— 它覆盖每叶子的 ensure。
YAML / JSON 写法
output:
title:
$type: str
$desc: 标题
$ensure: true
items:
$type:
- name:
$type: str
$desc: 名称
$ensure: true
value:
$type: str
$desc: 值约定:
$type—— 类型表达(字符串 token 或嵌套结构)$desc—— 描述$ensure: true(或$ensure: 1)—— 路径/key 存在性 ensure$ensure: "not_null"—— 路径/key 存在性 + 内置值存在性校验- 别名
.type/.desc也被 loader 接受,但推荐$前缀
$default 不再支持 —— default 已不属于 authoring。
YAML 类型 token
常用字符串 token:
| Token | 含义 |
|---|---|
"str"、"int"、"bool"、"float" | 标量 Python 类型 |
"list[str]"、"dict[str, int]" | typing 风格 |
"Literal[open, closed]" | 字面量 |
"Optional[str]" | 可选类型 |
Pydantic 与 Enum
TypeExpr 允许 Pydantic 模型与 Enum:
from enum import Enum
from pydantic import BaseModel
class Severity(str, Enum):
P0 = "P0"
P1 = "P1"
P2 = "P2"
class Ticket(BaseModel):
severity: Severity
rationale: str
agent.output(Ticket) # 等价于把 BaseModel 展开为嵌套叶子当 output() 接收的是 BaseModel 时,response 的 get_data_object() 会返回 Pydantic 实例。
纯文本
需要纯文本而不是结构化输出时,不要用 output() —— agent.input("...").start() 直接返回字符串,或 result.get_text()。Schema as Prompt 是给结构化输出用的。
不在范围内
Schema as Prompt 是单次模型请求的 authoring 层,不是:
- JSON Schema 在外部 API 契约场景的替代。
- TriggerFlow 的契约(TriggerFlow 用自己的
set_contract(...))。 - UI 表单定义。
早期把 .output()、TriggerFlow 契约和外部 schema 统一为同一 DSL("Agently DSL")的尝试已归档。每个消费者保留自己的入口;本页只覆盖 prompt 侧的 authoring。
另见
- 输出控制 —— 解析之后的事
- Prompt 管理 —— 槽位与 YAML/JSON 加载
- 术语表:ensure