Agent 开发进阶(十):系统提示词不是大字符串,而是可维护的组装流水线

3 阅读8分钟

Agent 开发进阶(十):系统提示词不是大字符串,而是可维护的组装流水线

本文是「从零构建 Coding Agent」系列的第十篇,适合想让系统提示词更灵活、可维护的开发者。

先问一个问题

你是怎么管理系统提示词的?

  • 写成一大段固定的硬编码文本?
  • 每次有新工具或新技能时,手动修改提示词?
  • 把所有信息都塞进一个大字符串里?

如果你的答案是肯定的,那么当系统功能越来越多时,你会遇到越来越多的麻烦。

系统提示词的「维护困境」问题

到了这一阶段,你的 Agent 已经具备了多种能力:

  • 核心循环运行
  • 工具使用与分发
  • 会话内规划
  • 子智能体机制
  • 技能加载
  • 上下文压缩
  • 权限系统
  • Hook 系统
  • Memory 系统

但随着功能的增加,系统提示词变得越来越难维护:

  • 工具列表会变
  • skills 会变
  • memory 会变
  • 当前目录、日期、模式会变
  • 某些提醒只在这一轮有效,不该永远塞进系统说明

所以到了这个阶段,系统提示词不能再当成一块硬编码文本。

它应该升级成:

由多个来源共同组装出来的一条流水线。

系统提示词的核心设计:组装流水线

用一个图来表示系统提示词的组装流程:

core (核心身份和规则)
  +
tools (工具列表)
  +
skills (技能元信息)
  +
memory (记忆内容)
  +
claude_md (长期规则说明)
  +
dynamic (动态环境信息)
  =
final system prompt

关键点只有一个:

system prompt 的关键不是「写一段很长的话」,而是「把不同来源的信息按清晰边界组装起来」。

几个必须搞懂的概念

System Prompt(系统提示词)

给模型的系统级说明,通常负责告诉模型:

  • 你是谁
  • 你能做什么
  • 你应该遵守什么规则
  • 你现在处在什么环境里

组装流水线

意思是:

  • 不同信息来自不同地方
  • 最后按顺序拼接成一份输入
  • 它不是一个死字符串,而是一条构建过程

动态信息

有些信息经常变化,例如:

  • 当前日期
  • 当前工作目录
  • 本轮新增的提醒

这些信息不适合和所有稳定说明混在一起。

最小实现

1. System Prompt Builder

class SystemPromptBuilder:
    """系统提示词构建器"""
    
    def __init__(self, config=None):
        self.config = config or {}
        self.tools = []
        self.skills = []
        self.memory_manager = None
        self.claude_md_path = None
    
    def set_tools(self, tools):
        """设置工具列表"""
        self.tools = tools
        return self
    
    def set_skills(self, skills):
        """设置技能列表"""
        self.skills = skills
        return self
    
    def set_memory_manager(self, memory_manager):
        """设置记忆管理器"""
        self.memory_manager = memory_manager
        return self
    
    def set_claude_md_path(self, path):
        """设置 CLAUDE.md 路径"""
        self.claude_md_path = path
        return self
    
    def build(self):
        """构建系统提示词"""
        parts = []
        
        # 1. 核心身份和行为说明
        parts.append(self._build_core())
        
        # 2. 工具列表
        parts.append(self._build_tools())
        
        # 3. 技能元信息
        parts.append(self._build_skills())
        
        # 4. 记忆内容
        parts.append(self._build_memory())
        
        # 5. CLAUDE.md 指令链
        parts.append(self._build_claude_md())
        
        # 6. 动态环境信息
        parts.append(self._build_dynamic())
        
        # 过滤空部分并拼接
        return "\n\n".join(p for p in parts if p)
    
    def _build_core(self):
        """构建核心身份和行为说明"""
        return """# 你是一个智能开发助手

## 你的角色
你是一个专业的编程助手,擅长解决各种开发问题,帮助用户完成代码相关的任务。

## 你的职责
- 理解用户需求
- 分析问题
- 提供专业的解决方案
- 执行相关工具
- 清晰地解释你的思路

## 你的规则
- 保持专业和友好
- 提供准确的信息
- 遇到不确定的问题时,先查询再回答
- 保护用户隐私
- 拒绝执行危险操作
"""
    
    def _build_tools(self):
        """构建工具列表说明"""
        if not self.tools:
            return ""
        
        tool_descriptions = []
        for tool in self.tools:
            name = tool.get("name")
            description = tool.get("description", "")
            parameters = tool.get("parameters", {})
            
            param_str = []
            for param_name, param_info in parameters.items():
                param_desc = param_info.get("description", "")
                param_type = param_info.get("type", "string")
                param_str.append(f"  - {param_name} ({param_type}): {param_desc}")
            
            tool_descriptions.append(f"- **{name}**: {description}\n" + "\n".join(param_str))
        
        return f"""# 可用工具

{"\n".join(tool_descriptions)}
"""
    
    def _build_skills(self):
        """构建技能元信息"""
        if not self.skills:
            return ""
        
        skill_descriptions = []
        for skill in self.skills:
            name = skill.get("name")
            description = skill.get("description", "")
            skill_descriptions.append(f"- **{name}**: {description}")
        
        return f"""# 可用技能

{"\n".join(skill_descriptions)}
"""
    
    def _build_memory(self):
        """构建记忆内容"""
        if not self.memory_manager:
            return ""
        
        return self.memory_manager.get_all_for_context()
    
    def _build_claude_md(self):
        """构建 CLAUDE.md 指令链"""
        if not self.claude_md_path or not self.claude_md_path.exists():
            return ""
        
        try:
            content = self.claude_md_path.read_text(encoding="utf-8")
            return f"""# 项目规则 (CLAUDE.md)

{content}
"""
        except Exception:
            return ""
    
    def _build_dynamic(self):
        """构建动态环境信息"""
        import datetime
        import os
        
        dynamic_parts = [
            f"**当前日期**: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"**当前目录**: {os.getcwd()}",
        ]
        
        # 添加当前模式
        current_mode = self.config.get("mode", "default")
        dynamic_parts.append(f"**当前模式**: {current_mode}")
        
        # 添加本轮提醒
        reminder = self.config.get("reminder", "")
        if reminder:
            dynamic_parts.append(f"**本轮提醒**: {reminder}")
        
        return f"""# 动态环境信息

{"\n".join(dynamic_parts)}
"""

2. 集成到 Agent Loop

def create_system_prompt(config):
    """创建系统提示词"""
    builder = SystemPromptBuilder(config)
    
    # 设置工具
    tools = [
        {
            "name": "read_file",
            "description": "读取文件内容",
            "parameters": {
                "file_path": {"type": "string", "description": "文件路径"}
            }
        },
        {
            "name": "write_file",
            "description": "写入文件内容",
            "parameters": {
                "file_path": {"type": "string", "description": "文件路径"},
                "content": {"type": "string", "description": "文件内容"}
            }
        },
        # 其他工具...
    ]
    builder.set_tools(tools)
    
    # 设置技能
    skills = [
        {"name": "code_review", "description": "代码审查技能"},
        {"name": "debug", "description": "调试技能"},
        # 其他技能...
    ]
    builder.set_skills(skills)
    
    # 设置记忆管理器
    from memory_manager import MemoryManager
    memory_manager = MemoryManager()
    builder.set_memory_manager(memory_manager)
    
    # 设置 CLAUDE.md 路径
    from pathlib import Path
    claude_md_path = Path("./CLAUDE.md")
    builder.set_claude_md_path(claude_md_path)
    
    # 构建系统提示词
    return builder.build()

def agent_loop():
    """智能体主循环"""
    # 配置
    config = {
        "mode": "default",
        "reminder": "本次任务:修复认证模块的登录问题"
    }
    
    # 创建系统提示词
    system_prompt = create_system_prompt(config)
    
    # 初始化状态
    state = {
        "system": system_prompt,
        "messages": []
    }
    
    # 主循环
    while True:
        # 调用模型
        response = call_model(state["messages"], system=state["system"])
        
        # 处理响应...

核心边界区分

1. 稳定说明 vs 动态提醒

类型内容特点
稳定说明身份、规则、工具、技能、长期约束不常变化,适合放在 system prompt 中
动态提醒当前日期、工作目录、本轮任务、临时状态每次都可能变化,适合作为动态部分

2. System Prompt vs System Reminder

类型适合放的内容特点
System Prompt身份、规则、工具、长期约束相对稳定,每轮变化不大
System Reminder本轮临时需要的补充上下文、当前变动的状态只在本轮有效,下轮可能不同

3. 不同信息来源的职责

来源职责特点
Core核心身份和行为规则最稳定的部分
Tools工具列表和使用说明随着工具增减而变化
Skills技能元信息随着技能加载而变化
Memory跨会话记忆随着记忆的增删而变化
CLAUDE.md长期规则说明相对稳定,项目级配置
Dynamic动态环境信息每次都可能不同

新手最容易犯的 4 个错

1. 把 system prompt 写成固定字符串

# ❌ 错误
system_prompt = """你是一个智能助手... 这里有很多工具... 还有很多规则..."""

# ✅ 正确
# 使用 SystemPromptBuilder 动态构建
builder = SystemPromptBuilder()
system_prompt = builder.build()

2. 把所有变化信息都塞进 system prompt

# ❌ 错误
system_prompt = f"""你是一个智能助手...

当前日期: {datetime.now()}
当前目录: {os.getcwd()}
本次任务: {current_task}
"""

# ✅ 正确
# 把动态信息放在动态部分
builder = SystemPromptBuilder(config={"reminder": "本次任务:修复登录问题"})

3. 把 CLAUDE.md、memory、skills 写成同一种东西

# ❌ 错误
system_prompt = f"""你是一个智能助手...

{load_claude_md()}
{load_memory()}
{load_skills()}
"""

# ✅ 正确
# 分开处理不同来源
builder.set_claude_md_path(Path("./CLAUDE.md"))
builder.set_memory_manager(memory_manager)
builder.set_skills(skills)

4. 不区分静态和动态部分

# ❌ 错误
system_prompt = """你是一个智能助手...

当前日期: 2024-01-01
当前目录: /home/user
"""

# ✅ 正确
# 动态部分每次都重新生成
builder = SystemPromptBuilder()
system_prompt = builder.build()  # 每次都会重新生成动态部分

为什么这很重要

因为一个可维护的系统,不应该把所有信息都混在一起。

系统提示词组装流水线让你能够:

  1. 更好维护:每个部分职责清晰,修改方便
  2. 更好测试:可以单独测试每个部分的生成效果
  3. 更好扩展:新增工具、技能时,自动更新到系统提示词
  4. 更好管理:稳定部分和动态部分分开处理

推荐的实现步骤

  1. 第一步:创建 SystemPromptBuilder 类
  2. 第二步:实现各个构建方法(core、tools、skills、memory、claude_md、dynamic)
  3. 第三步:在 Agent Loop 中使用构建器生成系统提示词
  4. 第四步:根据需要调整各部分的内容和顺序
  5. 第五步:测试不同场景下的系统提示词效果

系统提示词与后续章节的关系

  • s10 系统提示词:把前面所有功能组织成一份清楚的系统输入
  • s11 错误恢复:会使用系统提示词来指导错误处理
  • s12 任务系统:会在系统提示词中添加任务相关的信息
  • s19 MCP 插件:会通过系统提示词向模型介绍新的能力

所以系统提示词是连接所有功能的重要环节。

下一章预告

有了系统提示词组装流水线,你的 Agent 已经具备了灵活、可维护的系统说明能力。下一章我们将探讨错误恢复机制,让 Agent 在遇到错误时能够优雅地处理并继续工作。


一句话总结:system prompt 的关键不是「写一段很长的话」,而是「把不同来源的信息按清晰边界组装起来」。


如果觉得有帮助,欢迎关注,我会持续更新「从零构建 Coding Agent」系列文章。