Agent 应用和传统搜索、问答系统的差别,不只是“多了一个大模型”。Agent 会规划、调用工具、写入状态、根据反馈重试。也就是说,数据不再只是被检索出来给人看,而是会被模型拿来做决策。因此,“Data for Agents”这个主题的关键,不是把所有资料塞进向量库,而是把数据整理成 Agent 能理解、能验证、能执行的上下文。
由于来源摘要没有提供更细的实现细节,下面的实践示例按一个常见假设展开:你正在构建一个能回答内部知识、并可调用工具的 Agent。示例不是原文事实,而是可以这样实践的一套最小方案。
Agent 需要的数据,不等于普通 RAG 需要的数据
普通 RAG 系统通常关心三件事:文档切片、向量检索、把片段放进提示词。Agent 当然也需要这些,但还不够。
Agent 至少还会消耗四类数据:
- 知识数据:产品文档、接口说明、操作手册、FAQ、工单记录。
- 工具描述:有哪些工具、参数是什么、失败时返回什么、哪些操作有副作用。
- 运行状态:当前任务、已尝试步骤、用户偏好、会话内事实。
- 可验证信号:数据库记录、API 返回、日志、权限信息、测试结果。
问题往往出在边界上。比如文档里写“重启服务后等待健康检查通过”,人能理解流程,但 Agent 需要知道:重启哪个服务、用哪个命令、健康检查端点是什么、超时时间多少、失败后是否允许回滚。
因此,给 Agent 准备数据时,要从“给模型看”转向“给模型用”。文档片段应该尽量带结构化元数据,工具说明应该明确副作用,状态数据应该能被更新和审计。
数据切片要保留动作边界
很多团队切文档时只按固定 token 数切,比如每 800 token 一段。这对普通问答尚可,但对 Agent 不稳定。因为 Agent 需要执行动作,如果一个操作流程被切成两半,模型可能拿到“怎么检查”却没拿到“什么时候检查”,或者拿到命令却没拿到前置条件。
更适合 Agent 的切片方式是按语义和动作边界切:
- 一个 API 端点尽量独立成块。
- 一个运维 Runbook 的一个步骤或一个完整故障场景独立成块。
- 每个块保留标题、来源类型、更新时间、权限级别、适用系统。
- 对“危险操作”打标签,例如
destructive: true或requires_approval: true。
这样做的好处是,Agent 检索到的不只是文本,而是一块有上下文、有约束、有风险标记的数据。
可以这样实践:把文档整理成 Agent 可检索的 JSONL
下面是一个最小可运行的 Python 示例:读取 Markdown 文档,按标题切块,并输出带元数据的 JSONL。实际项目里你可以把结果写入向量库、搜索引擎或对象存储。
运行前准备:把 docs/ 改成你的文档目录,或先用示例命令创建测试文档。
mkdir -p docs
cat > docs/restart-api.md <<'EOF'
# Restart API Service
## Preconditions
User must have production operator permission. Check current incident status before restart.
## Restart command
Run `kubectl rollout restart deployment/api -n prod`.
## Health check
Call `https://api.example.com/healthz` and expect HTTP 200 within 120 seconds.
## Rollback
If health check fails, rollback the deployment and page the owner.
EOF
创建 prepare_agent_data.py:
from pathlib import Path
import hashlib
import json
import re
DOC_DIR = Path("docs")
OUT_FILE = Path("agent_chunks.jsonl")
heading_re = re.compile(r"^(#{1,3})\s+(.+)$", re.MULTILINE)
def stable_id(text: str) -> str:
return hashlib.sha256(text.encode("utf-8")).hexdigest()[:16]
def infer_risk(text: str) -> dict:
lower = text.lower()
destructive_words = ["delete", "drop", "rollback", "restart", "shutdown"]
requires_approval = any(word in lower for word in destructive_words)
return {
"requires_approval": requires_approval,
"risk": "high" if requires_approval else "normal",
}
def split_markdown(path: Path):
text = path.read_text(encoding="utf-8")
matches = list(heading_re.finditer(text))
if not matches:
yield {
"id": stable_id(str(path) + text),
"source": str(path),
"title": path.stem,
"content": text.strip(),
**infer_risk(text),
}
return
for i, match in enumerate(matches):
start = match.start()
end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
title = match.group(2).strip()
content = text[start:end].strip()
if not content:
continue
yield {
"id": stable_id(str(path) + title + content),
"source": str(path),
"title": title,
"content": content,
"content_type": "runbook" if "restart" in str(path).lower() else "doc",
**infer_risk(content),
}
def main():
chunks = []
for path in sorted(DOC_DIR.glob("**/*.md")):
chunks.extend(split_markdown(path))
with OUT_FILE.open("w", encoding="utf-8") as f:
for chunk in chunks:
f.write(json.dumps(chunk, ensure_ascii=False) + "\n")
print(f"wrote {len(chunks)} chunks to {OUT_FILE}")
if __name__ == "__main__":
main()
运行:
python prepare_agent_data.py
head -n 3 agent_chunks.jsonl
你会得到类似这样的数据块:
{"id":"...","source":"docs/restart-api.md","title":"Restart command","content":"## Restart command\nRun `kubectl rollout restart deployment/api -n prod`.","content_type":"runbook","requires_approval":true,"risk":"high"}
这类 JSONL 的价值在于,它能同时服务检索和控制逻辑。检索阶段可以用 content 做 embedding;执行阶段可以读取 requires_approval,要求用户确认后再调用有副作用的工具。
工具数据要写清楚失败模式
Agent 的工具描述经常被写得像 SDK 注释:函数名、参数、返回值。真正上线后,更重要的是失败模式和权限边界。
例如一个重启服务工具,描述里应该包含:
- 是否会影响生产流量。
- 哪些 namespace 允许操作。
- 是否需要人工确认。
- 失败返回是否可重试。
- 执行后应该检查哪个信号。
可以这样写一个工具注册配置:
tools:
- name: restart_kubernetes_deployment
description: Restart a Kubernetes deployment in an approved namespace.
side_effect: true
requires_approval: true
allowed_namespaces:
- staging
- prod
input_schema:
type: object
required: [namespace, deployment]
properties:
namespace:
type: string
enum: [staging, prod]
deployment:
type: string
pattern: "^[a-z0-9-]+$"
success_check:
type: http
timeout_seconds: 120
expected_status: 200
retry_policy:
max_attempts: 1
这不是某个框架的固定格式,而是一种值得采用的数据形态:把“能不能做、怎么做、做完如何验证”写成机器可读结构。Agent 的提示词可以引用它,工具执行层也可以用它做硬校验。
不要把记忆当成垃圾桶
Agent 往往会引入 memory:用户偏好、历史任务、长期事实、阶段性计划。这里最大的风险是污染。一次错误判断如果被写成长久记忆,后续任务会持续受影响。
更稳妥的做法是给记忆分层:
- 会话记忆:只在当前对话有效,例如“用户刚才选择了 staging”。
- 任务记忆:只在当前工单或当前工作流有效,例如“已经重启过 api deployment”。
- 长期记忆:必须经过确认或规则过滤,例如“该团队默认使用 prod namespace”。
写入长期记忆前,最好有验证步骤。比如只允许从明确用户声明、组织配置、成功执行结果里提取;不要从模型推测里提取。
落地检查清单
准备 Agent 数据时,可以用下面这份清单压一遍设计:
- 数据块是否保留了标题、来源、更新时间和适用范围?
- Runbook 是否按完整动作或故障场景切片,而不是机械 token 切片?
- 工具描述是否标注副作用、权限、失败模式和验证方式?
- 高风险数据是否带有
requires_approval一类的机器可读字段? - Agent 的运行状态是否可审计、可过期、可删除?
- 长期记忆是否有写入门槛,而不是把每轮对话都沉淀下来?
Agent 的能力上限,很大一部分取决于数据设计的下限。把数据整理成可检索、可执行、可验证的形态,模型才不容易在漂亮的文本里迷路,也更容易接入真实系统。