50 KiB
PAM 智能部署 LangGraph 重构设计文档
1. 背景
当前 PAM 智能部署能力由三部分组成:
PAM_AUTO_DEPLY_SKILL.md:定义 Agent/Skill 的流程约束、参数确认、执行顺序、回滚规则、检查点和输出规范。- PAM_NODE MCP 工具:面向 Node 在线执行场景,提供可由 Agent 调用的节点侧部署工具能力。
deploy.sh/deploy.ps1:提供实际 API 调用能力,已经暴露 action 入口,可按步骤执行建版、上传、发布、节点发现、云下载、升级、启停、校验、日志下载和回滚。
当前接口能力边界:
- PAM_HOME 接口不具备 MCP 能力,只能通过现有脚本 action 调用。
- PAM_NODE 接口支持 MCP,可以由 Agent 通过 MCP 工具调用。
现有模式的主要问题是:核心编排规则写在 Skill 文档中,依赖 Agent 按文本约束执行;HOME 脚本 action 与 NODE MCP 工具之间缺少统一动作路由;用户意图理解、参数抽取、缺参追问、异常解释等智能能力没有被显式建模;断点续跑、人工确认、回滚确认、进度事件和最终报告缺少一个可测试、可复用、可持久化的 Agent Runtime。
本设计将这套 Skill + PAM_NODE MCP + Shell/PowerShell 脚本组合重构为 LangGraph Agent。LangGraph 不只是顺序执行器,而是承载“大模型推理 + Skill 规则约束 + 混合工具路由 + 人工确认 + 状态持久化”的智能部署 Agent。
2. 设计目标
- 将 LangGraph 实现为 PAM 智能部署 Agent,而不是单纯脚本编排器。
- 支持
Skill + MCP:Skill 提供规则、约束和流程策略,PAM_NODE MCP 提供节点侧在线工具能力。 - 保留现有
deploy.sh/deploy.ps1action 能力,作为 PAM_HOME 固定执行后端,并作为全脚本离线模式后端。 - 引入大模型参与意图理解、参数抽取、缺参追问、执行计划生成、失败解释和报告摘要。
- 对高风险动作使用确定性图节点和人工确认兜底,禁止大模型绕过确认直接部署或回滚。
- 支持 checkpoint 持久化和断点续跑。
- 支持部署过程进度流式输出,避免长时间静默执行。
- 将 PAM_NODE MCP 和 PAM_HOME 脚本 action 输出解析、错误分类、最终报告生成标准化。
- 为后续服务化、可视化和 Python 原生 API client 迁移预留接口。
3. 非目标
第一阶段不做以下事情:
- 不自动生成、覆盖或修改
deploy.sh、deploy.ps1、deploy.bat、测试脚本。 - 不调用脚本主流程做真实部署,只调用 action 入口。
- 不把
CLIENT_SECRET等敏感字段拼接到命令行。 - 不自动执行回滚。
- 不在正式主流程里使用
download-cloud-to-node。 - 不一次性重写所有 PAM HTTP API 调用。
- 不让大模型直接执行高风险工具调用;大模型只能生成建议、解释和结构化计划,真实动作由图节点在确认后执行。
4. 总体架构
用户输入 / CLI / API / Chat
|
v
LangGraph PAM Deploy Agent
|
|-- Skill Loader
| |-- 加载 PAM_AUTO_DEPLY_SKILL.md
| |-- 提取硬约束、参数规范、流程策略
|
|-- LLM Reasoning Layer
| |-- 意图理解
| |-- 参数抽取与缺参追问
| |-- 部署计划生成
| |-- 失败原因解释
| |-- 报告摘要生成
|
|-- Deterministic Graph Layer
| |-- 人工确认 interrupt
| |-- 流程路由
| |-- checkpoint 更新
| |-- 回滚确认 interrupt
| |-- 安全策略校验
|
|-- Tool Runtime Layer
|-- ActionRouter
|-- MCPActionRunner
|-- ScriptActionRunner
|-- OutputParser
|-- EventBus
|
v
工具后端
|
|-- PAM_NODE MCP tools
|-- deploy.sh --action ...
|-- deploy.ps1 -Action ...
|
v
PAM HOME / PAM NODE API
核心原则是:大模型负责理解、规划、解释和生成候选动作;Skill 负责约束大模型和 Agent 的行为边界;LangGraph 确定性节点负责确认、状态和动作路由;PAM_HOME 动作固定走脚本 action;PAM_NODE 动作优先走 MCP,必要时可按用户确认降级到脚本 action。
4.1 Agent 分层
PAM LangGraph Agent 分为四层:
-
Skill Policy Layer- 读取并解析
PAM_AUTO_DEPLY_SKILL.md。 - 形成系统提示词、工具白名单、确认点、禁止事项和流程约束。
- 对 LLM 输出做规则校验。
- 读取并解析
-
LLM Reasoning Layer- 从自然语言中识别部署意图。
- 抽取业务参数和控制参数。
- 判断是否缺参或存在歧义。
- 生成用户可读的部署计划、风险提示、失败解释和最终摘要。
-
Deterministic Orchestration Layer- 用 LangGraph StateGraph 固化主流程。
- 执行人工确认、条件路由、checkpoint、重试和断点续跑。
- 决定何时允许调用工具。
-
Tool Runtime Layer- 按 action 粒度路由 HOME/NODE 动作。
- PAM_HOME 脚本 action 后端。
- PAM_NODE MCP 在线工具后端。
- 全脚本离线后端。
- Fake runner 测试后端。
- 统一 action 结果、错误和事件格式。
4.2 大模型介入点
大模型介入但不越权执行:
| 阶段 | LLM 作用 | 确定性约束 |
|---|---|---|
| 意图识别 | 判断是部署、预演、查询、回滚还是用法说明 | 输出必须符合枚举 intent |
| 执行策略选择 | 结合用户表达判断使用混合执行还是全脚本执行 | HOME 固定脚本,NODE 可选 MCP 或脚本 |
| 参数抽取 | 从自然语言、文件片段或对话上下文抽取参数 | 必填参数缺失时不能进入真实 action |
| 缺参追问 | 生成简短追问 | 只问缺失或歧义字段 |
| 部署计划 | 生成用户可读执行计划和风险提示 | action 顺序由图固定,不由 LLM 任意改 |
| 失败解释 | 将 action 错误、HTTP 响应和日志摘要解释给用户 | 原始错误必须保留 |
| 回滚建议 | 根据失败阶段建议 stopFirst |
回滚必须 interrupt 等用户确认 |
| 最终报告 | 生成摘要和后续建议 | 统计数据来自 State,不由 LLM 编造 |
禁止大模型做的事情:
- 直接调用真实部署工具。
- 跳过参数确认。
- 跳过 IP 范围确认。
- 自动执行回滚。
- 修改现有脚本文件。
- 编造 action 执行结果。
4.3 Skill + MCP 混合执行方式
Skill + MCP 在本项目中的实际含义是“HOME 脚本 action + NODE MCP 工具”的混合执行,而不是全链路 MCP。
PAM_AUTO_DEPLY_SKILL.md
|
v
SkillPolicy
|
v
LangGraph Agent
|
v
ActionRouter
|
|-- PAM_HOME action -> ScriptActionRunner -> deploy.sh/deploy.ps1
|
|-- PAM_NODE action -> MCPActionRunner -> PAM_NODE MCP tools
|
v
PAM HOME / PAM NODE
当用户明确要求“用 MCP”“直接在线执行”“不要生成脚本”,Agent 仍需要说明:PAM_HOME 当前没有 MCP 能力,HOME 阶段会通过现有脚本 action 执行;PAM_NODE 阶段使用 MCP 工具执行。
当 PAM_NODE MCP 不可用、用户明确要求脚本模式、或需要离线执行时,整轮部署可切换为全脚本执行,但必须在真实部署前向用户确认。
执行策略选择规则:
- 默认策略:
hybrid_node_mcp,即 HOME 走脚本 action,NODE 走 MCP。 - 用户明确指定 MCP:使用
hybrid_node_mcp;如果 NODE MCP 不可用则停止并说明,不自动改为全脚本。 - 用户明确指定脚本或离线:使用
script_only,所有 action 都走deploy.sh/deploy.ps1。 - 用户只说“帮我部署”:默认
hybrid_node_mcp;如果 NODE MCP 不可用,询问是否切换script_only。 - 用户只要用法或预演:不调用 MCP,也不调用脚本。
- 高风险动作无论 MCP 还是脚本,都必须先通过参数确认。
标准 action 归属:
| action | 接口归属 | 默认执行后端 |
|---|---|---|
get-token |
PAM_HOME | 脚本 action |
create-version |
PAM_HOME | 脚本 action |
upload-package |
PAM_HOME | 脚本 action |
publish-version |
PAM_HOME | 脚本 action |
get-node-url |
PAM_HOME | 脚本 action |
get-online-ips |
PAM_NODE | MCP |
create-download-task |
PAM_NODE | MCP |
poll-download-progress |
PAM_NODE | MCP |
upgrade-ip |
PAM_NODE | MCP |
poll-upgrade-progress |
PAM_NODE | MCP |
start-ip |
PAM_NODE | MCP |
stop-ip |
PAM_NODE | MCP |
verify-ip |
PAM_NODE | MCP |
download-log |
PAM_NODE | MCP |
rollback-ip |
PAM_NODE | MCP,且必须人工确认 |
5. 推荐目录结构
pam_deploy_graph/
__init__.py
agent.py
cli.py
graph.py
state.py
constants.py
skill_policy.py
nodes/
__init__.py
skill.py
intent.py
params.py
planning.py
confirmation.py
backend.py
tools.py
scripts.py
config_writer.py
global_actions.py
ip_actions.py
rollback.py
report.py
llm/
__init__.py
client.py
prompts.py
structured_outputs.py
validators.py
runtime/
__init__.py
action_router.py
tool_registry.py
mcp_runner.py
script_runner.py
fake_runner.py
output_parser.py
checkpoint_store.py
event_bus.py
file_lock.py
schemas/
__init__.py
skill.py
params.py
plan.py
action_result.py
checkpoint.py
report.py
tests/
test_output_parser.py
test_skill_policy.py
test_llm_structured_outputs.py
test_mcp_runner.py
test_script_runner.py
test_graph_routes.py
test_checkpoint_resume.py
fixtures/
action_outputs/
后续服务化时可新增:
pam_deploy_api/
app.py
routes.py
sse.py
6. 关键状态模型
LangGraph 的 State 是整个 Agent 的事实来源。建议使用 TypedDict 或 Pydantic model。第一版如果需要开发速度,可用 TypedDict;如果需要更强校验,使用 Pydantic。
class DeployState(TypedDict, total=False):
run_id: str
thread_id: str
user_input: str
messages: list[dict]
skill: SkillPolicy
skill_version: str
skill_source_path: str
llm_intent_result: LlmIntentResult
llm_param_result: LlmParamResult
llm_plan: LlmDeployPlan
mode: Literal["MCP", "API脚本"]
execution_strategy: Literal["hybrid_node_mcp", "script_only", "fake"]
action_backends: dict[str, Literal["mcp", "script", "fake"]]
intent: Literal[
"deploy",
"show_usage",
"preview",
"query_node_ips",
"rollback"
]
show_usage_only: bool
params: DeployParams
control: ControlParams
node_mcp_server_name: str
node_mcp_tool_names: dict[str, str]
script_entry: Literal["deploy.sh", "deploy.ps1"]
script_base_dir: str
config_path: str
checkpoint_path: str
trace_file_path: str
confirmation: ConfirmationState
completed_global_steps: list[str]
token_acquired: bool
hash_code: str
node_url: str
online_ips: list[str]
target_ips: list[str]
ip_states: dict[str, IpDeployState]
last_success_step: str
last_failed_step: str
pending_confirmation: str
errors: list[DeployError]
events: list[DeployEvent]
final_report: str
6.1 SkillPolicy
SkillPolicy 是从 PAM_AUTO_DEPLY_SKILL.md 加载出的规则对象,供 LLM prompt、图路由和工具执行共同使用。
class SkillPolicy(TypedDict):
name: str
source_path: str
allowed_modes: list[str]
allowed_actions: list[str]
forbidden_actions: list[str]
required_confirmations: list[str]
required_params: list[str]
optional_params: dict[str, object]
action_sequence: list[str]
ip_action_sequence: list[str]
rollback_rules: dict[str, object]
output_requirements: dict[str, object]
用途:
- 作为 LLM system prompt 的事实来源。
- 作为确定性节点的规则输入。
- 作为工具白名单和执行顺序约束。
- 当 Skill 文档更新时,Agent 不需要散落修改多个节点。
6.2 ActionRoute
ActionRoute 描述每个标准 action 的接口归属和实际执行后端。
class ActionRoute(TypedDict):
action: str
api_domain: Literal["PAM_HOME", "PAM_NODE"]
backend: Literal["script", "mcp", "fake"]
required_inputs: list[str]
produces: list[str]
默认路由:
PAM_HOMEaction 固定backend=script。PAM_NODEaction 在hybrid_node_mcp策略下backend=mcp。PAM_NODEaction 在script_only策略下backend=script。
6.3 DeployParams
class DeployParams(TypedDict):
HOME_BASE_URL: str
CLIENT_ID: str
CLIENT_SECRET: str
AIRPORT_CODE: str
APP_NAME: str
MODULE_NAME: str
VERSION_NUMBER: str
ZIP_FILE_PATH: str
ACTION_TYPE: str
TIMEOUT: int
LOG_NAME: str
默认值:
ACTION_TYPE = "FULL"TIMEOUT = 120LOG_NAME = "app.log"
6.4 ControlParams
class ControlParams(TypedDict):
user_specified_ips: list[str]
all_or_nothing: bool
rollback_approved: bool
os_target: Literal["windows", "linux", "macos", "git-bash"]
resume_from_checkpoint: bool
step_interval_sec: int
first_poll_delay_sec: int
per_ip_step_interval_sec: int
per_ip_interval_sec: int
failure_pause_sec: int
默认值:
step_interval_sec = 2first_poll_delay_sec = 2per_ip_step_interval_sec = 1per_ip_interval_sec = 3failure_pause_sec = 0
6.5 LLM 结构化输出
LLM 节点必须输出结构化对象,不直接输出可执行命令。
class LlmIntentResult(TypedDict):
intent: str
mode_preference: Literal["MCP", "API脚本", "未指定"]
confidence: float
reasons: list[str]
needs_clarification: bool
clarification_questions: list[str]
class LlmParamResult(TypedDict):
extracted_params: dict[str, object]
extracted_control: dict[str, object]
missing_required_params: list[str]
ambiguous_fields: list[str]
sensitive_fields_present: list[str]
class LlmDeployPlan(TypedDict):
summary: str
risk_notes: list[str]
planned_actions: list[str]
requires_confirmation: bool
结构化输出必须经过 validators.py 校验:
intent必须在枚举内。planned_actions必须是 Skill 允许的 action 子集。- 不允许出现 shell 命令或 PowerShell 命令文本。
- 不允许包含
CLIENT_SECRET明文。
6.6 IpDeployState
class IpDeployState(TypedDict, total=False):
ip: str
status: Literal["PENDING", "RUNNING", "SUCCESS", "FAILED", "SKIPPED"]
current_stage: str
completed_steps: list[str]
failed_stage: str
failure_reason: str
rollback_status: Literal[
"ROLLBACK_NOT_RUN",
"PENDING_AGENT_CONFIRMATION",
"ROLLBACK_SUCCESS",
"ROLLBACK_FAILED",
"ROLLBACK_REQUEST_FAILED",
"ROLLBACK_VERIFY_FAILED",
"ROLLBACK_SKIPPED"
]
rollback_stop_first: bool
log_file: str
raw_outputs: dict[str, str]
7. 工作流主图
7.1 主流程
START
-> load_skill_policy
-> llm_understand_request
-> validate_llm_intent
-> llm_extract_params
-> validate_and_normalize_params
-> llm_generate_plan
-> apply_skill_guardrails
-> route_by_intent
route_by_intent:
show_usage -> show_script_usage -> END
preview -> render_preview -> END
query_node_ips -> confirm_params -> select_execution_strategy -> build_action_routes -> prepare_tool_runtimes -> query_node_ips_flow -> END
deploy -> confirm_params -> select_execution_strategy -> build_action_routes -> prepare_tool_runtimes -> deploy_flow
rollback -> rollback_entry_flow
deploy_flow:
init_runtime_files
-> maybe_resume_from_checkpoint
-> get_token
-> create_version
-> upload_package
-> publish_version
-> get_node_url
-> get_online_ips
-> filter_target_ips
-> confirm_target_scope_if_needed
-> create_download_task
-> wait_first_poll_delay
-> poll_download_progress
-> deploy_ip_loop
-> aggregate_result
-> final_report
-> END
说明:
llm_understand_request、llm_extract_params、llm_generate_plan是智能层节点。validate_llm_intent、validate_and_normalize_params、apply_skill_guardrails是确定性安全节点。select_execution_strategy根据用户意图、Skill 规则和 PAM_NODE MCP 可用性选择hybrid_node_mcp、script_only或fake。build_action_routes生成每个 action 的实际后端;HOME action 固定脚本,NODE action 按策略走 MCP 或脚本。prepare_tool_runtimes检查 PAM_NODE MCP 工具、脚本文件和运行时配置。
7.2 单 IP 子流程
deploy_ip:
mark_ip_running
-> upgrade_ip
-> wait_per_ip_step_interval
-> poll_upgrade_progress
-> wait_per_ip_step_interval
-> start_ip
-> wait_per_ip_step_interval
-> verify_ip
-> wait_per_ip_step_interval
-> download_log
-> mark_ip_success
on failure:
record_ip_failure
-> download_log_best_effort
-> mark_pending_rollback
-> rollback_confirm_interrupt
-> route_rollback_decision
第一版建议逐台顺序执行 IP,不做并发。原因是部署动作本身风险较高,当前 Skill 文档也要求逐台播报。后续如果需要并发,可以在单 IP 子图稳定后引入受控 fan-out,并保留最大并发数和失败策略。
7.3 Agent ReAct 子图边界
本设计不采用开放式 ReAct 循环执行真实部署工具。原因是 PAM 部署包含建版、发布、升级和回滚等高风险动作,不能让模型自由选择下一步真实工具。
允许使用受限 ReAct 子图的场景:
- 缺参追问。
- 用户意图澄清。
- 失败原因解释。
- 日志摘要。
- 最终报告文字润色。
不允许使用开放式 ReAct 的场景:
create-versionupload-packagepublish-versioncreate-download-taskupgrade-iprollback-ip
这些动作必须由确定性图节点按照 Skill 固定顺序调用。
8. 节点设计
8.1 load_skill_policy
职责:
- 读取
PAM_AUTO_DEPLY_SKILL.md。 - 解析 Skill frontmatter 和正文中的关键规则。
- 生成
SkillPolicy。 - 将 Skill 规则注入 LLM system prompt 和后续图节点。
失败策略:
- Skill 文件缺失或解析失败时,Agent 不进入真实部署。
8.2 llm_understand_request
职责:
- 调用大模型理解用户自然语言。
- 输出结构化
LlmIntentResult。 - 判断用户是否要求 MCP、脚本、预演、查询或回滚。
约束:
- LLM 只输出结构化意图,不输出命令。
- 置信度低或存在歧义时,进入澄清分支。
8.3 validate_llm_intent
职责:
- 校验 LLM 输出是否符合枚举。
- 按 Skill 规则修正或拒绝不合法意图。
- 例如用户要求“生成脚本”时,转入
show_usage或限制说明分支。
8.4 llm_extract_params
职责:
- 从用户输入、对话上下文、上传的参数文件或历史 checkpoint 中抽取业务参数。
- 识别缺失字段和歧义字段。
- 标记
CLIENT_ID、CLIENT_SECRET等敏感字段是否已提供。
约束:
- 不把
CLIENT_SECRET明文写入普通消息。 - 不猜测必填参数。
8.5 validate_and_normalize_params
职责:
- 将 LLM 抽取结果映射为
DeployParams和ControlParams。 - 补齐默认值。
- 校验必填参数。
- 对机场码、版本号、IP 列表、路径格式做基础校验。
硬约束:
- 必填参数缺失时,不进入真实 action。
- 参数有歧义时,应中断并要求补充。
8.6 llm_generate_plan
职责:
- 基于 Skill 和已归一化参数生成用户可读部署计划。
- 说明执行策略:默认是 HOME 脚本 action + NODE MCP 的混合执行。
- 如果用户要求 MCP,明确提示 HOME 阶段仍会通过脚本 action 执行,因为 PAM_HOME 不具备 MCP 能力。
- 说明高风险动作和确认点。
约束:
- 计划中的 action 顺序必须与 Skill 固定流程一致。
- 计划只用于展示和确认,不作为真实执行序列的唯一来源。
8.7 apply_skill_guardrails
职责:
- 校验 LLM 输出是否违反 Skill 禁止事项。
- 校验是否试图调用脚本主流程。
- 校验是否试图自动回滚。
- 校验是否试图修改脚本。
失败策略:
- 发现违规时终止真实执行并输出限制说明。
8.8 parse_intent
职责:
- 判断用户要真实部署、查看用法、预演计划、查询 Node/IP,还是手动回滚。
- 判断用户是否明确要求
MCP或API脚本。 - 如果用户要求生成或修改脚本,直接进入受限说明分支。
输出:
intentmodeshow_usage_only
说明:
- 该节点保留为确定性兜底逻辑,用于 LLM 不可用或 structured output 失败时的基础规则识别。
8.9 normalize_params
职责:
- 从用户输入、环境变量、配置文件或外部调用参数中收集业务参数。
- 补齐默认值。
- 标记缺失参数。
- 敏感字段不进入普通播报内容。
硬约束:
- 必填参数缺失时,不进入真实 action。
- 参数有歧义时,应中断并要求补充。
说明:
- 该节点保留为确定性兜底逻辑。
8.10 confirm_params
职责:
- 渲染归一化参数确认单。
- 使用 LangGraph interrupt 等待用户确认。
- 未确认前不得调用任何真实 action。
确认单不展示 CLIENT_SECRET 明文,只展示“已提供/未提供”。
8.11 select_execution_strategy
职责:
- 根据用户偏好、PAM_NODE MCP 可用性、Skill 规则和运行环境选择执行策略。
- 输出
execution_strategy = hybrid_node_mcp | script_only | fake。
选择规则:
- 用户明确指定 MCP:选择
hybrid_node_mcp;PAM_NODE MCP 不可用则停止。 - 用户明确指定脚本或离线:选择
script_only。 - 用户未指定且 PAM_NODE MCP 可用:选择
hybrid_node_mcp。 - 用户未指定且 PAM_NODE MCP 不可用:询问是否切换
script_only。 - 测试环境可显式选择 fake runner。
8.12 build_action_routes
职责:
- 根据
execution_strategy生成action_backends。 - HOME action 固定为
script。 - NODE action 在
hybrid_node_mcp下为mcp。 - NODE action 在
script_only下为script。 - fake 策略下所有 action 为
fake。
输出示例:
{
"get-token": "script",
"create-version": "script",
"upload-package": "script",
"publish-version": "script",
"get-node-url": "script",
"get-online-ips": "mcp",
"create-download-task": "mcp",
"poll-download-progress": "mcp",
"upgrade-ip": "mcp",
"poll-upgrade-progress": "mcp",
"start-ip": "mcp",
"verify-ip": "mcp",
"download-log": "mcp",
"rollback-ip": "mcp"
}
8.13 prepare_tool_runtimes
职责:
- 混合执行下:检查脚本文件、选择脚本入口、写入 HOME 脚本配置,同时检查 PAM_NODE MCP server 和工具映射。
- 全脚本执行下:检查脚本文件、选择脚本入口、写入完整脚本配置。
- fake 模式下:加载 fixture 输出。
8.14 check_scripts
职责:
- 检查当前目录下是否存在
deploy.sh/deploy.ps1。 - 检查目标脚本是否可读。
- 不自动补写脚本。
失败策略:
- 缺少脚本时终止流程并输出原因。
8.15 select_script_entry
职责:
- Windows 默认选择
deploy.ps1。 - Linux / macOS / Git Bash 默认选择
deploy.sh。 deploy.bat只作为兼容包装入口,不作为 LangGraph action runner 默认入口。
8.16 write_config
职责:
- 将确认后的业务参数写入
config.txt或本次运行专属配置文件。 - 命令行只传 action 级参数,不传
CLIENT_SECRET。
建议:
- 默认写入
./runtime/config_<run_id>.txt,避免覆盖人工维护的config.txt。 - 如果必须兼容脚本默认路径,可由 CLI 参数指定
--config-path ./config.txt。
说明:
- 混合执行下仍需要写配置文件,因为 PAM_HOME action 固定通过脚本执行。
- 全脚本执行下写完整配置文件。
- PAM_NODE MCP 工具不从
config.txt读参数,由 Agent 通过 MCP tool input 传入必要字段。 CLIENT_SECRET只允许写入受控配置文件或安全凭证通道,不进入命令行和普通日志。
8.17 init_runtime_files
职责:
- 创建
logs/或runtime/目录。 - 生成本次运行的
checkpoint_path。 - 生成本次运行的
trace_file_path。 - 写入初始业务 checkpoint。
命名建议:
logs/deploy_checkpoint_<AIRPORT_CODE>_<APP_NAME>_<MODULE_NAME>_<VERSION_NUMBER>.json
logs/api_trace_<AIRPORT_CODE>_<APP_NAME>_<MODULE_NAME>_<VERSION_NUMBER>_<run_id>.log
8.18 action 节点
每个 action 节点只做四件事:
- 播报即将执行的阶段。
- 通过
ActionRouter按 action 归属调用 MCP 或脚本 action。 - 解析 key=value 输出并更新 State。
- 更新 checkpoint 和进度事件。
全局 action 节点:
get_tokencreate_versionupload_packagepublish_versionget_node_urlget_online_ipscreate_download_taskpoll_download_progress
单 IP action 节点:
upgrade_ippoll_upgrade_progressstart_ipverify_ipdownload_logrollback_ip
8.19 llm_explain_failure
职责:
- 在全局失败或单 IP 失败后,基于
ActionResult、原始输出、阶段名和 Skill 规则生成用户可读解释。 - 给出下一步建议,例如检查凭证、包路径、Node 连通性、在线 IP 或是否回滚。
约束:
- 不能替换原始错误。
- 不能承诺未发生的恢复动作。
- 回滚建议必须进入确认节点。
8.20 final_report
职责:
- 汇总模式、脚本入口、机场、应用、模块、版本。
- 汇总在线 IP 数、目标 IP 数、成功数、失败数。
- 汇总每台 IP 的状态、失败阶段、失败原因、回滚状态、日志路径。
- 输出 checkpoint 和 trace 路径。
- 输出是否断点续跑和当前间隔控制参数。
- 调用 LLM 生成简短摘要,但所有统计值必须来自 State。
9. Tool Runtime 设计
9.1 统一 ToolRunner 接口
class ToolRunner:
def run(
self,
action: str,
*,
params: DeployParams,
config_path: str | None = None,
script_entry: str | None = None,
ip: str | None = None,
hash_code: str | None = None,
stop_first: bool = False,
trace_file_path: str | None = None,
timeout_sec: int | None = None,
) -> ActionResult:
...
ActionRouter 根据 state.action_backends[action] 按 action 粒度分发到具体 runner:
class ActionRouter:
def run_action(self, state: DeployState, action: str, **kwargs) -> ActionResult:
backend = state["action_backends"][action]
if backend == "mcp":
return self.node_mcp_runner.run(action, params=state["params"], **kwargs)
if backend == "script":
return self.script_runner.run(
action,
params=state["params"],
config_path=state["config_path"],
script_entry=state["script_entry"],
**kwargs,
)
return self.fake_runner.run(action, params=state["params"], **kwargs)
9.2 MCPActionRunner
MCPActionRunner 只负责 PAM_NODE action。PAM_HOME 当前没有 MCP 能力,HOME action 不进入 MCPActionRunner。
PAM_NODE MCP 工具映射:
| 标准 action | MCP tool 建议名 | 说明 |
|---|---|---|
get-online-ips |
pam_get_online_ips |
获取在线工作站 |
create-download-task |
pam_create_download_task |
创建云下载任务 |
poll-download-progress |
pam_poll_download_progress |
轮询云下载进度 |
upgrade-ip |
pam_upgrade_ip |
创建单 IP 升级任务 |
poll-upgrade-progress |
pam_poll_upgrade_progress |
轮询单 IP 升级进度 |
start-ip |
pam_start_ip |
启动应用 |
stop-ip |
pam_stop_ip |
停止应用 |
verify-ip |
pam_verify_ip |
校验应用 |
download-log |
pam_download_log |
下载日志 |
rollback-ip |
pam_rollback_ip |
手动回滚 |
MCP runner 职责:
- 发现 PAM_NODE MCP server 和工具列表。
- 将标准 action 映射为 MCP tool。
- 将
DeployParams转为 tool input。 - 读取
node_url、airportCode、applicationName、moduleName、versionNumber、目标 IP 等运行时状态。 - 调用工具并统一转为
ActionResult。 - 保存工具原始返回。
- 对敏感字段做脱敏。
MCP runner 约束:
- 只能调用 Skill 白名单中的 PAM_NODE 工具。
- 不能调用 PAM_HOME action。
rollback-ip必须在回滚确认后调用。- 工具返回结果不得由 LLM 改写后写入 State。
- PAM_NODE MCP 不可用时,不能静默切换脚本后端,除非用户确认
script_only。
9.3 ScriptActionRunner
ScriptActionRunner 有两类职责:
- 在
hybrid_node_mcp策略下,固定执行 PAM_HOME action:get-tokencreate-versionupload-packagepublish-versionget-node-url
- 在
script_only策略下,执行全部 action,包括 PAM_NODE action。
脚本后端仍然只允许调用 action 入口,不允许调用脚本主流程。
9.4 Shell 命令
bash ./deploy.sh \
--config ./config.txt \
--action upload-package \
--trace-file ./logs/api_trace_xxx.log
带 IP:
bash ./deploy.sh \
--config ./config.txt \
--action upgrade-ip \
--ip 192.168.1.10 \
--trace-file ./logs/api_trace_xxx.log
发布版本:
bash ./deploy.sh \
--config ./config.txt \
--action publish-version \
--hash-code 43858bcf \
--trace-file ./logs/api_trace_xxx.log
回滚:
bash ./deploy.sh \
--config ./config.txt \
--action rollback-ip \
--ip 192.168.1.10 \
--stop-first \
--trace-file ./logs/api_trace_xxx.log
9.5 PowerShell 命令
powershell -File .\deploy.ps1 -ConfigPath .\config.txt -Action upload-package
带 IP:
powershell -File .\deploy.ps1 -ConfigPath .\config.txt -Action upgrade-ip -Ip 192.168.1.10
发布版本:
powershell -File .\deploy.ps1 -ConfigPath .\config.txt -Action publish-version -HashCode 43858bcf
回滚:
powershell -File .\deploy.ps1 -ConfigPath .\config.txt -Action rollback-ip -Ip 192.168.1.10 -RollbackStopFirst
9.6 当前能力差异
Shell 侧当前支持 --trace-file,可以由 LangGraph 在一轮部署中传入同一个 trace 文件。
PowerShell 侧当前 deploy.ps1 action 参数未暴露 -TraceFile。第一阶段处理策略:
- LangGraph 统一保存每个 PowerShell action 的 stdout/stderr 到工作流 trace。
- 业务 checkpoint 中仍记录同一个
trace_file_path。 - 如果必须做到 PowerShell 脚本内部 HTTP trace 也复用同一个文件,需要后续单独评估是否修改
deploy.ps1,不纳入第一阶段。
9.7 FakeRunner
Fake runner 用于图路由、LLM 结构化输出、checkpoint 和报告生成测试。
职责:
- 根据 action 返回 fixture。
- 模拟全局失败、单 IP 失败、回滚确认和日志下载失败。
- 不访问真实 PAM 环境。
10. Action 输出解析
OutputParser 负责把脚本 stdout 和 MCP tool result 都归一化为 ActionResult。
脚本后端优先解析 key=value 行。
输入示例:
ACTION=upload-package
HASH_CODE=43858bcf
TRACE_FILE=./logs/api_trace_xxx.log
解析结果:
{
"ACTION": "upload-package",
"HASH_CODE": "43858bcf",
"TRACE_FILE": "./logs/api_trace_xxx.log"
}
解析规则:
- 只将形如
KEY=VALUE的行作为结构化结果。 [INFO]、[WARN]、[FLOW]作为日志,不参与主结果判断。- 同名 key 多次出现时:
IP保留为列表。- 其他字段默认以后出现的值覆盖先出现的值。
- 非零退出码视为 action 失败。
- stderr、非结构化 stdout 和原始输出必须保存在
ActionResult.raw_output。 - 出现
PENDING_AGENT_CONFIRMATION(...)时,必须转入人工确认分支。
MCP 后端解析规则:
- MCP tool 如果返回 JSON object,直接映射到
values。 - MCP tool 如果返回文本,先尝试按 JSON 解析,再尝试按
key=value解析。 - MCP 原始返回必须保存在
raw_output。 - MCP tool error 统一转换为
ok=false和error_summary。 - 结果字段名归一化为脚本 action 同款字段,例如
hashCode归一为HASH_CODE,nodeUrl归一为NODE_URL。
10.1 ActionResult
class ActionResult(TypedDict):
action: str
backend: Literal["mcp", "script", "fake"]
tool_name: str
exit_code: int
ok: bool
values: dict[str, str | list[str]]
stdout: str
stderr: str
raw_output: str
error_summary: str
11. Checkpoint 设计
需要两层 checkpoint:
- LangGraph checkpointer:保存图执行位置和完整 State,用于
interrupt恢复和工作流续跑。 - 业务 checkpoint JSON:兼容现有 Skill 文档,方便人工排查,也方便脱离 LangGraph 查看部署状态。
11.1 业务 checkpoint 文件
路径:
./logs/deploy_checkpoint_<airportCode>_<applicationName>_<moduleName>_<versionNumber>.json
内容:
{
"runId": "20260529_103000_abcd",
"mode": "MCP",
"executionStrategy": "hybrid_node_mcp",
"actionBackends": {
"get-token": "script",
"create-version": "script",
"upload-package": "script",
"publish-version": "script",
"get-node-url": "script",
"get-online-ips": "mcp",
"create-download-task": "mcp",
"poll-download-progress": "mcp",
"upgrade-ip": "mcp",
"poll-upgrade-progress": "mcp",
"start-ip": "mcp",
"verify-ip": "mcp",
"download-log": "mcp",
"rollback-ip": "mcp"
},
"skillVersion": "pam-auto-deply",
"scriptEntry": "deploy.ps1",
"nodeMcpServerName": "pam-node",
"checkpointPath": "./logs/deploy_checkpoint_HET_PAM_Node_2.0.5.json",
"resumeFromCheckpoint": true,
"params": {
"HOME_BASE_URL": "https://pam.home.example.com",
"AIRPORT_CODE": "HET",
"APP_NAME": "PAM",
"MODULE_NAME": "Node",
"VERSION_NUMBER": "2.0.5",
"ZIP_FILE_PATH": "C:\\path\\to\\pam-2.0.5.zip",
"ACTION_TYPE": "FULL",
"LOG_NAME": "app.log"
},
"artifacts": {
"configPath": "./runtime/config_20260529_103000_abcd.txt",
"traceFilePath": "./logs/api_trace_HET_PAM_Node_2.0.5_20260529_103000_abcd.log",
"hashCode": "43858bcf",
"nodeUrl": "https://pam-node.example.com"
},
"onlineIps": [
"192.168.1.10",
"192.168.1.11"
],
"targetIps": [
"192.168.1.10"
],
"completedGlobalSteps": [
"get-token",
"create-version",
"upload-package",
"publish-version"
],
"ipStates": {
"192.168.1.10": {
"status": "FAILED",
"completedSteps": [
"upgrade-ip",
"poll-upgrade-progress",
"start-ip"
],
"failedStage": "verify-ip",
"failureReason": "Health check failed",
"rollbackStatus": "PENDING_AGENT_CONFIRMATION",
"rollbackStopFirst": true,
"logFile": "./logs/deploy_192.168.1.10.zip"
}
},
"lastSuccessStep": "start-ip",
"lastFailedStep": "verify-ip",
"pendingConfirmation": "rollback-ip:192.168.1.10",
"updatedAt": "2026-05-29 10:30:00"
}
敏感字段不写入业务 checkpoint:
CLIENT_SECRET- token
- Authorization header
11.2 断点续跑策略
- 启动时如果指定
resume_from_checkpoint=true,先读取业务 checkpoint。 - 校验当前核心参数与 checkpoint 参数是否一致。
- 核心参数不一致时,不直接续跑,必须要求用户确认重新开始或使用旧参数。
- 已完成的全局步骤默认跳过。
create-download-task已成功但poll-download-progress未完成时,从poll-download-progress继续。- 单 IP 已成功的默认跳过。
- 单 IP 失败且处于回滚确认状态时,恢复后先进入回滚确认,不继续后续动作。
12. 人工确认设计
使用 LangGraph interrupt 表示需要外部输入的确认点。
12.1 参数确认
触发点:
- 真实部署前。
- 查询 Node/IP 前。
- 手动回滚前。
确认内容:
- 模式
- 脚本入口
- HOME_BASE_URL
- AIRPORT_CODE
- APP_NAME
- MODULE_NAME
- VERSION_NUMBER
- ZIP_FILE_PATH
- ACTION_TYPE
- TIMEOUT
- LOG_NAME
- 指定 IP
- CLIENT_ID 是否已提供
- CLIENT_SECRET 是否已提供
12.2 IP 范围确认
触发点:
- 用户指定 IP 和在线 IP 取交集后,部署范围发生变化。
- 过滤结果为空。
- 用户启用
all_or_nothing=true且部分 IP 不在线。
12.3 回滚确认
触发点:
upgrade-ip失败。poll-upgrade-progress失败。start-ip失败。verify-ip失败。- action 输出
PENDING_AGENT_CONFIRMATION(...)。
确认内容:
- 目标 IP
- 失败阶段
- 失败原因
- 建议是否回滚
stopFirst建议值
默认建议:
- 升级失败:建议回滚,
stopFirst=false - 启动失败:建议回滚,
stopFirst=true - 校验失败:建议回滚,
stopFirst=true
13. 进度事件设计
工作流运行中输出结构化事件,供 CLI、日志、SSE 或 WebSocket 使用。
class DeployEvent(TypedDict):
run_id: str
level: Literal["INFO", "WARN", "ERROR"]
type: Literal[
"FLOW_START",
"FLOW_DONE",
"FLOW_FAIL",
"ACTION_START",
"ACTION_DONE",
"ACTION_FAIL",
"WAIT",
"IP_START",
"IP_DONE",
"IP_FAIL",
"CONFIRMATION_REQUIRED",
"REPORT"
]
stage: str
ip: str | None
message: str
next_stage: str | None
wait_sec: int | None
data: dict
created_at: str
事件示例:
{
"type": "ACTION_DONE",
"stage": "upload-package",
"message": "软件包上传完成",
"data": {
"HASH_CODE": "43858bcf"
}
}
等待事件示例:
{
"type": "WAIT",
"stage": "create-download-task",
"message": "等待 2 秒后开始首次下载进度轮询",
"next_stage": "poll-download-progress",
"wait_sec": 2
}
14. 分支流程
14.1 混合智能执行
适用场景:
- 用户明确要求“用 MCP”“直接在线执行”“不要生成脚本”。
- 用户只说“帮我部署”,且当前环境存在可用 PAM_NODE MCP 工具。
流程:
load_skill_policy
-> llm_understand_request
-> llm_extract_params
-> validate_and_normalize_params
-> llm_generate_plan
-> confirm_params
-> select_execution_strategy(hybrid_node_mcp)
-> build_action_routes
-> prepare_tool_runtimes
-> deploy_flow
行为:
- PAM_HOME action 通过
ScriptActionRunner调用deploy.sh/deploy.ps1action。 - PAM_NODE action 通过
MCPActionRunner调用 PAM_NODE MCP 工具。 - 需要写配置文件供 HOME 脚本 action 使用,但敏感字段不进入命令行和普通日志。
- 仍然按 Skill 固定 action 顺序执行。
- 仍然写业务 checkpoint 和 trace。
- 仍然要求参数确认、IP 范围确认和回滚确认。
14.2 脚本离线执行
适用场景:
- 用户明确要求“用脚本”“离线执行”。
- PAM_NODE MCP 不可用且用户确认切换全脚本后端。
流程:
load_skill_policy
-> llm_understand_request
-> llm_extract_params
-> validate_and_normalize_params
-> llm_generate_plan
-> confirm_params
-> select_execution_strategy(script_only)
-> build_action_routes
-> prepare_tool_runtimes
-> deploy_flow
行为:
- 只调用
deploy.sh/deploy.ps1action 入口。 - 不调用脚本主流程。
CLIENT_SECRET只写入配置文件,不进入命令行。
14.3 只说明脚本用法
适用场景:
- 用户要求“给我脚本用法”。
- 用户要求“生成脚本”,但 Skill 禁止生成或修改脚本。
- 用户明确“不直接动环境”。
行为:
- 说明现有
deploy.sh/deploy.ps1action 用法。 - 不写
config.txt。 - 不调用 MCP。
- 不调用真实脚本 action。
14.4 预演部署计划
适用场景:
- 用户只想确认参数和计划,不执行真实部署。
行为:
- LLM 抽取和归一化参数。
- LLM 生成用户可读部署计划。
- 输出确认单。
- 输出预计 action 顺序。
- 输出执行策略:混合执行或全脚本执行。
- 明确 HOME action 和 NODE action 的执行后端。
- 如存在 checkpoint,说明可从哪个步骤恢复。
- 不调用真实 action。
14.5 只查询 Node 和在线 IP
流程:
confirm_params
-> select_execution_strategy
-> build_action_routes
-> prepare_tool_runtimes
-> get_token
-> get_node_url
-> get_online_ips
-> report_node_ips
禁止执行:
create-versionupload-packagepublish-versioncreate-download-taskupgrade-ip
14.6 手动回滚
流程:
rollback_entry
-> llm_extract_rollback_target
-> confirm_rollback_target
-> select_execution_strategy
-> build_action_routes
-> prepare_tool_runtimes
-> rollback_ip
-> verify_ip optional
-> download_log
-> update_checkpoint
-> final_report
回滚必须由用户明确确认,不能根据失败状态自动执行。
15. 错误处理策略
15.1 全局失败
以下阶段失败时终止整轮部署:
get-tokencreate-versionupload-packagepublish-versionget-node-urlget-online-ipscreate-download-taskpoll-download-progress
处理:
- 记录
last_failed_step。 - 写 checkpoint。
- 输出失败报告。
- 保留原始 action 输出。
15.2 单 IP 失败
以下阶段失败时只标记当前 IP 失败:
upgrade-ippoll-upgrade-progressstart-ipverify-ip
处理:
- 记录失败阶段和原因。
- 尽力执行
download-log。 - 写 checkpoint。
- 转入回滚确认。
- 未确认回滚前,不执行
rollback-ip。
15.3 日志下载失败
download-log 失败不覆盖原始失败原因。
处理:
- 记录日志下载失败。
- 保留主失败阶段。
- 报告中明确日志缺失或下载失败。
16. 安全设计
CLIENT_SECRET不进入命令行。CLIENT_SECRET不进入普通日志、进度事件、最终报告。- token 不进入最终报告。
- action 原始输出保存前需要做敏感字段脱敏。
config.txt或运行时配置文件权限应尽量限制为当前用户可读写。- 回滚必须显式确认。
- 若用户要求“不落地配置文件”,真实部署流程直接终止并说明原因。
- 对脚本路径使用白名单,只允许当前工作目录下既有脚本。
- MCP 工具调用使用白名单,只允许 Skill 中定义的 PAM_NODE 工具。
- LLM 输出必须经过结构化校验和 Skill guardrails。
- LLM 不能生成可执行 shell/PowerShell 命令作为真实执行依据。
- PAM_HOME action 不允许被路由到 MCP。
17. CLI 设计
第一阶段建议先落地 Agent CLI,便于本地验证 Skill、LLM、MCP 和脚本后端。
17.1 部署
python -m pam_deploy_graph.cli deploy \
--strategy hybrid-node-mcp \
--home-base-url https://pam.home.example.com \
--client-id xxx \
--client-secret "***" \
--airport-code HET \
--app-name PAM \
--module-name Node \
--version-number 2.0.5 \
--zip-file-path C:\path\to\pam-2.0.5.zip \
--target-ip 192.168.1.10 \
--target-ip 192.168.1.11
脚本后端:
python -m pam_deploy_graph.cli deploy \
--strategy script-only \
--config ./deploy_params.json
17.2 预演
python -m pam_deploy_graph.cli preview --config ./deploy_params.json
17.3 对话式 Agent
python -m pam_deploy_graph.cli chat
对话式 Agent 行为:
- 使用 LLM 理解用户自然语言。
- 使用 Skill 规则控制工具调用。
- 在真实部署前输出确认单并等待用户确认。
- 支持继续追问缺失参数。
17.4 断点续跑
python -m pam_deploy_graph.cli resume \
--checkpoint ./logs/deploy_checkpoint_HET_PAM_Node_2.0.5.json
17.5 回滚确认恢复
python -m pam_deploy_graph.cli resume \
--thread-id <thread_id> \
--approve-rollback \
--ip 192.168.1.10 \
--stop-first
18. 服务化设计
后续可将 Agent CLI 包装为 FastAPI 服务。
接口建议:
POST /agent/chat
POST /deploy/preview
POST /deploy/start
POST /deploy/{run_id}/confirm
POST /deploy/{run_id}/rollback/confirm
POST /deploy/{run_id}/resume
GET /deploy/{run_id}
GET /deploy/{run_id}/events
GET /deploy/{run_id}/report
事件输出:
- CLI:直接打印结构化进度。
- API:通过 SSE 或 WebSocket 输出
DeployEvent。
19. 测试策略
19.1 单元测试
覆盖:
SkillPolicy从 Skill 文档提取规则。- LLM structured output schema 校验。
- LLM 输出违反 Skill guardrails 时会被拒绝。
OutputParser解析key=value。- 多个
IP=行解析为列表。 PENDING_AGENT_CONFIRMATION(...)检测。- 敏感字段脱敏。
- MCP tool input 构造。
- 脚本 action 命令构造。
- checkpoint JSON 写入和读取。
19.2 图路由测试
覆盖:
show_usage不调用 action。preview不调用 action。- 参数未确认不调用 action。
- PAM_NODE MCP 可用且用户未指定策略时使用
hybrid_node_mcp。 - PAM_NODE MCP 不可用时需要用户确认才切
script_only。 - HOME action 始终路由到脚本。
- NODE action 在混合策略下路由到 MCP。
- IP 范围变化进入确认。
- 单 IP 失败进入回滚确认。
- 用户拒绝回滚后继续或结束。
19.3 LLM 节点测试
覆盖:
- 自然语言中抽取机场、应用、模块、版本和包路径。
- 缺少
CLIENT_SECRET时生成追问。 - 用户说“不要动环境”时进入预演或用法说明。
- 用户说“用 MCP”时 strategy preference 为
hybrid_node_mcp,并提示 HOME 仍走脚本 action。 - 用户说“离线脚本执行”时 mode preference 为 API脚本。
- LLM 计划中出现非法 action 时被 guardrails 拒绝。
19.4 MCP runner 测试
覆盖:
- PAM_NODE 标准 action 到 MCP tool 的映射。
- PAM_NODE MCP 工具缺失时停止。
- PAM_HOME action 不会进入 MCP runner。
- MCP 返回结构化结果转为
ActionResult。 - MCP 原始错误进入
raw_output。 - 回滚未确认时不调用
pam_rollback_ip。
19.5 Runner 假实现测试
使用 fake runner 模拟脚本输出:
- 全部成功。
- 全局失败。
- 上传返回
HASH_CODE。 - Node 返回
NODE_URL。 - 在线 IP 返回多个
IP=。 - 单 IP 校验失败。
- 日志下载失败。
19.6 集成测试
MCP 或脚本真实后端接入后,只做可控环境下的 smoke:
get-tokenget-node-urlget-online-ips
完整部署集成测试需要人工指定测试环境和测试包,不默认纳入自动 CI。
20. 实施计划
阶段一:Agent MVP
交付:
DeployStateSkillPolicy加载器- LLM structured output schema
llm_understand_requestllm_extract_paramsllm_generate_plan- Skill guardrails
- 主图和单 IP 顺序流程
- fake runner
- output parser
- 参数确认 interrupt
- 业务 checkpoint JSON
- 最终报告
验收:
- 对话式输入能抽取参数并生成部署计划。
- 能跑通
preview。 - 能跑通
query_node_ips。 - fake runner 能跑通完整部署成功链路。
- fake runner 能验证单 IP 失败和回滚确认。
- LLM 不能绕过参数确认调用 fake runner。
阶段二:混合工具路由接入
交付:
ActionRouter。- PAM_HOME action 到
ScriptActionRunner的固定路由。 - PAM_NODE MCP server/tool discovery。
MCPActionRunner。- PAM_NODE 标准 action 到 MCP tool 的映射。
- MCP 工具结果统一转
ActionResult。 - 混合执行
query_node_ipssmoke:get-token/get-node-url走脚本,get-online-ips走 MCP。
验收:
- 用户指定 MCP 时进入
hybrid_node_mcp,HOME 阶段仍走脚本。 - 用户未指定策略且 PAM_NODE MCP 可用时默认混合执行。
- PAM_NODE MCP 不可用时不会静默切全脚本。
- 回滚未确认时不会调用 MCP 回滚工具。
阶段三:全脚本后端完善
交付:
- Shell runner 接入全部
deploy.sh --action。 - PowerShell runner 接入全部
deploy.ps1 -Action。 - 真实 stdout/stderr 收集。
- action 超时控制。
- 统一工作流 trace 文件。
验收:
- 在 Windows 上可调用
deploy.ps1action。 - 在 Git Bash/Linux 上可调用
deploy.shaction。 - 不调用脚本主流程。
阶段四:断点续跑完善
交付:
- 从业务 checkpoint 恢复。
- 参数一致性校验。
- 已完成全局步骤跳过。
- 已成功 IP 跳过。
- pending rollback 恢复后继续等待确认。
验收:
- 模拟中断后可从指定阶段恢复。
- 参数变化时会要求用户确认。
阶段五:服务化和可视化
交付:
- Chat Agent API。
- FastAPI 包装。
- SSE/WebSocket 进度事件。
- 运行记录查询。
- 最终报告接口。
验收:
- 前端或调用方可实时看到进度。
- 可通过接口完成确认和恢复。
阶段六:Python 原生 API client 迁移
交付:
- 将脚本内部 HTTP 能力逐步迁移为 Python client。
- 保留脚本作为兼容入口。
验收:
- Python client 与脚本 action 行为一致。
- 关键接口都有单元测试和契约测试。
21. 风险与待决事项
- PowerShell 脚本当前未暴露
-TraceFile,接口级 trace 复用存在能力差异。 - HOME action 只能通过脚本 action 执行,脚本内部会重复获取 token。第一阶段接受该开销,后续若 PAM_HOME 支持 MCP 或 Python client 后再优化。
config.txt落地包含敏感字段,需要明确文件权限和清理策略。- 单 IP 是否允许并发需要谨慎评估,第一版不并发。
- 真实回滚策略需要业务方确认“失败后是否继续处理后续 IP”的默认行为。
- PAM_NODE MCP 工具名称、参数 schema 和返回 schema 需要与 MCP server 对齐。
- LLM 结构化输出需要稳定模型和严格 schema 校验,否则只能作为建议,不能驱动真实工具。
- Skill 文档如果继续演进,需要建立 SkillPolicy 的解析测试,避免规则变更后 Agent 行为漂移。
- 混合执行会同时依赖脚本环境和 MCP 环境,需要在启动前做两类运行时检查。
22. 推荐第一版取舍
第一版只做三件事:
- 用 LangGraph 实现 Agent 骨架:Skill 加载、LLM 结构化理解、确认点、固定流程和 fake runner。
- 优先接混合工具路由:HOME 脚本 action + NODE MCP,形成符合当前接口能力的智能部署闭环。
- 再完善全脚本策略作为离线和兜底路径,不重写现有脚本。
这样能先体现智能部署:用户用自然语言发起部署,LLM 负责理解和计划,Skill 负责约束,LangGraph 负责状态和确认,ActionRouter 按 HOME/NODE 归属分发到脚本或 MCP。流程稳定后,再决定是否把脚本能力迁移到 Python 原生实现。