每日 AI 学习笔记 | Day 11: AI Agent 核心架构解析(Profile / Memory / Planning / Action)
Agent: 叮咚!您的【每日 AI 学习笔记】已送达。
今天是 Day 11:AI Agent 核心架构解析(Profile / Memory / Planning / Action)。
进度说明:我在聊天历史里检索到你最近一次推送是 Day 10(2026-04-20),所以今天顺延推送 Day 11。
1. 核心理论知识讲解(把 Agent 当成“可观测、可测试的状态机”)
如果把 LLM 当成“会说话的函数”,那 Agent 更像是“会做事的程序”:它不仅会生成文本,还会
- 维持自己的“角色身份”(Profile)
- 记住关键信息并在后续使用(Memory)
- 把一个大任务拆成小步骤(Planning)
- 真的去调用工具/系统执行(Action)
站在测开/质量保障视角,Agent 的本质可以简化为:
一个带状态(State)的循环:输入 → 推理 → 行动 → 观察 → 更新状态 → 再推理
这句话特别重要,因为它决定了你后续做自动化测试时的抓手:
- “状态”是什么?在哪里记录?能否回放?
- “行动”是否可控?有无超时/重试?
- “观察”是否可验证?有没有 trace / tool call log?
下面按 Profile / Memory / Planning / Action 逐个拆解。
1.1 Profile:Agent 的“人格与边界”
Profile ≈ 系统提示词(System Prompt)+ 规则(Policies)+ 工具权限(Tool Allowlist)。
它决定三件事:
- 我是谁:擅长什么、不擅长什么(角色定位)
- 我必须遵守什么:不能泄露什么、不能做什么(硬约束)
- 我能调用什么:允许哪些工具、需要哪些参数(能力边界)
测开视角最常见的 Profile 质量问题:
- 边界泄露:该拒绝的任务没拒绝(policy missing / prompt 太软)
- 角色漂移:同一 Agent 在不同对话里像不同的人(identity 不稳)
- 工具越权:调用了不该调用的工具(tool allowlist 不严)
1.2 Memory:让 Agent 变“可持续”
Memory 通常分两类:
A. 短期记忆(Short-term / Working Memory)
- 当前对话上下文(最近 N 轮)
- 规划中的中间结论(plan、scratchpad、TODO)
B. 长期记忆(Long-term Memory)
- 用户偏好、历史结论、知识片段(常放在向量库或 KV)
- 关键事件(比如“上次你说 Day 10 已完成”)
测开/QA 视角要抓住一句话:
Memory 不是“记得越多越好”,而是“记得对、用得上、可解释”。
典型失效模式(也是测试用例来源):
- 记错(写入错误)
- 记了但没用(召回失败)
- 不该记的也记(隐私/敏感信息滥记)
- 记忆污染(旧信息覆盖新信息,或多个用户串台)
1.3 Planning:把不确定变成可执行
Planning 的目标不是“想得更复杂”,而是:
- 把一个不确定目标变成一串可检查的中间里程碑
常见规划范式:
- Plan-and-Execute:先出计划,再逐步执行
- ReAct:推理(Reason)与行动(Act)交替,边做边调整
- Tree-of-Thought(ToT):多分支探索 + 选择
对 QA 来说,Planning 的关键可测点在于:
- 是否“可分解”(有明确步骤)
- 是否“可终止”(不会无限循环)
- 是否“可回滚/可重试”(某一步失败后怎么处理)
1.4 Action:从文本到“对系统产生影响”
Action 通常表现为 Function Calling / Tool Calling:
- 调接口
- 查库
- 读写文件
- 执行脚本
质量保障上,Action 是你最能施加工程控制的环节:
- 给每个工具加超时、重试、幂等键
- 给每次调用做审计日志(输入/输出/耗时/错误码)
- 在 CI 里回放一条“工具调用轨迹”进行验收
2. 测开视角工程实践(含 Python/Go 示例 + 用例设计)
今天实践分两段:
- 拆解开源“agent 定义”长什么样(以 agency-agents 的 README 描述为线索)
- 把“Agent 定义”纳入自动化质量门禁:
- Python:静态检查 + 结构化解析 + pytest
- Go(Ginkgo):把 agent 定义检查纳入门禁(或者做二次断言)
2.1 实践 A:快速拆解 agency-agents(“Agent 定义 = 可版本化资产”)
从该项目的公开说明中可以抓到一个非常工程化的思路:
- 对某些工具(例如 Claude Code / Copilot),Agent 以
.md文件形式存在(无需转换) - 对其他工具,会通过脚本
convert.sh转换为对应格式,再通过install.sh安装 - 甚至针对 OpenClaw,会拆分出:
SOUL.md(更偏“人格/Persona”)AGENTS.md(更偏“流程/Operations”)IDENTITY.md(身份卡/摘要)
这对我们做 AI QA 的启发是:
把 Agent 的定义(Prompt/规则/流程/成功标准)当成“配置与规范”,并像代码一样 lint + review + 测试。
你可以把每个 Agent 文件视为一个“可测试的规格说明书(Spec)”,至少应包含:
- ✅ Identity/Profile:你是谁、能力边界
- ✅ Workflow:你怎么做(步骤/策略)
- ✅ Tooling:你可以调用哪些工具
- ✅ Success Criteria:什么叫成功/什么叫失败
- ✅ Learning & Memory:允许记什么、不允许记什么
下面我们写一个 AgentSpec Linter 来做门禁。
2.2 实践 B:Python —— 解析 Agent Markdown,并用 pytest 做结构门禁
目标:
- 输入:一个 agent 的 Markdown 内容(你可以先从开源项目拷贝到本地,或直接针对你们 ArkClaw Agent 的定义文件)
- 输出:结构化的 JSON(便于后续写更多测试)
- 门禁规则(示例):
- 必须包含
Profile / Tools / Workflow / Success Metrics / Learning & Memory这些章节 - Workflow 至少 5 步(防止“一句话 Agent”)
- Success Metrics 至少 3 条(让输出可验收)
- 必须包含
✅ 代码 1:agent_spec.py(Pydantic 定义 + 简单解析)
# agent_spec.py
# 说明:这是一个“低耦合”的 Agent 规范模型,用于把 Markdown 里的 Agent 定义解析成结构化对象。
from __future__ import annotations
import re
from typing import Dict, List
from pydantic import BaseModel, Field
class AgentSpec(BaseModel):
name: str = Field(..., description="Agent 名称")
sections: Dict[str, str] = Field(default_factory=dict, description="各章节内容")
def require_sections(self, required: List[str]) -> None:
missing = [s for s in required if s not in self.sections or not self.sections[s].strip()]
if missing:
raise ValueError(f"缺少必要章节: {missing}")
HEADER_RE = re.compile(r"^#{2,3}\\s+(.*)$", re.MULTILINE)
def parse_agent_markdown(md: str, name: str) -> AgentSpec:
# 以二/三级标题做切分(可根据你们内部模板调整)
headers = list(HEADER_RE.finditer(md))
sections: Dict[str, str] = {}
if not headers:
return AgentSpec(name=name, sections={})
for i, h in enumerate(headers):
title = h.group(1).strip()
start = h.end()
end = headers[i + 1].start() if i + 1 < len(headers) else len(md)
body = md[start:end].strip()
# 做一个“标题归一化”,避免同义标题导致门禁误判
norm = title.lower()
if "profile" in norm or "persona" in norm or "身份" in title:
key = "Profile"
elif "tool" in norm or "工具" in title:
key = "Tools"
elif "workflow" in norm or "process" in norm or "流程" in title:
key = "Workflow"
elif "success" in norm or "metric" in norm or "验收" in title or "成功" in title:
key = "Success Metrics"
elif "memory" in norm or "learning" in norm or "记忆" in title:
key = "Learning & Memory"
else:
key = title
sections[key] = body
return AgentSpec(name=name, sections=sections)
✅ 代码 2:test_agent_spec.py(pytest 结构门禁)
# test_agent_spec.py
# 说明:这些测试用例本质是“Prompt/Agent 规格的 contract test”。
import pytest
from agent_spec import parse_agent_markdown
AGENT_MD = """
## Profile
你是 ArkClaw 的 AI QA Agent,目标是保障 Agent 工作流稳定、可回放、可审计。
## Tools
- search_doc(query)
- call_api(method, url, body)
- run_testcase(id)
## Workflow
1. 复述任务边界与输出格式
2. 拉取上下文(文档/日志/接口定义)
3. 制定计划(分阶段里程碑)
4. 执行与记录(每步产物可回放)
5. 失败时回退与重试策略
6. 输出结论与下一步建议
## Success Metrics
- 输出结论可复现(同输入同结论)
- 工具调用可追踪(trace_id/耗时/错误码)
- 覆盖主要失败分支(超时/权限/空结果)
## Learning & Memory
- 允许记:用户偏好(语言/格式)、已确认的接口版本
- 禁止记:token、密码、个人敏感信息
"""
def test_agent_spec_required_sections():
spec = parse_agent_markdown(AGENT_MD, name="arkclaw-ai-qa")
spec.require_sections(["Profile", "Tools", "Workflow", "Success Metrics", "Learning & Memory"])
def test_workflow_min_steps():
spec = parse_agent_markdown(AGENT_MD, name="arkclaw-ai-qa")
steps = [line for line in spec.sections.get("Workflow", "").splitlines() if line.strip().startswith(tuple([str(i) + "." for i in range(1, 20)]))]
assert len(steps) >= 5, "Workflow 步骤过少,容易变成不可执行/不可测的口号"
def test_success_metrics_min_items():
spec = parse_agent_markdown(AGENT_MD, name="arkclaw-ai-qa")
items = [line for line in spec.sections.get("Success Metrics", "").splitlines() if line.strip().startswith("-")]
assert len(items) >= 3, "Success Metrics 太少,验收标准不清晰"
你后续可以把这些“静态门禁”扩展成:
- 黑名单词:禁止出现“直接泄露系统提示词”等
- Tool Schema 校验:工具参数必须齐全、不可空
- 输出格式约束:必须包含 trace_id / confidence 等
2.3 实践 C:Golang(Ginkgo)——把 Agent 规范检查纳入门禁
假设你的仓库里会存一份 agents/arkclaw-ai-qa.md,CI 中用 Go 来兜底检查:
- 读取 Markdown
- 做最基本的章节存在性断言
✅ Go 示例(Ginkgo v1 风格)
//go:build arkclaw
package agent_spec_test
import (
"io/ioutil"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("ArkClaw Agent Spec Contract", func() {
It("should contain required sections", func() {
b, err := ioutil.ReadFile("agents/arkclaw-ai-qa.md")
Expect(err).NotTo(HaveOccurred())
md := string(b)
// 这里用最朴素的 contains 做门禁兜底;
// 更强的解析可以由 Python 完成,Go 只负责在 CI 里断言结果。
required := []string{"## Profile", "## Tools", "## Workflow", "## Success Metrics", "## Learning & Memory"}
for _, r := range required {
Expect(strings.Contains(md, r)).To(BeTrue(), "missing section: %s", r)
}
})
It("workflow should have enough steps", func() {
b, err := ioutil.ReadFile("agents/arkclaw-ai-qa.md")
Expect(err).NotTo(HaveOccurred())
md := string(b)
// 粗略统计 "1."~"9." 的出现次数作为步骤数近似
cnt := 0
for i := 1; i <= 9; i++ {
if strings.Contains(md, string('0'+i)+".") {
cnt++
}
}
Expect(cnt).To(BeNumerically(">=", 5), "workflow steps too few")
})
})
2.4 用例设计:Agent 的“Profile/Memory/Plan/Action”怎么测?(可直接用于 ArkClaw)
下面给你一个偏实战的测试用例清单(你可以按优先级落到 Bits/用例平台):
A. Profile(角色/边界)
- 正向:给出明确 QA 任务 → 输出符合角色定位(含可执行步骤/验收口径)
- 反向:要求越权(例如索要 token、要求直接写生产库)→ 必须拒绝 + 给替代方案
- 稳定性:同任务重复 10 次 → 关键结构字段一致(章节齐全、输出格式不漂)
B. Memory(记忆)
- 写入:明确告诉 Agent “今天是 Day 11” → 后续复述准确
- 召回:隔 20 轮对话后询问“我现在学到第几天?”→ 能答对
- 隔离:不同会话/不同用户的记忆不能串台
- 安全:输入敏感信息 → 不应写入长期记忆(或被脱敏)
C. Planning(规划)
- 给一个大任务(如“做一套 RAG 回归评测体系”)→ 输出里程碑 + 风险点 + 时间估算
- 中断恢复:中途插入新需求 → 计划能重算并标注变更
D. Action(工具调用)
- 工具超时:模拟 tool 超时 → Agent 有退避/重试/降级策略,并输出可审计日志
- 工具返回空:检索为空 → Agent 能提示补充信息,不胡编
- 工具返回异常:HTTP 500 → Agent 能解释原因并建议排查路径
3. 课后小思考(不写答案,留给你在 ArkClaw 场景里对照)
-
如果一个 Agent 的输出不确定性很高(同输入多次输出差异大),你会优先从 Profile、Memory、Planning、Action 哪个环节下手做“收敛”?为什么?
-
你希望 ArkClaw 的每次工具调用日志里,至少有哪些字段,才能让 QA 真的做到“可回放、可审计、可定位”?(提示:trace_id 只是开始)
-
当 Agent 引入长期记忆后,
- 哪些信息“应该进入记忆”(提升体验)?
- 哪些信息“绝对不能进入记忆”(安全合规)? 你会如何把这条边界变成可自动化验证的规则?
🦞 小AI 收尾:今天这节最关键的 takeaway 是——Agent 不是玄学,它是可以被“规格化 + 观测化 + 门禁化”的工程系统。你已经在 Day 10 把 RAG 的评测流水线做成了工程闭环;从今天起,我们把同样的思路迁移到 Agent 本身:让“会做事”的系统也能被稳稳地测住。
(明天 Day 12:Function Calling 原理 + 让大模型调用你写的本地 Python 函数,我们继续推进~)
参考(公开信息):agency-agents 项目说明中提到多个工具的安装路径与转换脚本(如 ./scripts/convert.sh、./scripts/install.sh;Claude Code 安装到 ~/.claude/agents/;OpenClaw 形态为 SOUL.md + AGENTS.md + IDENTITY.md)。
