“帮我做得更有秋天的感觉”,可以开启讨论,却很难结束一次交付。模型不知道要保留哪些素材,也不知道“更好看”到底对应什么检查。最后常常得到一份流畅提案,和一堆没人敢覆盖的文件。
我给轻量创作工具设计任务单时,会先写可以观察的约束:输入来自哪里,允许改什么,输出几份,谁来判断完成。情绪词可以留在风格栏,但不代替这些字段。比如把一段代码改写成短诗,风格可以安静、简洁;十四行、引用哪些源码、不得覆盖原文件,则需要明确写出来。
可携带的说明,不等于执行权
10 月 22 日,AAIF 接纳了 Agent Skills、OpenResponses、OpenEnv 和 OpenSandbox。它们涉及不同层次的工作流与运行接口。这个进展值得关注,但不能据此假设任何任务描述都自带安全隔离。
Agent Skills 规范把name、description等信息放进SKILL.md,并允许附带脚本与参考资料。对独立产品,我会借鉴这种“说明与素材放在一起”的方式,同时把真正的文件写入权限交给程序控制。文本里写了允许,并不意味着操作系统已经限制了其他路径。
下面把任务单作为普通 JSON 数据处理。检查器要求输入素材、输出目标、允许动作和验收项都存在;随后只产生待确认摘要,不直接运行提案里的命令。approved由调用方传入,这只是演示流程字段,不能用一个客户端布尔值代替生产环境的身份验证和授权。
验收项要能说“不”
“氛围温柔”适合人工评议;“封面一张、标题一致、原文件保留”可以逐项核对。两者最好分开记录。模型说自己完成了,不是证据;程序生成了文件,也不代表图片没有多余肢体、文字没有错字。一次真正的交付,应把产物与检查结果一起交回来。
运行node brief.js能验证缺项被拒绝,以及未批准时只返回提案。本例没有访问文件系统、调用模型或生成图片。它的价值是把创意讨论变成一份可回看、可拒绝的约定。留出这一步,才有机会把时间花在作品上,而不是反复猜对方的意思。
可独立运行的核心例子
function validate(task) { for(const k of ['inputs','outputs','allowedActions','acceptance']) { if(!Array.isArray(task[k]) || !task[k].length || task[k].some(x=>typeof x!=='string' || !x.trim())) throw Error('任务单缺少有效字段:'+k); } if(!task.goal || typeof task.goal!=='string') throw Error('缺少目标'); return task; } function prepare(task,approved=false) { validate(task); return { goal:task.goal, inputs:[...task.inputs], outputs:[...task.outputs], allowedActions:[...task.allowedActions], acceptance:[...task.acceptance], state:approved?'已批准,交给受限执行器':'仅提案,等待确认' }; } const task={ goal:'把代码改写成十四行短诗', inputs:['用户提供且允许引用的代码片段'], outputs:['poem-v1.md'], allowedActions:['读取指定代码','写入新文件'], acceptance:['恰好十四行','不覆盖源文件','人工复核代码含义与诗句'] }; if(!prepare(task).state.includes('等待确认')) throw Error('不应默认执行'); let rejected=false; try{prepare({...task,inputs:[]});}catch{rejected=true;} if(!rejected) throw Error('空输入应被拒绝'); console.log(JSON.stringify(prepare(task),null,2));