作者手工实现了一个Agent编排框架,包含动态工具注册、能力基础的路由、权限deny-by-default模型、并行执行和冲突解决。
六个工具通过 @tool(...) 装饰器在模块导入时自动注册——每个工具声明自己的名称、能力集合、权限作用域和 JSON 参数模式。路由器从不看工具名称;它只根据能力查询注册表。添加新工具后,无需修改路由器就能让它可路由——注册表是唯一需要改动的地方。
这六个工具故意跨越全谱:三个价格源(price_alpha/beta/gamma,都是网络源),一个只读的 weather_lookup 和 fx_convert,再加一个 ledger_write 是唯一的写工具。选择三个源——而不是两个——这样多数投票才真正有意义,每个源都带着一个信任优先级和时间戳,使得打破平局的逻辑完全确定。
当被问"AAPL 的当前参考价格是多少?"时,模型看到的是广告能力(price_quote、weather、persist 等),而不是工具本身,然后它选择任务需要的能力。编排器将这些能力解析为具体工具。在本次运行中:通过 LLM 路由 via=llm caps=['price_quote'] → ['price_alpha', 'price_beta', 'price_gamma']。路由会根据注册表进行验证——幻觉能力会被丢弃——并有一个关键字回退被记录为 via=fallback,这样小的 8B 模型永远无法卡住管道。
我运行了同一个"在账本中记录审计备注"的任务两次。在受限的授权范围 ['network','read'] 下,路由到达 ledger_write,但它需要 write 权限——所以被拒绝并记录了日志,运行结果是无法完成这个任务。授予 ['network','read','write'] 权限后,完全相同的路由现在能写入账本条目。唯一的区别是作用域。执行是纯 Python——安全决策从不依赖模型输出。
三个价格源是独立的,所以它们在线程池中并发运行。每个源耗时 0.60s:串行运行是 1.80s 的挂钟时间,并发运行是 0.61s——在完全相同的工具集上测得 2.97× 的加速。这是在同一次运行中做的真实 A/B 测试,不是 README 里的承诺——相同的三个源,一次串联运行一次并发运行,节省时间被打印出来。
三个源没有达成一致:alpha 是 $150.25,beta 是 $172.40,gamma 是 $150.25。一份文档化的、确定的政策来解决它——先多数投票,再信任优先级,最后新鲜度——所以 $150.25 以 2 比 1 票胜出,冲突被记录下来:全部三个价格、谁不同意、以及哪个政策步骤决出了胜负。特意的转折:beta 实际上按优先级是最受信任的源,但多数投票正确地推翻了它。交换政策顺序,赢家就会改变——这正是为什么政策要被写下来,而不是留作隐含的。
即使在温度 0 下,8B 模型也不是完全确定性的,所以重新运行可能用不同措辞表述路由原因或最终答案。但它选择的能力、拒绝、时序形状和冲突赢家是稳定的——因为路由根据注册表验证,权限执行和冲突解决是确定的 Python,不是模型输出。只有路由和最终合成是 LLM。
Live https://dev48v.infy.uk/agentic/project4-orchestrator.html Repo https://github.com/dev48v/agentic-ai-from-zero