TL;DR

本文核心观点:

  1. 设计原则的演进 — 传统 SOLID 原则诞生于面向对象时代,旨在解决类级别设计的耦合问题;在 AI-Native 时代,软件系统的核心单元已从类演变为 Agent,需要全新的设计原则。
  2. 抽象层次的跃迁 — SOLID 原则在 2000-2020 年间指导了数以百万计的软件设计,但在 AI-Native 时代,Agent 不是更好的类,而是完全不同的抽象层次,其局限性日益明显。
  3. 新 SOLID 原则 — 本文提出新 SOLID 原则(SCP/OCP-P/LAP/ISP/DIP),将设计哲学从”对象协作”升维到”Agent 协作”,通过 Capability Contract、Intent Router 和抽象层依赖倒置驾驭这种转变。
  4. 核心洞察 — 一个 Agent 应该只负责一种核心能力,Agent 的输出应该忠实反映其内部推理过程,复杂性来自协作而非单个 Agent 的能力。

SOLID 原则回顾

在重构之前,让我们快速回顾 Robert C. Martin 在 2000 年提出的 SOLID 原则:

单一职责原则 (SRP)

一个类应该只有一个引起它变化的原因。

开闭原则 (OCP)

对扩展开放,对修改关闭。

里氏替换原则 (LSP)

子类型必须能够替换其基类型而不改变程序正确性。

接口隔离原则 (ISP)

客户端不应该被迫依赖它们不使用的接口。

依赖倒置原则 (DIP)

高层模块不应该依赖低层模块,两者都应该依赖抽象。


面向对象时代的 SOLID 局限

SOLID 原则在 2000-2020 年间指导了数以百万计的软件设计,但在 AI-Native 时代,它们的局限性日益明显:

💡 Key Insight

传统思维追求 100% 确定性,但 AI 系统天然是概率性的——这一根本差异渗透到从执行模型到状态管理的每一个设计维度。

局限一:假设了确定性的执行模型

传统 SOLID 假设:

  • 方法调用是同步确定
  • 返回值是可预测的
  • 副作用是可控的

但 Agent 的行为是概率性的:

  • 同样的输入可能产生不同输出
  • 执行时间不确定
  • 可能调用外部工具产生不可预测副作用

局限二:忽视了上下文和状态管理

传统设计将状态封装在对象内部,但 Agent 需要:

  • 上下文窗口管理:有限的 token 预算
  • 长期记忆:跨会话的信息保持
  • 工作记忆:当前任务的临时状态

局限三:无法处理涌现行为

传统设计追求可预测性,但 Agent 系统的一个重要特性是涌现——整体行为不等于部分之和。

当多个 Agent 协作时,会产生设计者未明确编程的行为。SOLID 原则无法指导这种涌现系统的设计。

局限四:接口定义过于静态

传统接口是编译时契约:

但 Agent 的能力是动态的:

  • 通过 prompt 工程可以”教授”新能力
  • 工具调用列表可以动态扩展
  • 不同模型版本能力差异巨大

局限五:忽视了反馈和学习循环

传统软件是”编写一次,运行多次”,但 AI 系统需要:

  • 从反馈中学习
  • 持续优化 prompt
  • 版本化管理模型和策略
维度 传统软件 AI-Native 系统
正确性 确定性 概率性
扩展方式 继承/组合 Prompt 工程 + 工具注册
状态管理 对象字段 上下文 + 记忆
接口 静态类型 动态能力描述
演化 版本发布 持续学习

AI-Native 时代的 SOLID 重构

面对上述局限,我们需要一套新的设计原则。这不是对 SOLID 的否定,而是在更高抽象层次上的重构。

💡 Key Insight

Agent 不是更好的类,而是完全不同的抽象层次——这一认知转变是理解新 SOLID 原则的前提。

从 Class 到 Agent:抽象层次的跃迁

关键区别:

特性 Class Agent
激活方式 方法调用 Intent + Context
执行逻辑 确定性代码 LLM + Tool Calling
状态管理 字段封装 Context Window + Memory
能力扩展 继承/组合 Prompt 调整 + Tool 注册
交互模式 Request/Response 多轮对话 + 自主决策

从 Interface 到 Intent:契约形式的转变

传统接口定义”能做什么”:

Intent 定义”意图和期望结果”:

核心转变总结

核心转变总结


新 SOLID:适用于 Agent 协作的设计原则

基于上述分析,我提出适用于 AI-Native 开发的新 SOLID 原则

💡 Key Insight

一个 Agent 应该只负责一种核心能力,并通过清晰的 Capability Contract 定义其边界——这是避免”上帝 Agent”反模式的关键。

S - 单一能力原则 (SCP)

一个 Agent 应该只负责一种核心能力,并通过清晰的 Capability Contract 定义其边界。

核心思想

  • 每个 Agent 专注于一个领域(如数据查询、代码生成、客户服务)
  • 避免”上帝 Agent”试图做所有事情
  • 通过 Capability Contract 明确声明能力范围

对比表格

传统 SRP 新 SCP
单一变化原因 单一核心能力
职责 = 业务功能 能力 = 领域专精 + 工具组合
通过类拆分实现 通过 Agent 专业化 + Contract 定义
编译时检查 运行时 Capability 匹配

O - 提示工程开闭原则 (OCP-P)

Agent 的核心行为应该通过 Prompt 模板扩展,而非修改代码。

核心思想

  • 将行为逻辑外置到 Prompt 模板
  • 通过 Prompt 变量和模板继承实现扩展
  • 支持 A/B 测试和动态行为切换

L - 忠实表达原则 (LAP)

Agent 的输出应该忠实反映其内部推理过程,而非隐藏或伪造。

核心思想

  • Agent 应该”展示其工作”(show your work)
  • 区分”推理过程”和”最终输出”
  • 便于调试、审计和信任建立

对比表格

传统 LSP 新 LAP
子类型可替换父类型 输出应忠实反映内部过程
关注类型兼容性 关注透明度和可审计性
编译时类型检查 运行时推理链验证
防止继承误用 防止”幻觉”和不可信输出

I - 意图隔离原则 (ISP)

复杂的用户请求应该被分解为独立的 Intent,每个 Intent 由专门的 Agent 或 Tool 处理。

核心思想

  • 使用 Intent Router 分解复合请求
  • 每个 Intent 对应单一、明确的目标
  • 避免强迫一个 Agent 处理它不擅长的任务

D - 抽象层依赖倒置 (DIP)

Agent 不应该直接依赖具体的 LLM 或工具实现,而应该依赖抽象的 Capability Interface。

核心思想

  • 定义 Capability 抽象接口
  • LLM、工具、记忆系统都实现这些接口
  • 支持灵活替换(模型升级、工具切换)

实战:应用新 SOLID 设计 Agent 系统

让我们通过一个完整的实例来演示如何应用新 SOLID 原则设计一个多 Agent 系统。

场景:智能客服系统

我们需要设计一个能够处理多种客户请求的智能客服系统:

  • 订单查询
  • 退款处理
  • 技术支持
  • 产品推荐

系统设计

系统设计

完整代码实现

以下代码展示了一个简化但完整的多 Agent 客服系统实现,涵盖 Intent 路由、Agent 专业化分工和 Capability 抽象接口。

Capability 接口定义

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List, Optional

@dataclass
class Capability:
    name: str
    description: str
    input_types: List[str]
    output_type: str

class CapabilityContract(ABC):
    @abstractmethod
    def get_capabilities(self) -> List[Capability]:
        pass

    @abstractmethod
    def can_handle(self, intent: str) -> bool:
        pass

OrderQueryAgent 实现

class OrderQueryAgent(CapabilityContract):
    def get_capabilities(self) -> List[Capability]:
        return [
            Capability(
                name="order_query",
                description="根据订单号或用户信息查询订单状态",
                input_types=["order_id", "user_id"],
                output_type="OrderInfo"
            )
        ]

    def can_handle(self, intent: str) -> bool:
        return intent in ["query_order", "check_status"]

    async def execute(self, context: dict) -> dict:
        order_id = context.get("order_id")
        # 查询逻辑
        return {"status": "shipped", "eta": "2-3 days"}

Intent Router

class IntentRouter:
    def __init__(self, agents: List[CapabilityContract]):
        self.agents = agents

    def route(self, user_input: str) -> tuple[str, CapabilityContract]:
        intent = self.classify_intent(user_input)
        for agent in self.agents:
            if agent.can_handle(intent):
                return intent, agent
        raise ValueError(f"No agent can handle intent: {intent}")

    def classify_intent(self, text: str) -> str:
        # 简化的意图分类逻辑
        keywords = {"order": "query_order", "refund": "process_refund"}
        for key, intent in keywords.items():
            if key in text.lower():
                return intent
        return "general_inquiry"

LLM 抽象层 (DIP 实现)

class LLMProvider(ABC):
    @abstractmethod
    async def complete(self, prompt: str, context: dict) -> str:
        pass

class OpenAIProvider(LLMProvider):
    def __init__(self, api_key: str):
        self.api_key = api_key

    async def complete(self, prompt: str, context: dict) -> str:
        # OpenAI API 调用实现
        response = await openai.ChatCompletion.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}]
        )
        return response.choices[0].message.content

新 SOLID 原则应用总结

在这个实战示例中,我们应用了新 SOLID 原则:

原则 应用位置 具体实现
SCP OrderQueryAgent, RefundAgent 每个 Agent 专注单一能力,通过 CapabilityContract 定义边界
OCP-P PromptTemplate 继承体系 通过模板继承扩展行为,无需修改代码
LAP AgentResponse.reasoning 要求 LLM 输出推理过程,展示其工作
ISP IntentRouter 将复合请求分解为独立 Intent,路由到专门 Agent
DIP LLMProvider, ToolProvider, MemoryProvider Agent 依赖抽象接口,可灵活替换实现

反直觉洞察

在实践新 SOLID 原则的过程中,有一些反直觉的洞察值得分享:

💡 Key Insight

AI 系统天然是概率性的,试图消除不确定性反而会设计出脆弱的系统——拥抱概率性,才是设计 AI-Native 系统的正确姿态。

洞察一:”确定性”是一种奢望,拥抱概率性

💡 Key Insight

传统思维追求 100% 确定性,但 AI 系统天然是概率性的。

反直觉做法

  • 不要试图用复杂规则消除不确定性
  • 而是设计”不确定性友好”的架构
  • 让系统能够表达”我不确定”并优雅降级

洞察二:Prompt 是比代码更重要的”代码”

💡 Key Insight

Prompt 工程不是临时技巧,而是核心工程实践。

反直觉做法

  • 像对待代码一样对待 Prompt:版本控制、测试、Code Review
  • Prompt 模板化、参数化、继承化
  • 建立 Prompt 设计规范

洞察三:Agent 越”笨”,系统越聪明

💡 Key Insight

试图让一个 Agent 做所有事情会导致”上帝 Agent”反模式。

反直觉做法

  • 让每个 Agent 尽可能”笨”和专注
  • 复杂性来自协作,而非单个 Agent 的能力
  • 像设计生态系统一样设计 Agent 系统

洞察四:上下文管理比算法更重要

💡 Key Insight

在 AI-Native 系统中,如何管理上下文(context window)往往比算法选择更重要。

反直觉做法

  • 投入大量精力优化上下文压缩和选择
  • 建立记忆层次结构(工作记忆/短期记忆/长期记忆)
  • 主动遗忘和总结是必要的能力

洞察五:测试 AI 系统需要新范式

💡 Key Insight

传统单元测试假设确定性,但 AI 系统需要新的测试范式。

反直觉做法

  • 使用”属性测试”而非”值测试”
  • 建立评估基准(evaluation benchmark)
  • 人工在环(human-in-the-loop)是必要的

工具链与最佳实践

推荐工具链

类别 工具 用途
LLM 抽象 LangChain, LlamaIndex 统一不同 LLM 接口
Prompt 管理 LangSmith, PromptLayer Prompt 版本控制和测试
Agent 框架 AutoGen, CrewAI, OpenAI Agents SDK 多 Agent 协调
评估 TruLens, RAGAS, Arize Agent 性能评估
监控 Langfuse, Weights & Biases 生产监控和调试
记忆 Chroma, Pinecone, Weaviate 向量存储

最佳实践清单

SCP - 单一能力原则

  • 每个 Agent 有明确的 Capability Contract
  • 避免 Agent 的能力列表超过 5 个
  • 定期审查 Agent 的边界是否清晰

OCP-P - 提示工程开闭原则

  • 所有 Prompt 使用模板化
  • Prompt 变更通过 A/B 测试验证
  • 建立 Prompt 设计规范文档

LAP - 忠实表达原则

  • 关键 Agent 必须输出 reasoning chain
  • 建立 confidence score 阈值机制
  • 高不确定性时主动寻求人工介入

ISP - 意图隔离原则

  • 使用专门的 Intent Router
  • 复合意图自动分解
  • 每个 Intent 对应单一明确的 Agent

DIP - 抽象层依赖倒置

  • LLM、工具、记忆都通过接口依赖
  • 支持运行时切换实现
  • 建立清晰的 capability 注册机制

设计审查清单

在部署 Agent 系统前,问自己这些问题:

架构层面

  1. 每个 Agent 的能力边界是否清晰?
  2. 如果替换底层 LLM,需要修改多少代码?
  3. 系统的涌现行为是否可预测和可控?

运维层面

  1. 如何监控 Agent 的 confidence score 分布?
  2. 失败时如何优雅降级?
  3. 如何追踪和调试多 Agent 协作流程?

安全层面

  1. 工具调用的权限边界在哪里?
  2. 如何防止 Prompt 注入攻击?
  3. 敏感数据如何在上下文中流转?

结语

从 SOLID 到新 SOLID:一场范式转移

Robert C. Martin 在 2000 年提出 SOLID 原则时,软件世界正从过程式编程向面向对象编程转变。那些原则帮助数以百万计的开发者写出了更好的代码。

💡 Key Insight

设计原则是手段,不是目的——原则是为了解决特定问题,而非教条;在 AI-Native 时代,接受概率性、拥抱涌现性,比固守确定性思维更能设计出健壮的系统。

今天,我们站在另一个范式转移的门槛上:从面向对象到 AI-Native。

这不是对过去的否定,而是在更高抽象层次上的重构。

  面向对象时代 AI-Native 时代
核心问题 如何组织代码 如何协调智能
设计单元 Class Agent
主要挑战 耦合、内聚 涌现、不确定性
解决手段 多态、封装 Intent、Context、Tool Calling
关键技能 算法、数据结构 Prompt 工程、系统设计

关键启示

  1. Agent 不是更好的类,而是完全不同的抽象——不要试图用面向对象思维套在 Agent 上

  2. 设计原则是手段,不是目的——原则是为了解决特定问题,而非教条

  3. 在不确定性中设计——接受概率性,拥抱涌现性

  4. Prompt 是第一公民——像对待代码一样对待 Prompt

  5. 协作产生智慧——让多个简单 Agent 协作,胜过单个复杂 Agent

展望未来

新 SOLID 原则不是终点,而是起点。随着 AI 技术的演进,我们可能需要在以下几个方面继续探索:

  • 自适应系统:Agent 能够动态调整自己的能力边界
  • 联邦学习:跨系统、跨组织的 Agent 协作
  • 伦理和治理:如何在设计阶段就嵌入负责任的 AI 原则

正如 Charlie Munger 所说:“弄清楚什么是有效的方法,然后去实践它。”

新 SOLID 原则是我们在 AI-Native 软件开发实践中总结出的有效方法。希望它能帮助你在构建 Agent 系统时少走弯路。


深度阅读时间:约 14 分钟

延伸阅读

  1. Robert C. Martin - 《Clean Architecture》
  2. Andrew Ng - AI Agent 设计模式系列
  3. OpenAI - Function Calling Best Practices
  4. Anthropic - Contextual AI Design Patterns

系列导航


“The best time to plant a tree was 20 years ago. The second best time is now.”

开始构建你的 AI-Native 系统吧。