从理论到实践:深度解析Agent记忆系统与ReAct框架,附小红书爆款案例
书接上文,我们继续构建智能体(Agent)的探索之旅。此前,我们致力于实现一个简单的智能体原型,并带领大家进行实操。鉴于内容篇幅,该主题被分为上下两篇。本文作为下篇,将聚焦于三大核心模块:记忆系统、ReAct框架以及一个小红书爆款内容发布的实践案例。
记忆系统:构建智能体的海马体
真正实践过复杂AI项目的开发者会深刻理解,在AI应用层,最具挑战性的环节往往是:数据如何与AI进行有效交互。
例如,某些生产级的复杂AI项目,其代码量可能仅在一万行左右,但所依赖的知识库却异常庞大。这里存在着显著的非对称性,其结果便是:在复杂的AI项目中,高达80%的开发时间都投入在了处理数据相关的问题上!
因此,我们格外关注复杂AI项目中AI与数据交互的范式(最佳实践)。正是在此基础上,衍生出了许多专业术语:短期记忆、长期记忆、语义记忆、情景记忆……
所有这些概念共同构成了智能体的记忆系统。如果说大型语言模型(LLM)是智能体的大脑,负责思考与决策;那么记忆(Memory)就是智能体的海马体,负责记录经验与知识。
LLM有一个核心特性:无状态性。对于模型而言,每一次调用都是全新的开始。无论之前的对话多么深入,一旦开启新一轮交互,它就会将此前发生的一切彻底遗忘。
为了让智能体具备“记忆”能力,就必须构建一套外部的记忆系统。这套系统远不止简单地“保存聊天记录”,它需要解决三个核心的工程挑战:
- 记在哪里?(存储机制:数据库选型)
- 怎么记住?(写入策略:短期与长期)
- 怎么想起?(检索机制:RAG与检索)
在工程语境下,记忆指的是模型在当前输入之外,仍然能够访问和使用的信息集合。这些信息可能来源于历史对话、外部存储或系统内部状态,但其核心目标始终如一:为当前的推理过程提供必要的上下文补充。
从内容性质上划分,智能体中的记忆通常可以分为三类:
- 情景记忆:记录具体发生的事件或会话片段,例如用户说过的话、一次任务执行过程中的中间决策。
- 语义记忆:记录经过抽象提炼的稳定信息,例如用户的偏好、已验证的事实、总结后的结论。
- 程序性记忆:记录“如何执行任务”,例如可用的工具、技能、流程模板或固定的执行策略。
这是一种逻辑上的分类,并不等同于具体的存储或实现方式。在实际落地时,这些记忆往往会以不同的工程形态存在。
常见的记忆工程模式
在实际的系统中,很少直接实现抽象的“情景记忆”或“语义记忆”,而是通过以下几种常见的工程模式来承载它们:

上下文记忆
上下文记忆是最基础的实现方式。其原理是将历史对话内容原样拼接到当前的提示词(Prompt)中,一并发送给模型。模型通过“看到”先前的对话来保持语义上的连贯性。
这种方式实现成本极低,适合用于原型验证或短对话场景。但它受限于模型的上下文长度(Token)上限,对话越长,成本越高,且无法支持跨会话或长期记忆。从本质上讲,它是一种短期、一次性的情景记忆。
滑动窗口记忆
滑动窗口记忆是在上下文记忆基础上的一种优化策略,即只保留最近固定轮数的对话,超出窗口的旧内容会被直接丢弃。它主要解决的不是“记忆能力”问题,而是“Token成本控制”问题。
在工程上,可以将其理解为情景记忆的生命周期管理机制。它适用于上下文有效期明确、业务流程较短的场景。然而,一旦关键信息被移出窗口,就会永久丢失。
摘要记忆
摘要记忆通过调用模型对历史对话进行压缩,将大量的情景记忆转换为一小段简要描述,并在后续对话中使用该摘要来替代原始内容。
这种方式在控制成本和扩展上下文长度方面具有明显优势。但摘要过程不可避免地会造成信息丢失,其质量高度依赖于模型的能力。因此,它更适合用于保留“整体脉络”,而不适用于那些依赖精确细节的场景。
从记忆类型来看,摘要记忆本质上是将情景记忆转化为一种低精度的语义记忆。
向量记忆
向量记忆是一种典型的长期记忆实现方式。其核心做法是将对话内容、经验或用户偏好转化为向量(嵌入)后,存入向量数据库。在需要时,通过计算语义相似度来检索相关内容。
这种方式不受单次对话长度的限制,适合长期知识积累和跨会话记忆。但检索结果是基于“语义相似”而非“精确匹配”,且实现复杂度高于前几种方式。它是当前智能体系统中最常见的语义记忆工程实现。
记忆存储方案
某些信息需要被持久化存储,这有多种目的:保存单次会话内的完整对话历史;支持在同一会话中进行多轮交互,使AI能访问历史消息;保证消息的顺序和完整性;提供高效的查询与加载机制;支持基于语义的检索。
根据项目需求和复杂度,通常涉及以下几类存储方案:
- 关系型数据库:擅长结构化存储,查询方便,技术成熟稳定,支持ACID事务。
- 本地JSON文件:无需搭建数据库,操作简单,便于保存和读取整个会话状态。
- 向量数据库:专为高维向量设计,支持高效的相似度检索(语义搜索)。
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| MySQL / PostgreSQL | 功能强大稳定,支持高并发 | 部署和维护成本相对较高 | 生产级服务 |
| SQLite | 单文件、零配置,支持完整SQL | 并发能力弱,适合单机应用 | 本地智能体 / 实验 / 轻量级应用 |
| 本地 JSON 文件 | 极致简单,无需额外依赖 | 无法进行复杂查询,读写效率较低 | 脚本级测试或原型 |
| 向量数据库 | 具备强大的语义检索能力 | 通常只存储向量,不适合存结构化业务数据 | 长期记忆 / 知识库 |
在后续的实现中,我们将采用 SQLite + ChromaDB 的混合存储方案。
关键连接器:RAG
SQLite与ChromaDB的混合存储方案,相当于为智能体配备了功能不同的硬盘。而检索增强生成(RAG)则在智能体的记忆系统中扮演了关键连接器的角色。它的核心职责是在有限的上下文窗口内,精准地加载最相关的长期记忆。对于记忆模块而言,RAG不仅仅意味着“搜索”,它涵盖了一个完整的记忆调度流程:
- 感知:当用户发出输入时,系统不仅将其视为待处理的“输入”,同时也将其作为“检索查询”。
- 回忆:拿着这个查询,同时向ChromaDB(基于语义联想)和SQLite(基于精确查询)寻找相关的记忆片段。
- 筛选:受限于Token数量,系统需要从检索结果中筛选出最重要、最相关的信息。
- 注入:将筛选出的记忆片段进行格式化(例如,作为系统提示词的一部分:
相关历史信息:...),并注入到当前对话的提示词中。
通过RAG机制,有效解决了智能体“记不住”(无状态)和“记不下”(Token限制)的核心矛盾。
接下来,我们将进入具体实现部分。
基于双存储的Memory系统实现
为了实现上述目标——解决智能体“记不住、存不下”的问题,我们设计了一个分层的记忆架构:
-
L1 热记忆
- 载体:内存 / 列表(List)
- 内容:当前会话中最新的N轮对话。
- 特点:访问速度极快,保留原始内容,但容量极小(采用滑动窗口管理)。
- 作用:维持当前对话的即时连贯性。
-
L2 温记忆
- 载体:ChromaDB(向量数据库)
- 内容:历史对话的嵌入向量及摘要。
- 特点:存储容量大,支持基于模糊语义的检索。
- 作用:提供长期的经验和背景知识(例如,“你三个月前提到过喜欢吃辣”)。
-
L3 冷记忆
- 载体:SQLite(关系型数据库)
- 内容:完整的结构化会话日志(会话/消息记录)。
- 特点:即使系统重启也不会丢失数据,支持精确的SQL查询。
- 作用:作为“单一事实来源”,用于审计、回溯或在必要时重建向量库。
整体工作流程如下:
- 用户输入 -> RAG 检索引擎
- RAG 引擎 -> 并行查询 (L1 热记忆 + L2 温记忆)
- 结果融合 -> 构建完整的提示词
- LLM 生成回复
- 异步写入 -> 同时更新 L1(滑动窗口)、L2(向量库)、L3(数据库)
写入与管理机制
在编写代码之前,我们需要明确如何管理这些数据,制定以下核心策略:
一、双写一致性策略
我们同时使用了SQLite和ChromaDB,如何保证两者之间的数据一致性?
- 以SQLite为主:所有原始数据(消息)首先写入SQLite,并生成唯一的
message_id。 - 以ChromaDB为辅:将SQLite中的文本内容向量化后存入ChromaDB,并在其元数据中记录对应的
message_id。 - 关联查询:检索时,首先从ChromaDB找到语义相似的向量,获取其关联的
message_id,然后(可选地)回查SQLite以获取完整的详细信息。这确保了向量库主要充当“索引”角色,而不会成为数据孤岛。
二、混合检索策略
为了避免检索出完全不相关的内容,我们需要为检索过程添加“约束条件”:
- 用户隔离:检索时必须强制附带
user_id过滤条件,防止用户A检索到用户B的隐私信息。 - 阈值过滤:设置一个相似度阈值(例如0.4)。如果最相关的记忆相似度都低于此阈值,则判定为全新话题,不注入任何长期记忆,以避免模型产生“幻觉”。
三、生命周期管理
- 滑动窗口:L1热记忆仅保留最近10-20轮对话。
- 持久化:L2和L3记忆必须落盘存储,确保服务重启后不会发生“失忆”。
- 衰减机制(可选):虽然本次实现暂不引入复杂的艾宾浩斯遗忘曲线,但在设计数据库表结构时,我们预留了
importance_score(重要性评分)和last_accessed_at(最后访问时间)字段,为未来实现“不常用的记忆自动淡化”功能打下基础。
理论基础已阐述完毕,现在可以开始代码实现了。
记忆系统代码实现
基于前面的理论,我们实现了一个完整的记忆系统,涵盖了数据存储、向量检索、RAG增强以及LLM交互等核心功能。
整个系统采用清晰的分层架构,自底向上依次为:
应用层:chat_with_memory.py (LLM交互入口)
↓
工具层:memory_tools.py (高级功能封装)
↓
服务层:memory_service.py (核心业务逻辑)
↓
存储层:vector_store.py + models.py (数据访问抽象)
↓
数据层:ChromaDB + SQLite (实际物理存储)
设计遵循以下原则:
- 分层解耦:每一层仅依赖其下一层,便于独立测试和组件替换。
- 面向接口:基于抽象接口而非具体实现进行编程。
- 单一职责:每个模块只负责一个明确的功能领域。
数据模型设计
一、users表(用户)
class User(Base):
id = Column(Integer, primary_key=True)
username = Column(String(100), unique=True, nullable=False)
email = Column(String(255), unique=True, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow)
二、sessions表(会话)
class Session(Base):
id = Column(Integer, primary_key=True)
session_id = Column(String(100), unique=True, nullable=False)
user_id = Column(Integer, ForeignKey('users.id'))
title = Column(String(255), nullable=True)
context_window = Column(Integer, default=10) # 上下文窗口大小
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
三、memories表(记忆)
class Memory(Base):
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
session_id = Column(Integer, ForeignKey('sessions.id'), nullable=True)
memory_type = Column(String(50)) # episodic/semantic/procedural
content = Column(Text, nullable=False)
metadata = Column(JSON, nullable=True)
vector_id = Column(String(100)) # 关联ChromaDB的向量ID
importance_score = Column(Float, default=0.5) # 重要性评分
access_count = Column(Integer, default=0) # 被访问次数
last_accessed_at = Column(DateTime, nullable=True)
is_deleted = Column(Boolean, default=False) # 软删除标记
设计要点:
memory_type字段用于区分三种记忆类型。vector_id字段用于关联向量数据库中的对应条目。importance_score字段可用于记忆的过滤和排序。access_count字段支持基于热度的分析。is_deleted字段实现软删除,避免数据被误删。
向量存储实现
使用ChromaDB作为向量数据库,其核心代码如下:
class VectorStore:
def __init__(self, persist_directory: str = "./chat_chroma.db"):
self.client = chromadb.Client(Settings(
persist_directory=persist_directory,
anonymized_telemetry=False
))
self.collection = self.client.get_or_create_collection(
name="memory_collection"
)
def add_memory(self, content: str, metadata: Dict = None) -> str:
"""添加记忆到向量库"""
memory_id = str(uuid.uuid4())
metadata = metadata or {}
metadata['created_at'] = datetime.utcnow().isoformat()
self.collection.add(
ids=[memory_id],
documents=[content],
metadatas=[metadata]
)
return memory_id
def search_memories(self, query: str, n_results: int = 5,
filter_metadata: Dict = None) -> Dict:
"""语义搜索记忆"""
results = self.collection.query(
query_texts=[query],
n_results=n_results,
where=filter_metadata
)
return {
'ids': results['ids'][0],
'documents': results['documents'][0],
'metadatas': results['metadatas'][0],
'distances': results['distances'][0]
}
关键特性:
- 本地持久化:无需启动额外服务,数据直接保存在本地文件。
- 自动嵌入:ChromaDB内置嵌入模型,自动将文本转换为向量。
- 元数据过滤:支持通过元数据进行精确过滤。
- 语义搜索:基于余弦相似度进行向量检索。
记忆服务层
MemoryService类整合了数据库和向量库的操作,提供了统一的记忆管理接口。其核心方法包括:
添加记忆(实现双写机制):
def add_memory(self, user_id: int, content: str,
memory_type: str = "episodic",
session_id: int = None,
metadata: Dict = None,
importance_score: float = 0.5) -> Memory:
"""添加记忆(同时保存到数据库和向量库)"""
db = self._get_db_session()
try:
# 1. 创建数据库记录
memory = Memory(
user_id=user_id,
session_id=session_id,
memory_type=memory_type,
content=content,
metadata=metadata or {},
importance_score=importance_score
)
db.add(memory)
db.commit()
db.refresh(memory)
# 2. 添加到向量库
vector_metadata = {
'user_id': user_id,
'memory_type': memory_type,
'memory_db_id': memory.id
}
vector_id = self.vector_store.add_memory(
content=content,
metadata=vector_metadata
)
# 3. 更新向量ID关联
memory.vector_id = vector_id
db.commit()
return memory
finally:
db.close()
搜索记忆(整合语义检索与数据库查询):
def search_memories(self, query: str, user_id: int = None,
memory_type: str = None,
n_results: int = 5) -> List[Dict]:
"""搜索记忆"""
# 1. 在向量库中进行语义搜索
filter_metadata = {}
if user_id:
filter_metadata['user_id'] = user_id
if memory_type:
filter_metadata['memory_type'] = memory_type
results = self.vector_store.search_memories(
query=query,
n_results=n_results * 2, # 多检索一些,用于后续过滤
filter_metadata=filter_metadata if filter_metadata else None
)
# 2. 整合数据库中的详细信息
memories = []
db = self._get_db_session()
try:
for i, vector_id in enumerate(results['ids']):
metadata = results['metadatas'][i]
memory_db_id = metadata.get('memory_db_id')
if memory_db_id:
memory = db.query(Memory).filter(
Memory.id == memory_db_id,
Memory.is_deleted == False
).first()
if memory:
# 更新访问统计信息
memory.access_count += 1
memory.last_accessed_at = datetime.utcnow()
memories.append({
'id': memory.id,
'content': memory.content,
'memory_type': memory.memory_type,
'importance_score': memory.importance_score,
'distance': results['distances'][i],
'created_at': memory.created_at.isoformat()
})
if len(memories) >= n_results:
break
db.commit()
return memories
finally:
db.close()
核心逻辑:
- 双写机制:确保数据同时写入SQLite和ChromaDB。
- 关联查询:通过
memory_db_id字段关联两个存储系统中的数据。 - 访问统计:每次检索都会自动更新记忆的访问计数和最后访问时间。
- 软删除过滤:自动过滤掉已被标记为删除的记忆。
高级工具层
MemoryTools类提供了面向应用的高级接口,其中最核心的是RAG检索功能:
def retrieve_for_query(self, user_id: int, query: str,
session_id: int = None,
include_context_window: bool = True,
max_results: int = 5) -> Dict:
"""RAG检索:整合短期和长期记忆"""
result = {
'context_window': [],
'relevant_memories': []
}
# 1. 获取上下文窗口(短期记忆)
if include_context_window and session_id:
context_memories = self.service.get_context_window(session_id)
result['context_window'] = [
{'content': m.content, 'created_at': m.created_at.isoformat()}
for m in context_memories
]
# 2. 语义搜索(长期记忆)
relevant = self.service.search_memories(
query=query,
user_id=user_id,
n_results=max_results
)
result['relevant_memories'] = relevant
return result
RAG实现要点:
- 双重检索:同时获取短期记忆(上下文窗口)和长期记忆(向量检索结果)。
- 智能拼接:按照系统指令 → 长期记忆 → 短期记忆 → 当前查询的顺序组织最终提示词。
- 数量控制:严格限制每部分记忆的数量,确保不超出模型的Token限制。
ChatWithMemory类则整合了记忆系统与LLM调用:
class ChatWithMemory:
def chat(self, user_input: str, use_rag: bool = True) -> str:
"""与LLM进行带记忆的对话"""
messages = [{"role": "system", "content": self.system_prompt}]
if use_rag:
# 执行RAG检索
rag_result = self.memory.retrieve_for_query(
user_id=self.user_id,
query=user_input,
session_id=self.session_id,
include_context_window=True,
max_results=3
)
# 添加相关的长期记忆到上下文
if rag_result['relevant_memories']:
memory_context = "相关历史信息:\n"
for mem in rag_result['relevant_memories'][:3]:
memory_context += f"- {mem['content']}\n"
messages.append({"role": "system", "content": memory_context})
# 添加上下文窗口中的短期记忆
for ctx in rag_result['context_window']:
# 解析对话内容(假设格式为"User: ...\nAssistant: ...")
if "User:" in ctx['content'] and "Assistant:" in ctx['content']:
parts = ctx['content'].split("\nAssistant:")
user_part = parts[0].replace("User:", "").strip()
assistant_part = parts[1].strip()
messages.append({"role": "user", "content": user_part})
messages.append({"role": "assistant", "content": assistant_part})
# 添加当前用户输入
messages.append({"role": "user", "content": user_input})
# 调用LLM
response = call_llm(messages=messages)
assistant_message = response.choices[0].message.content
# 保存本轮对话到记忆系统
self.memory.add_conversation_memory(
user_id=self.user_id,
session_id=self.session_id,
user_message=user_input,
assistant_message=assistant_message
)
return assistant_message
完整流程:
- 检索记忆:利用RAG机制获取与当前查询相关的历史信息。
- 构建消息:按照大模型要求的格式组织完整的对话历史。
- 调用LLM:将构建好的消息发送给模型以生成回复。
- 保存记忆:将本轮的用户输入和AI回复保存到记忆系统中,供未来使用。
使用示例
基础使用:
# 基础使用
from memory_tools import MemoryTools
# 初始化
memory = MemoryTools()
# 创建用户和会话
user_id = memory.create_user("alice")
session_id = memory.create_session(user_id, "session-001")
# 添加对话记忆
memory.add_conversation_memory(
user_id=user_id,
session_id=session_id,
user_message="我喜欢Python编程",
assistant_message="Python是一门很棒的语言!"
)
# 搜索记忆
results = memory.search_memories(
user_id=user_id,
query="编程语言",
n_results=5
)
带记忆的交互式聊天:
# 运行交互式聊天程序
python chat_with_memory.py
# 示例对话
你: 我叫Alice,喜欢编程
助手: 你好Alice!很高兴认识你。编程是一个很有趣的领域...
你: 我之前说过我叫什么名字?
助手: 你之前说你叫Alice。
系统会自动完成以下工作:
- 将每一轮对话保存到记忆系统中。
- 在后续对话中检索相关的历史信息。
- 将这些记忆作为上下文注入给LLM,使其能做出连贯且个性化的回复。
小结
本记忆系统的实现展示了如何将理论概念转化为可运行的工程系统,其特点包括:
- 分层架构:清晰的职责划分,便于维护和扩展。
- 双存储设计:关系型数据库与向量数据库相结合,各司其职。
- RAG实现:有机整合短期与长期记忆,提供完整的对话上下文。
- 实用工具:提供了从底层API到高级封装的完整工具链,满足不同场景需求。
通过这套系统,智能体能够:
- 记住用户的个人偏好和历史对话内容。
- 在较长的多轮对话中保持上下文的连贯性。
- 基于历史经验提供更具个性化的回答。
- 实现跨会话的知识和技能复用。
这正体现了记忆系统在智能体架构中的核心价值。
ReAct框架:实现智能任务规划
在理解了记忆系统之后,我们便可以进入ReAct框架模块。其核心在于如何实现任务的循环规划与执行。
任务规划是智能体系统中的核心控制模块,负责将复杂的自然语言指令转化为一系列结构化的、可执行的步骤。
它连接了LLM的推理能力与各种工具的执行能力,通过“先规划、后执行”的模式,解决了直接让模型生成执行动作所伴随的不确定性与幻觉问题。
ReAct框架的核心模块包含三个组件:
- 规划器:负责调用LLM,根据用户目标和可用工具生成结构化的计划(通常为JSON格式)。
- 执行器:负责解析规划器输出的计划,按顺序调度并执行各个工具,同时管理步骤间上下文数据的流转。
- 数据模型:定义标准的计划与步骤数据结构,作为各组件之间通信的契约。

其核心思想并不复杂,主要是一个循环执行的过程。下面我们直接看代码实现。
数据模型定义
系统通过Plan和PlanStep类来定义标准的任务数据结构。每个步骤包含唯一的ID、需要调用的工具名称、参数以及执行状态等信息。
@dataclass
class PlanStep:
id: str
tool: str
args: Dict[str, Any]
why: str = ""
status: Literal["pending", "running", "success", "failed", "skipped"] = "pending"
output: Any = None
error: str = ""
@dataclass
class Plan:
goal: str
steps: List[PlanStep] = field(default_factory=list)
规划器设计
规划器通过精心设计的系统提示词,强制LLM输出指定格式的JSON。提示词中会注入当前可用的工具描述。
为了实现步骤间的数据传递,我们定义了一种模板语法{{steps.step_id.output.field}},允许后续步骤的参数引用前序步骤的输出结果:
system_prompt = f"""
你是一个任务规划器。你必须只输出JSON,不要输出任何解释文字。
目标:将用户的需求拆解为若干个步骤,每一步需要调用一个指定的工具,并提供相应的参数。
关键规则——数据依赖:
如果某一步的参数需要依赖前面步骤的输出结果,请务必使用模板语法 `{{{{steps.前序步骤ID.output.字段名}}}}`。
不要自己捏造数据,而是严格引用前序步骤的实际输出。
例如:
1. step1 (id="s1") 调用 geocode 工具,返回 `{{"location": "116.40,39.90"}}`
2. step2 (id="s2") 需要用到这个坐标,其参数应写为: `{{"location": "{{{{steps.s1.output.location}}}}"}}`
你必须输出的JSON结构:
{{
"goal": "...",
"steps": [
{{
"id": "step1",
"tool": "tool_name",
"args": {{ ... }}
}}
]
}}
"""
执行器与参数解析
执行器在调用具体工具之前,会先扫描步骤参数中的所有模板占位符,并从当前的执行上下文中提取真实值进行替换。这种机制实现了模型规划与具体数据处理的解耦:
async def _run_step(self, step: PlanStep, mcp_client: Client, context: Dict[str, Any]) -> None:
step.status = "running"
try:
# 解析参数中的 {{...}} 模板,替换为上下文中的真实数据
resolved_args = resolve_templates(step.args, context)
# 通过MCP客户端调用指定的工具
result = await mcp_client.call_tool(step.tool, resolved_args)
# 记录工具执行的输出结果
step.output = getattr(result, "structured_content", None) or result.content
step.status = "success"
# 将本步骤的输出写入上下文,供后续步骤引用
context["steps"][step.id] = {
"status": step.status,
"output": step.output
}
except Exception as e:
step.status = "failed"
step.error = str(e)
运行示例
项目中包含一个命令行演示程序,用于展示完整的规划与执行过程。
- 启动MCP服务器:确保提供基础工具能力的MCP服务已运行。
uv run python -m code.MCP.mcp_server - 运行规划演示CLI:
uv run python -m code.Planning.demo_planning_cli.py
执行效果示例如下图所示:

可以看到,其核心逻辑确实清晰明了。最后,我们将通过一个真实案例,将前面所学的所有知识点串联起来。
实践案例:小红书爆款内容一键发布
首先展示一些效果图:

在智能体的基础能力(工具调用、记忆、规划)逐步完善后,我们开始探索更具实用价值的集成应用场景。
社交媒体内容创作与发布是一个典型的重复性工作流程,非常适合通过自动化来提升效率。今天,我们将使用智能体来实现从小红书主题输入到最终平台发布的全流程自动化。
该智能体接收用户的自然语言指令(例如:“生成一篇关于露营装备的推荐笔记”),随后自动完成内容创作、配图生成、平台登录、内容填充及发布等一系列操作。其整体流程如下图所示:

核心组件:内容生成引擎
我们在Coze平台上构建了一个多节点协同的工作流,专门用于生产符合小红书平台调性的结构化内容包。该工作流并非简单的文本生成,而是一条遵循“爆款公式”的标准化生产线:

这里有以下几个核心节点:
一、主题分析与结构规划节点
用户输入爆文主题,可以是一段新闻稿,也可以是引发思考的一句话,例如下文案例中的“Gemini3 是目前最强 AI 吗?”。
随后,调用LLM分析主题关键词,并利用大模型节点内置的新闻搜索技能,收集相关信息作为素材。
最终输出:完整的内容大纲框架,包含备选标题、情绪钩子、段落逻辑设计以及互动结尾。
二、文案生成与图片提示词生成节点
- 输入:上一步产出的内容大纲框架。
- 处理:根据生成的文案,再次调用大模型,并结合特定提示词,生成对应的配图。
- 风格控制:应用短句结构、Emoji插入策略、口语化转换、热点词融合等技巧。
- 输出:文生图提示词以及生成的图片。
三、结构化打包节点
- 输入:前述所有节点产出的素材(标题、正文、标签、图片等)。
- 处理:将所有素材打包为标准化的JSON格式,并上传至飞书多维表格,便于后续查看和管理。
- 输出格式示例:
async function main({ params }: Args): Promise<Output> {
// 构建输出对象
const ret = {
fields: [
{
fields: {
"小红书文案": params.content,
"小红书标题": params.title,
"小红书图文地址": params.imageUrl
},
record_id: params.record_id
}
]
};
return ret;
}
实现步骤拆解
当我们手头有一段文字素材、一篇新闻稿,甚至仅仅是一句灵感时,如何快速生成适用于抖音、小红书、公众号这三个主流自媒体平台的内容?
这三个平台用户活跃度高且风格各异,传统手动改写方式耗时耗力。因此,我们希望通过自动化流程,实现“一次输入,多平台适配”。
飞书多维表格在此扮演了“内容中央数据库”的角色。为了支持后续的自动化流程,首先需要设计清晰的字段结构。
- 建立一个线索表,用于存放初始的内容素材,如文字、新闻稿或一句话灵感。
- 建立一个文章产出表,用于存放由Coze工作流写回的、已加工完成的内容数据,包括图片URL、标题、正文等。

飞书表格设计完成后,即可根据其字段结构,在Coze中设计对应的工作流。
Coze工作流实现
在Coze工作流中,我们为大模型节点添加了“新闻识别”技能,使其能够根据简短的一句话自动扩展并生成完整的文章。
当输入内容较少时,大模型会自动提取关键词进行新闻搜索,获取相关信息作为补充语料,进而辅助文章生成:

提示词的设计对于模型理解任务至关重要。推荐使用Markdown格式进行结构化组织,明确指定角色、任务、可用技能、具体要求和输出格式等。这种结构化的方式能帮助大模型更准确地把握任务目标,从而提升生成内容的质量。
我们选用了豆包1.6的“深度思考”模型。该模型在内容生成质量上表现更优,但运行速度相对较慢。若提示词较为复杂,且对生成时长要求不高,推荐使用思考模型以获得更优质的结果:

考虑到公众号、小红书和抖音在内容形式上存在显著差异,我们对不同平台进行了独立的工作流设计:
- 公众号:以长文章为主,提示词需设计得更加详尽,确保内容的深度和结构的完整性。
- 小红书与抖音:以图文或短视频为主,需要将文章内容进一步转化为适合图文或视频生成的提示词。

三个平台的内容生成流程执行完毕后,结果会自动写回到飞书多维表格中,便于后续的统一管理与使用。
以下为完整流程示例,输入内容为:“Gemini3 是目前最强 AI 吗?”

下图展示了飞书表格中收集到的、由工作流生成的完整信息:

现在,开始进行飞书与Coze工作流的对接。Coze工作流制作并发布后,会形成一个API端点,可供外部系统调用。
飞书对接Coze工作流
在飞书平台配置自动化流程时,我们选择“按钮”作为触发飞书字段更新的方式。用户可以通过点击表格中的按钮来发送HTTP请求,从而触发已经封装好的Coze工作流API,实现流程的自动化启动:

完成触发器配置后,在飞书的自动化流程编辑器中进一步设置按钮的具体操作。下图展示了飞书与Coze工作流对接的完整流程配置:

核心组件:浏览器操作工具
在工作流部分解决了内容生成问题后,智能体仍不具备发布功能。因此,这里还需要引入浏览器操作能力。浏览器自动化是智能体非常基础且重要的工具之一。
与传统的基于DOM元素定位的自动化工具不同,我们采用了一种更接近人类操作方式的方法:让LLM“看到”屏幕内容并做出决策。
核心原理是通过计算机视觉分析浏览器界面,结合页面HTML结构,让LLM像真人一样理解当前页面状态并决定下一步操作。核心实现逻辑如下图所示:

这里调用的Agent,实际上是browser-use工具库中封装好的一个内置智能体。它运行时需要三个核心参数:llm(大模型)、task(任务指令)和browser(浏览器实例):
- llm:我们传入的大模型,负责进行决策与规划。
- task:用自然语言编写的指令,告知Agent需要完成的具体任务。
- browser:提前初始化好的浏览器工具实例,提供网页访问与操作能力。
回顾我们之前开发的旅游助手Agent,其本质结构与这个内置Agent完全一致:都是LLM + Tools的架构。
区别在于,现在我们在自己构建的Agent内部,再去调用另一个封装好的Agent,这就形成了一个多智能体协作的示例。其执行流程解析如下:
- 视觉理解与决策
- Agent接收当前浏览器界面的截图和DOM信息。
- LLM分析截图中的可视元素,如按钮、输入框、菜单等。
- 基于任务指令和当前界面状态,决定下一步操作。
- 输出自然语言指令,例如“点击右上角的发布按钮”。
- 操作执行与反馈
- 系统将LLM输出的自然语言指令转换为具体的浏览器操作命令。
- 执行操作后,获取新的页面状态。
- 将操作结果和新的界面状态反馈给LLM,以供其进行下一步决策。
- 自适应与容错处理
- 当页面布局发生变化时,LLM能基于视觉信息重新定位元素。
- 遇到意外弹窗或错误提示时,LLM能够理解并尝试处理。
- 面对网络延迟或页面加载问题时,LLM会决定等待或重试。
| 特性 | 传统DOM操作 | LLM驱动的视觉操作 |
|---|---|---|
| 页面适应性 | 依赖固定的CSS选择器或XPath,页面改版易失效 | 基于对屏幕内容的视觉理解,适应性强 |
| 开发效率 | 需要编写大量定位元素的代码 | 使用自然语言描述任务,开发更简单直观 |
| 维护成本 | 页面结构变化后,需要更新测试脚本 | 能自动适应小幅度的UI变化 |
| 容错能力 | 严格匹配,元素找不到则脚本失败 | 能理解上下文,尝试替代方案或处理异常 |
| 操作逻辑 | 线性的脚本执行流程 | 基于理解的、灵活的智能决策流程 |
小结
至此,这个完整的自动化案例就介绍完毕了。我们使用Browser-Use工具解决了一些复杂的网页交互问题。需要注意的是,在实践中,这类基于视觉理解的自动化方案的稳定性可能不如传统的脚本,更适合用于演示或原型验证。若应用于生产环境,可能需要考虑更稳定的企业级RPA方案。
结语
本文详细阐述了智能体(Agent)中记忆系统的设计与实现、ReAct任务规划框架的原理,并通过一个小红书内容发布的实战案例,展示了如何将这些技术模块串联起来,解决实际的自动化需求。希望本次从理论到实践的深度解析,能为你构建自己的智能体应用带来启发。