标签 AI代理 下的文章

我和同事们目前正在利用 OpenCode(Claude Code 的一个替代方案)进行一项小研究。目前我们刚开始测试 gpt-5-mini,看看它在编程辅助方面的性能能否与 Claude Sonnet 媲美。

也非常欢迎大家亲自尝试研究并分享心得,比如哪种 LLM 模型成功率最高,以及使用了什么样的 Prompt(提示词)。

注:我是来自印尼的用户,正在使用 Google Gemini 协助翻译论坛里的讨论。如果翻译有不准确的地方,还请大家多多包涵,手下留情。


📌 转载信息
原作者: galpt
转载时间: 2026/1/25 08:06:35

从上次说起

我的skill都可以在这里看到

安装也是非常的简洁

npx skills add BenedictKing/codex-review
npx skills add BenedictKing/tavily-web
npx skills add BenedictKing/context7-auto-research
npx skills add BenedictKing/exa-search
npx skills add BenedictKing/firecrawl-scraper

上下文占用非常少,主打的就是一个省钱还好用


📌 转载信息
原作者: Foward
转载时间: 2026/1/25 08:04:37

一、概述

LangGraph是LangChain团队开发的低级别编排框架,专为构建、管理和部署长时间运行的有状态AI代理设计,提供持久化执行、灵活控制流和全面内存管理功能,支持循环和条件分支,是开发复杂AI工作流的理想选择。

1.1 核心特点

  • 持久执行:自动保存执行状态,支持故障恢复和断点续跑
  • 循环与分支:突破传统DAG限制,支持复杂的条件判断和循环逻辑
  • 全面内存:集成短期工作内存和长期持久内存,支持跨会话状态保留
  • 人机协作:内置中断机制,允许人工介入审批或修改代理行为
  • 流支持:实时输出执行结果,包括LLM的token级流式响应
  • 可观察性:无缝集成LangSmith,提供完整的执行轨迹和状态转换可视化

二、核心概念

2.1 状态(State)

共享内存,所有节点都可读写的全局数据结构,是代理的"工作记忆"。

  • 定义为Python的TypedDict或dataclass,包含代理需要的所有信息
  • 存储原始数据而非格式化文本,确保不同节点可灵活使用
  • 示例:

    from typing import TypedDict
    class AgentState(TypedDict):
        messages: list  # 对话消息列表
        search_results: list  # 搜索结果
        user_preferences: dict  # 用户偏好

2.2 节点(Nodes)

图的基本执行单元,是接收状态并返回更新的函数。

  • 类型:

    • LLM节点:调用语言模型进行文本理解或生成
    • 工具节点:执行外部API调用、数据库查询等
    • 数据处理节点:转换或分析数据
    • 人工介入节点:暂停执行等待用户输入
  • 定义示例:

    def greet(state: AgentState) -> dict:
        return {"greeting": f"Hello, {state['user_name']}!"}

2.3 边(Edges)

节点间的连接,定义执行流的路径。

  • 普通边:始终执行固定路径
  • 条件边:根据状态决定下一步执行节点
  • 定义示例:

    # 普通边:从"start"到"greet"
    graph.add_edge("start", "greet")
    
    # 条件边:根据状态判断是执行"search"还是"reply"
    def decide_next(state: AgentState) -> str:
        return "search" if state["needs_info"] else "reply"
    graph.add_conditional_edges("greet", decide_next)

三、架构与工作原理

3.1 图结构

LangGraph使用有向图模型表示代理工作流,包含:

  • 特殊节点

    • START:执行入口点
    • END:执行结束点
  • 执行模型:基于"消息传递"的迭代执行,以离散"超步骤"(super-step)推进

3.2 状态管理

  • 短期内存:线程范围内存,随执行结束自动清除
  • 长期内存

    • 存储于独立的Store系统,支持跨会话、跨线程访问
    • 使用namespacekey组织数据,类似文件系统的目录和文件名
    • 支持多种存储后端:内存(开发)、PostgreSQL(生产)、Redis等

3.3 执行流程

  1. 初始化状态并设置入口节点
  2. 执行入口节点,更新状态
  3. 根据边的类型(普通/条件)决定下一节点
  4. 重复直到到达END或达到递归限制(默认25步)
  5. 执行过程中自动保存检查点,支持故障恢复

四、存储方案

LangGraph支持多种存储后端,满足不同场景需求:

存储类型适用场景特点配置示例
InMemoryStore开发测试速度快,无持久化store = InMemoryStore()
PostgresStore生产环境高可靠,支持事务store = PostgresStore("postgresql://user:pass@host/db")
RedisStore分布式系统高性能读写,适合缓存store = RedisStore("redis://host:port")
SQLiteStore轻量级应用文件存储,无需服务器store = SQLiteStore("langgraph.db")

长期记忆配置

from langgraph.store.postgres import PostgresStore
from langgraph.backends import CompositeBackend, StateBackend, StoreBackend

# 配置复合存储:/memories/路径下的数据持久化,其他临时存储
def make_backend(runtime):
    return CompositeBackend(
        default=StateBackend(runtime),  # 临时存储
        routes={"/memories/": StoreBackend(runtime, PostgresStore("..."))}  # 持久存储
    )

五、使用方法

5.1 安装

pip install -U langgraph  # Python版本
npm install @langchain/langgraph  # JavaScript版本

5.2 基本使用步骤

1. 定义状态

from typing import TypedDict
class ChatState(TypedDict):
    messages: list  # 对话消息列表

2. 构建图

from langgraph.graph import StateGraph, START, END
from langchain.llms import OpenAI

# 初始化图
graph = StateGraph(ChatState)

# 定义节点:调用LLM生成回复
def call_llm(state: ChatState):
    llm = OpenAI(temperature=0)
    response = llm.invoke(state["messages"])
    return {"messages": state["messages"] + [response]}

# 添加节点和边
graph.add_node("generate_response", call_llm)
graph.add_edge(START, "generate_response")
graph.add_edge("generate_response", END)

3. 编译并执行

# 编译为可执行应用
app = graph.compile()

# 执行
initial_state = {"messages": [{"role": "user", "content": "Hello!"}]}
final_state = app.invoke(initial_state)
print(final_state["messages"][-1]["content"])  # 输出AI回复

5.3 条件执行与循环

# 定义条件函数:检查是否需要调用工具
def needs_tool(state: ChatState) -> Literal["use_tool", "reply"]:
    last_message = state["messages"][-1]
    return "use_tool" if last_message.get("tool_calls") else "reply"

# 添加条件边
graph.add_conditional_edges("generate_response", needs_tool)

# 添加工具节点和循环边
graph.add_node("use_tool", tool_node)
graph.add_edge("use_tool", "generate_response")  # 循环回LLM节点

六、API参考

6.1 Graph API

核心类

  • StateGraph:构建状态驱动的图,需传入状态类型
  • MessageState:预定义的消息状态,适合聊天应用
  • Checkpointer:管理执行状态的保存和恢复

关键方法

  • add_node(name, function, **kwargs):添加节点,支持重试策略等配置
  • add_edge(from_node, to_node):添加普通边
  • add_conditional_edges(from_node, condition_func):添加条件边
  • compile(checkpointer=None):编译图为可执行应用,支持持久化配置
  • invoke(input_state, config=None):执行图,返回最终状态

6.2 Functional API (简化版)

提供更简洁的方式构建小型工作流:

from langgraph import entrypoint, task

@entrypoint
def my_agent():
    state = {"counter": 0}
    while state["counter"] < 3:
        state = task(increment)(state)  # 调用任务函数
    return state

@task
def increment(state):
    state["counter"] += 1
    return state

result = my_agent()  # 执行

七、开发指南

7.1 构建步骤

  1. 设计工作流:将问题分解为离散步骤,确定节点间依赖关系
  2. 定义状态:确定需要在步骤间共享的数据
  3. 实现节点:为每个步骤编写函数,处理输入状态并返回更新
  4. 连接节点:使用边定义执行顺序,添加必要的条件判断
  5. 添加内存:配置检查点和持久化,实现长期记忆
  6. 测试与调试:使用LangSmith可视化执行过程,检查状态转换

7.2 最佳实践

状态设计

  • 只存储必要信息,避免冗余
  • 保持状态原始,在节点内格式化输出
  • 使用描述性键名,提高可读性

节点设计

  • 单一职责:每个节点专注做一件事
  • 错误处理:为不同错误类型设置适当的处理策略(重试/回退/人工介入)
  • 外部调用:将API调用、数据库操作等封装为独立节点,便于添加重试和监控

内存管理

  • 短期数据存于状态,长期数据使用专用存储
  • 定期清理过时数据,优化存储性能
  • 使用命名空间组织长期数据,便于管理和查询

八、调试与监控

8.1 使用LangSmith集成

LangGraph无缝集成LangSmith,提供全面的可观察性:

# 启用LangSmith追踪
import os
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = "..."

# 编译图时启用追踪
app = graph.compile(checkpointer=checkpointer, trace=True)

监控功能

  • 执行轨迹可视化:查看完整执行路径和状态变化
  • 性能分析:测量各节点执行时间,识别瓶颈
  • 异常检测:自动标记执行错误和异常路径
  • 交互式调试:在LangSmith Studio中检查中间状态

8.2 本地调试技巧

  • 断点打印:在节点函数中添加print语句,输出关键状态
  • 分步执行:使用graph.invoke并传入小输入,逐步验证每个节点
  • 错误处理:为节点添加详细的异常捕获和日志记录:

    def safe_node(state):
        try:
            # 正常逻辑
        except Exception as e:
            return {"error": str(e)}  # 返回错误信息而非崩溃

九、部署方案

9.1 自托管部署

使用Docker

# 安装CLI
pip install -U langgraph-cli

# 构建镜像
langgraph build --name my-agent .

# 运行
docker run -p 8124:8124 my-agent

生产配置建议

  • 使用PostgreSQL作为存储后端,确保数据持久化
  • 配置数据加密,保护敏感信息
  • 设置适当的资源限制,防止滥用
  • 使用负载均衡和水平扩展,提高吞吐量

9.2 LangSmith Cloud (原LangGraph Platform)

提供一键式云部署:

  • Lite版本:免费使用,每年限制100万节点执行
  • Enterprise版本:全功能支持,适合大规模生产环境

优势

  • 自动扩展和高可用性
  • 内置监控和告警系统
  • 开箱即用的安全与合规功能
  • 与LangSmith无缝集成,提供完整的可观察性

十、完整示例:构建天气查询代理

# 1. 安装依赖
pip install langgraph langchain openai

# 2. 导入必要模块
from typing import TypedDict, Literal
from langchain.llms import OpenAI
from langchain_core.messages import HumanMessage, AIMessage
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver  # 内存检查点

# 3. 定义状态
class WeatherAgentState(TypedDict):
    messages: list  # 对话消息
    location: str  # 查询的城市
    weather_info: str  # 天气信息

# 4. 定义工具函数
def get_weather(location: str) -> str:
    """简化的天气查询API"""
    if location.lower() == "sf":
        return "60°F, foggy"
    elif location.lower() == "ny":
        return "90°F, sunny"
    else:
        return "Weather data not available for this location"

# 5. 定义节点
def initial_prompt(state: WeatherAgentState) -> dict:
    """询问用户想查询哪个城市的天气"""
    llm = OpenAI(temperature=0)
    response = llm.invoke([HumanMessage(content="Which city's weather would you like to check?")])
    return {"messages": [response]}

def parse_location(state: WeatherAgentState) -> dict:
    """从用户消息中提取城市名"""
    last_message = state["messages"][-1]
    location = last_message.content.strip().lower()
    return {"location": location, "messages": state["messages"] + [AIMessage(content=f"Checking weather for {location}...")]}

def get_weather_info(state: WeatherAgentState) -> dict:
    """调用天气工具获取信息"""
    weather = get_weather(state["location"])
    return {"weather_info": weather, "messages": state["messages"] + [AIMessage(content=f"Weather in {state['location']}: {weather}")]}

# 6. 构建图
graph = StateGraph(WeatherAgentState)

# 添加节点
graph.add_node("initial_prompt", initial_prompt)
graph.add_node("parse_location", parse_location)
graph.add_node("get_weather_info", get_weather_info)

# 添加边定义执行流
graph.add_edge(START, "initial_prompt")
graph.add_edge("initial_prompt", "parse_location")
graph.add_edge("parse_location", "get_weather_info")
graph.add_edge("get_weather_info", END)

# 7. 添加内存支持
checkpointer = MemorySaver()  # 使用内存检查点保存状态
app = graph.compile(checkpointer=checkpointer)

# 8. 执行代理
first_run = app.invoke({})
print("First run output:")
for msg in first_run["messages"]:
    print(f"{msg['role'].capitalize()}: {msg['content']}")

print("\nSecond run (with state persistence):")
# 第二次执行会保留之前的对话状态
second_run = app.invoke({})
for msg in second_run["messages"]:
    print(f"{msg['role'].capitalize()}: {msg['content']}")

十一、总结

LangGraph是构建复杂AI代理的强大框架,通过状态驱动的图结构,提供了持久执行、灵活控制流和全面内存管理能力。使用LangGraph,开发者可以轻松构建具有记忆、能够处理复杂逻辑的AI代理,适用于客服、研究助手、自动化工作流等多种场景。

本地架设也行,丢到服务器上去也行,基于opencode serve,可以直接选择自定义的agent和模型,每个agent都是独立线程,完全模拟群聊的感觉


📌 转载信息
转载时间: 2026/1/18 12:10:31

最近一直在折腾 AI Agent ,发现让 Agent 可靠地与 Web 交互是个大难题,现有工具要么太底层,要么不够灵活。所以动手撸了一个轮子: @isdk/web-fetcher,想和大家分享一下,也希望能得到一些反馈。

解决了什么痛点?

你可能会问,为啥不用 fetch 或 Playwright/Crawlee ?

  • fetch 拿不到 JS 动态渲染的内容,对现代网页基本没用。
  • Playwright 虽然强大,但需要写大量命令式的过程代码 (await page.click(...) 等),不仅繁琐,而且 AI (比如 LLM) 很难直接生成这种复杂的逻辑。

我不想重复造轮子,所以底层用了Crawlee 库来处理。

我的目标是在 Crawlee 之上构建一个跨引擎一致性:抽象/模拟 HTTP 与 Browser 的共有行为,声明式的“意图层”,让 AI 可以通过生成简单的 JSON 来“指挥”浏览器完成任务,而不是去写具体的执行代码。

核心功能

  • ⚙️ 双引擎架构: 你可以选择 http 模式(基于 Cheerio )来极速抓取静态内容,也可以用 browser 模式(基于 Playwright )来处理复杂的动态网页。
  • ✨ 统一的操作模型 (核心设计): 这是最关键的一点。我抽象了 http 和 browser 模式下的共性行为。无论底层用哪个引擎,你都使用同一套 actions API 。比如 extract (提取数据) 这个操作,在 http 模式下它会通过 Cheerio 解析静态 HTML ,在 browser 模式下它会操作浏览器渲染后的 DOM 。你只需要学习一套 API ,库在内部完成了适配和翻译。
  • ? 声明式操作脚本: 基于统一的模型,你可以用 JSON 定义一个多步骤任务流(登录、填表、点击),AI 生成这个 JSON 的成本远低于生成 JS 代码。
  • ? 强大的数据提取: 同样是声明式的 Schema ,轻松从页面提取结构化数据。
  • ?️ 内置反爬: browser 模式下开启 antibot: true,能处理一些常见的 Cloudflare 挑战。
  • ? 易于扩展: 可以自己封装常用的操作,比如把“登录知乎”封装成一个 loginToZhihu 的自定义动作。

快速上手:提取个标题

注意,下面的代码不关心目标 URL 是静态还是动态的,extract 操作在两种模式下都有效。

import { fetchWeb } from '@isdk/web-fetcher';
async function getTitle(url: string) {
  const { outputs } = await fetchWeb({
    url,
    actions: [
      {
        id: 'extract',
        params: {
          selector: 'title', // 提取 <title> 标签内容
        },
        storeAs: 'pageTitle', // 结果存到 outputs.pageTitle
      },
    ],
  });
  console.log('页面标题:', outputs.pageTitle);
}
getTitle('https://blog.xiaohack.org');

进阶玩法:多步表单提交 (Google 搜索)

这个例子展示了如何用 JSON 指挥浏览器执行一系列动作。

import { fetchWeb } from '@isdk/web-fetcher';
async function searchGoogle(query: string) {
  const { result } = await fetchWeb({
    url: 'https://www.google.com',
    engine: 'browser', // 显式指定需要浏览器环境
    actions: [
      // 步骤 1: 找到输入框并填入内容
      { id: 'fill', params: { selector: 'textarea[name=q]', value: query } },
      // 步骤 2: 提交表单
      { id: 'submit', params: { selector: 'form' } },
      // 步骤 3: 等待搜索结果容器加载出来
      { id: 'waitFor', params: { selector: '#search' } },
    ]
  });
  console.log('搜索结果页 URL:', result?.finalUrl);
}
searchGoogle('xiaohack');

项目状态

项目刚起步,核心架构已经搭好。下一步计划是实现更智能的抓取策略(比如发现 http 模式拿不到内容时,自动升级到 browser 模式)。

项目是开源的,欢迎大家试用、Star 、提 Issue ,或者狠狠地拍砖!感谢。

设计初衷:

单次CLaude code任务会执行文件查看,理解,执行的过程。对于相同的prompt,可能会出现每次查看的文件都不相同,进而导致任务执行偏差。简单的任务往往都可以正常完成,但一旦复杂起来就会出现执行偏差。
上述仅仅是单次提问就可能存在的问题,在一个完整的工作流中往往要经过多次执行过程,整个过程中误差是在累计的,最终导致偏离执行目标。举个例子:

  • 提示词1:“开发XX功能”
  • 提示词2: “查看XX文件中架构设计,开发XX功能”。

提示词2应该要好于第一个。尽管第一个提示词大多数可以执行成功,但是对于工作流来说是不可接受的,因为误差会累计。

对于上述问题,我观察的现有工作流对任务进行细分、拆解,形成一条条的执行任务,但是缺少上下文获取步骤。这是我认为 当前工作流从0到1开发完全可以,但是用于从1到2的开发比较难用的原因。

解决方案:

为了解决上述问题,设计了Claude-code-workflow(CCW) ,广泛吸收现有的技术,多个AI模型cli 集成设计(当前gemini claude gpt 模型各有特点,我觉得应该取长补短,综合利用),exa code mcp 示例搜索,code index现有代码库检索等主要从几个方面减少过程误差:

  • 优化行动规划步骤,一个行动规划过程,分为context_package获取(借助mcp形成任务与现有代码库的关联的json文件),cli规划增强(借助gemini、codex长上下文能力,增强现有规划,比如重点关注的文件等等,现有规划存在误区),task生成(从全局视角,预定义每个task需要查看哪些文件,获取哪些内容,在规划阶段,规范agent执行流程)
  • 将任务文档从md格式转成json清单,通过结构化的数据让agent准确执行流程。json中定义agent执行步骤,核心在于pre_analysis上下文获取步骤(上下文获取,API示例获取,cli辅助分析)
  • cli辅助分析:利用gemini长上下文及免费额度,理解架构,快速定位bug。
尽管从架构设计,减少工作流误差,但是仍需要人为把控,才能产出好的代码

如何设计claude code工作流:

开发过程全部在claude code中完成,利用自带的plan功能,先从整体架构设计出发,生成相应的命令和agent,通过实例观察claude code执行情况,逐步细化,迭代修改过程。有一些核心要点:

  • 对于全局CLAUDE.md 我认为应该放代码执行准则,工具调用准则,这个应该是被主流程和agent加载的,内容不要太多。
  • outputstyle 这个只影响主流程,记忆效果貌似要优于CLAUDE.md。可以放一些,工作流在主流程中的规范,如,使用todowrite跟踪复杂任务执行等类似的。
  • commands 是核心,是工作流流重点设计的地方。可以采用模块化设计,复用command。
  • 文档可以进行层次化、模块化设计,将相同功能介绍归类同一文档,可通过@引用子文档。

附带 精简优化指令的提示词:

# Master Prompt v2.0: Technical Command Reference Architect

## 1. 角色与使命 (Role & Mission)

你是一位顶尖的 **技术文档架构师 (Technical Document Architect)**。你的专长在于将复杂的、叙事性的技术规范(尤其是关于命令行工具或自动化流程的文档),解构、重组并升华为高度结构化、可操作的“速查参考手册”。

**你的核心能力包括:**
- **信息架构 (Information Architecture):** 识别并抽象出文档中的核心概念、流程、条件逻辑和具体指令。
- **内容甄别 (Content Discrimination):** 能够精确区分**叙事性文本**(需重构)、**模板化信息**(必须保留原样,如JSON示例)、**内联引用**(必须保留格式)和**可执行指令**(需转换为代码块)。
- **逻辑与命令的可视化 (Logic & Command Visualization):** 精通使用高级流程图 (`->`) 表达宏观顺序,使用伪代码 (`pseudocode`) 表达抽象条件逻辑,并使用格式化的 Bash 代码块 (`bash`) 呈现具体、可执行的命令。

**你的使命:** 接收一份 Markdown 格式的命令技术文档,严格遵循下述思维链和转换规则,输出一份经过彻底重构、清晰易查的参考文档。关键在于 **100% 保留原始信息**,但以最优化的形式呈现。

---

## 2. 核心思维链 (Chain of Thought) - 你的内在工作流程

**你必须在最终输出的最顶端,使用一个独立的 Markdown 代码块,标题为 `思考过程`,来展示你遵循以下步骤的完整思考过程。这是强制要求。**

1.  **步骤一:预处理与内容分类 (Pre-processing & Content Classification)**
    -   **识别固定元素:** 完整复制 `---` 包裹的 YAML 头信息(如果存在)。
    -   **识别并标记“不可变”内容 (CRITICAL):** 扫描整个文档,标记所有必须保持原样的内容。这包括两类:
        1.  **模板化信息:** 代码块(` ```json` 等)、文件结构图、API 响应/请求示例、完整配置文件。
        2.  **内联引用 (Inline References):** 所有以 `@` 符号开头的引用标识符(例如 `@some-document`, `@argument-name`)。
    -   **识别“可执行指令”:** 定位所有描述具体操作或工具调用的文本,特别是以 `Action:` 或 `Tool:` 开头的行。这些是转换为 `bash` 代码块的候选者。
    -   **建立心智模型:** 通览其余的叙事性文本,理解命令或流程的宏观目标、功能、各个阶段和内在逻辑。

2.  **步骤二:概念解构与分块 (Conceptual Deconstruction & Chunking)**
    -   **识别逻辑单元:** 将**叙事性文本**和**可执行指令**分解为独立的逻辑“概念块”(例如,一个协议、一个阶段、一个特定的逻辑判断)。
    -   **规划卡片结构:** 为每个“概念块”以及每个被标记的“模板化信息”规划一个“卡片”作为其最终归宿。为每个卡片拟定一个简洁、信息丰富的标题(例如,`### Phase 1: Goal Analysis & System Planning`)。**优先将原文中的标题(如 `## Phase 1...`)作为卡片标题。**

3.  **步骤三:为每个分块选择最佳表现形式 (Representation Strategy per Chunk)**
    -   **审视内容本质:** 对每一个“概念块”进行精确判断。
    -   **应用转换规则:**
        -   **模板化信息:** **直接复制,不作任何修改**。
        -   **陈述性/描述性文本:** 提炼为要点列表 (`-`)。
        -   **宏观顺序性文本:** 转换为高层级箭头流程 (`A -> B -> C`)。
        -   **具体指令/工具调用 (Action/Tool):** 转换为带注释的 Bash 代码块 (` ```bash ... ``` `)。
        -   **抽象条件/循环逻辑:** 编写为伪代码块 (` ```pseudo ... ``` `)。这是为不涉及具体命令的 IF/ELSE 或循环逻辑保留的。

4.  **步骤四:内容转换与组装 (Transformation & Assembly)**
    -   **逐块执行转换/迁移:**
        -   在所有转换过程中,**务必确保其中包含的任何 `@` 内联引用被原封不动地保留,不添加任何额外的引号或格式**。
        -   对于“可执行指令”,将其转换为 Bash 代码。使用 `#` 注释来解释命令的目的,保留原始上下文。例如,`Action: Read the high-level user goal.` 变为 `read_user_goal # Reads the high-level user goal`。
    -   **逻辑关联实现:** 在编写伪代码或 Bash 时,通过注释 (`//` 或 `#`) 主动交叉引用相关概念或 `@` 标识符。
    -   **逻辑排序与编排:** 将生成的所有卡片按照从高层概览到底层细节的逻辑顺序进行排列。

5.  **步骤五:最终审查 (Final Review)**
    -   **不可变内容校验 (Highest Priority):**
        1.  **模板完整性:** 对比原始文档,确认所有代码块、JSON 结构等是否**一字不差**地保留。
        2.  **内联引用完整性:** 随机抽查几个 `@` 引用,确保它们在输出中存在,且**没有被引号包裹**或做任何修改。
    -   **信息完整性校验:** 检查叙事性文本中的所有核心信息点是否在新格式中有所体现。
    -   **格式与关联性校验:** 检查 YAML 头、卡片格式、流程、Bash 代码和伪代码的格式及关联注释是否正确、清晰。

---

## 3. 转换规则与格式规范 (Transformation Rules & Formatting Standards)

-   **YAML 头 (YAML Header):** 必须是输出的**第一个**元素,且与输入**完全一致**(如果存在)。
-   **不可变内容 (Immutable Content):**
    -   **模板化信息:** 如 JSON, YAML, 文件树等。**处理规则:绝对禁止修改**。
    -   **内联引用:** 以 `@` 符号开头的标识符。**处理规则:必须原样保留,不得添加引号或其他格式**。
-   **卡片 (Card):**
    -   文档的基本组织单元。每个卡片由一个 `###` 级别的 Markdown 标题开始。
-   **要点列表 (Bullet Points):**
    -   用于转换**描述性段落**。
-   **流程 (Flow):**
    -   用于表示**宏观的、多步骤的顺序操作**。使用 `->` 连接。
-   **实际命令 (Actual Commands):**
    -   用于转换**具体的、可执行的指令**(特别是 `Action:` 或 `Tool:` 格式的文本)。
    -   **必须**包裹在 ` ```bash ... ``` `中。
    -   使用 `#` 注释来保留原始描述的上下文。
    -   将指令动词转换为函数式或命令式风格(例如 `Create the project_timeline` -> `create_project_timeline_unit`)。
-   **伪代码 (Pseudocode):**
    -   **专门**用于描述**不涉及具体工具调用的、抽象的条件逻辑或循环**(例如,`IF/ELSE` 决策流程,`FOR` 循环)。
    -   必须包裹在 ` ```pseudo ... ``` `中,并通过注释 (`//`) 关联到具体概念。

---

## 4. 禁止行为 (Prohibitions)

-   **禁止修改模板信息:** 最高级别的禁令。
-   **禁止修改或包装内联引用:** 不得以任何形式修改 `@` 引用。
-   **禁止信息丢失:** 不能省略原始文档中的任何核心功能、参数、约束或默认值。
-   **禁止信息杜撰:** 不得添加原始文档中未提及的任何信息。
-   **禁止混淆表现形式:** 严格遵守何时使用 Bash、何时使用伪代码、何时使用流程图的规则。

---

## 5. 输入文档 (Input Document)

请根据以上所有规则,对以下 Markdown 文档进行重构:


# ? Orchestrator Constitution

## Guiding Principles
- The Timeline (`dmacs/timeline.jsonl`) is the only source of truth for **Published** project artifacts.
- The `system_plan` is the high-level blueprint of goals. Specialist agents handle the detailed "how".
- My primary function is to Audit, Decide, and Delegate Goals. I do not create content.

<!-- MODIFIED -->
## Phase 1: Goal Analysis & System Planning
1.  **Project Initialization**: On initial invocation with a user goal -> `Action: Create the project_timeline D-MACS unit` -> `Action: Publish it by logging the PROJECT_TIMELINE_CREATED event.`
2.  **High-Level Goal Decomposition**: `Action: Read the high-level user goal.` -> `Action: Decompose the goal into a logical sequence of high-level objectives (e.g., Background Research, Method Development, Experimentation, Result Writing, Discussion), using the IMRaD structure as a guiding heuristic.`
3.  **Capability-to-Task Mapping**:
    -   `Action: For each objective, analyze its core intent.`
    -   `Action: Consult my internal knowledge of specialist agent capabilities, derived from their role definitions in the system configuration.`
    -   `Action: Map each objective to the most appropriate specialist agent slug.` (e.g., 'Conduct literature review' -> `researcher`; 'Design and run experiment' -> `experimenter`; 'Draft the introduction' -> `writer`).
4.  **System Plan Creation & Publication**:
    -   `Action: Consolidate the sequence of agent-assigned objectives into a structured `system_plan` D-MACS unit.`
    -   `Action: The plan MUST define the sequence of execution and any dependencies between the objectives.`
    -   `Action: Publish the `system_plan` by logging the DMACS_UNIT_CREATED event.`

## Phase 2: Managed Execution (Observe-Orient-Decide-Act Loop)
1.  **OBSERVE**: `Tool: read(dmacs/timeline.jsonl)` -> Action: Identify the latest un-processed events, which represent Newly Published D-MACS units.
2.  **ORIENT (Audit & State Update)**:
    - `Condition: If a task I delegated has failed` -> Action: Initiate Failure Protocol.
    - `Condition: If a new D-MACS unit was Published` -> Action: Execute the **D-MACS Audit Protocol**.
    - `Action: Update internal model` of project state.
3.  **DECIDE**:
    - `Condition: If audit failed` -> Decision: Halt and create `error_report`.
    - `Condition: If in Write-Review-Revise loop` -> Action: Consult **Revision Loop Protocol**.
    - `Condition: If current high-level goal is complete and approved` -> Action: Consult `system_plan` for the next objective.
    - `Condition: If all objectives in plan are complete` -> Decision: Delegate final task to `integrator`.
4.  **ACT**: `Tool: new_task(...)` or `Action: Create error_report`.

## Core Protocols

### D-MACS Audit Protocol
For every new unit Published on the timeline, I MUST verify:
1.  **Type Check**: Is `meta.json.type` an expected output? (e.g., An `agent_plan` is the expected first Published response from a specialist, followed by their final deliverable.)
2.  **Version Check**: If task was a revision, does `meta.json.relations` contain a valid `PREVIOUS_VERSION` entry?
3.  **Feedback Check**: If type is `review_feedback`, I MUST parse `meta.json.custom_fields.review_details`.


### Revision Loop Protocol
1.  `Action: Read meta.json` of the new `review_feedback` unit.
2.  `Condition: If outcome is "APPROVED"` -> Action: Exit loop for this chapter.
3.  `Condition: If outcome is "REVISION_REQUESTED"`:
    - `Action: Check revision_count_so_far.`
    - `Condition: If count < 5` -> Decision: Re-delegate to `writer` with original draft and new feedback as context. This starts a new Plan-then-Execute cycle for the Writer.
    - `Condition: If count >= 5` -> Decision: Trigger **Failure Protocol (Max Revisions)**.

### Failure Protocol
- `On any failed audit, agent task failure, or max revisions` ->
  1.  `Action: Formulate a detailed description` of the error.
  2.  `Action: Create a new D-MACS unit` with `type: 'error_report'`.
  3.  `Action: Publish the unit by logging the DMACS_UNIT_CREATED` event.
  4.  `Action: Halt all further task delegations`.