一个小循环,先回答谁决定下一步
Mini Agent 是一个命令行项目:用户给出自然语言任务,模型选择工具,程序执行,再把结果交回下一轮。工具包括工作目录中的文件操作、文本搜索和计算等。
我在面试研习社练习“Agent 和工作流有什么区别”时,最容易拿这个循环举例。这里下一步读哪个文件、换哪个工具由模型依据观察决定;代码负责工具集合、校验、记录和停止条件。模型调用次数多,不是判断它是不是 Agent 的充分条件。
一轮只接受一份明确决定
schemas.py 定义两种响应:action 或 final。下面是一份动作格式示例,实际参数仍要符合具体工具定义:
{
"type": "action",
"reason": "先查看工作目录中的说明文件",
"tool": "read_file",
"arguments": { "path": "README.md" }
}
Pydantic 严格模型会拒绝多余字段、错误类型和不符合约定的结构。解析器不会为了让调用继续而猜测模型原意,执行端也不把一段任意文本直接当作命令运行。
不过 JSON 合法仍只是第一步。未知工具名需要由注册表拒绝;参数还要经过工具本身的校验;文件路径必须满足工作目录约束。协议验证和执行权限不能互相代替。
把错误变成可以利用的观察
工具返回统一的成功数据或错误对象。比如路径不存在、参数无效、未知工具,各有稳定的错误代码,模型可以据此修正行动。
协议错误也会形成 Observation 进入后续上下文,而不是直接伪装成一次成功的工具结果。下一轮如果仍能继续,模型应该看到自己哪里没有满足契约。
模型服务异常则对应另一类结束状态。当前循环会区分 completed、unable、max_rounds 和 llm_error,不会把所有退出都包装成“任务完成”。
相对路径也可能跑出工作目录
只检查字符串是不是以工作目录开头不够。../ 可以向上跳转,符号链接和 Windows junction 也可能把看似内部的路径指向外部。
项目的 Workspace 会解析真实路径,再检查结果是否位于固定根目录下;同时处理 Windows 盘符、绝对路径及 NTFS 备用数据流一类输入。Path.resolve 的路径规范化与链接解析行为,可对照 Python 官方文档。
这些检查是文件工具的访问约束,不等同于操作系统级沙箱。不能因为有一个 Workspace 类,就推导出程序获得了容器隔离、任意代码执行安全性或对所有文件系统竞争的绝对保护。
Trace 要能解释动作与结果
agent.py 会记录用户任务、决定、工具调用、结果、轮次和结束原因。Trace 的用途是回放“它做了哪些可观察动作,分别得到了什么”,不是保存模型完整的内部思考。
排查一次失败时,我会先看最后一个成功的工具动作,再看错误是否进入了后续观察;接着检查模型有没有换参数、换路径,还是重复同一个失败动作直到步数耗尽。
这也提醒我,轮次上限只约束循环次数,并不自动等于总费用或墙上时间上限。描述项目能力时要把程序真实提供的限制逐项说清楚。
模型说 completed,还需要看产物
如果任务是从 CSV 计算总额并写出报告,模型返回“完成”并不足够。还应检查报告是否存在、汇总值是否与输入一致、没有偷偷覆盖原文件。搜索 TODO 的任务,则需要核对覆盖了哪些文件,以及结果能否回到原位置。
项目交付里把三个实际任务的输入、产物和 Trace 分开保存,这种组织方式比只截一张最终回答更容易验收。它仍不意味着通用任务已经自动得到可靠评分。
读完单 Agent 循环,再看洛谷工作台的多角色协作,就能更清楚地区分两件事:增加角色改变了任务分工,执行边界仍然需要程序落实。