先贴个东西。
while llm.should_continue():
msg = llm.chat(history)
if msg.tool_call:
result = run_tool(msg.tool_call)
history.append(result)
else:
break
一个 agent。别装了,这就是你那个"智能体"的核心。拿这九行代码去套市面上那些 agent 框架,底子一模一样。但你看看你同事上周刚提 PR 合进来的那个——原本一个循环能解决的事,上面糊了些什么?
MCP server。编排框架。重试机制。长期记忆。工具注册中心。
services:
orchestrator:
depends_on: [mcp_server, memory_store, tool_registry]
agent:
framework: "langchain"
retries: 3
memory: redis
一个死循环,活生生被撑成一个分布式系统。复杂度翻了几十倍。为了什么?为了"以后可能要并发"、"以后可能要跨进程"。
可能性。可能性是最贵的东西。
工程师最大的懒惰,就是遇到拿不准的取舍,无脑加一层。你问他为什么需要这层抽象,他卡壳了。这层抽象替你省的麻烦,根本抵不过它带来的认知负担。新来个人想读懂你的 agent,得先翻三个库的文档,才能搞明白一句 agent.run("查个数据") 到底在中间经过了多少层转发。
我自己捣鼓玩具存储引擎的时候也干过这种事。核心数据结构改了三版。第一版想做"通用",什么都能存;第二版想做"灵活",什么都能换。最后全砍了,就留两个函数:存一个键,取一个键。
反而跑得最快。
说句题外话。我有时候觉得写代码跟写文章是一码事。一段函数写完,读一遍,觉得哪里啰嗦,回去改;改完再读,还是啰嗦,再改。一个接口定义我能改三遍,跟改一句开场白没区别。代码不是写出来的,是改出来的 😅。
砍,才是工程师真正的活。现在让模型写个函数,它默认给你塞一堆"以防万一"的扩展点。它给的方案默认偏复杂。工程师的活就是往回砍,不是往上加。
凡是有人说"加一层以后好扩展",先让他回答"以后是谁、扩展什么、不扩展会死吗"。答不上来,先别加。
简单的东西能活得更久。你那个 agent,大概率也只需要一个 while 循环。
