agent_deply/doc_scripts/PAM_LangGraph_重构设计文档.md
2026-05-29 14:08:50 +08:00

50 KiB
Raw Permalink Blame History

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. 设计目标

  1. 将 LangGraph 实现为 PAM 智能部署 Agent而不是单纯脚本编排器。
  2. 支持 Skill + MCPSkill 提供规则、约束和流程策略PAM_NODE MCP 提供节点侧在线工具能力。
  3. 保留现有 deploy.sh / deploy.ps1 action 能力,作为 PAM_HOME 固定执行后端,并作为全脚本离线模式后端。
  4. 引入大模型参与意图理解、参数抽取、缺参追问、执行计划生成、失败解释和报告摘要。
  5. 对高风险动作使用确定性图节点和人工确认兜底,禁止大模型绕过确认直接部署或回滚。
  6. 支持 checkpoint 持久化和断点续跑。
  7. 支持部署过程进度流式输出,避免长时间静默执行。
  8. 将 PAM_NODE MCP 和 PAM_HOME 脚本 action 输出解析、错误分类、最终报告生成标准化。
  9. 为后续服务化、可视化和 Python 原生 API client 迁移预留接口。

3. 非目标

第一阶段不做以下事情:

  • 不自动生成、覆盖或修改 deploy.shdeploy.ps1deploy.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 动作固定走脚本 actionPAM_NODE 动作优先走 MCP必要时可按用户确认降级到脚本 action。

4.1 Agent 分层

PAM LangGraph Agent 分为四层:

  1. Skill Policy Layer

    • 读取并解析 PAM_AUTO_DEPLY_SKILL.md
    • 形成系统提示词、工具白名单、确认点、禁止事项和流程约束。
    • 对 LLM 输出做规则校验。
  2. LLM Reasoning Layer

    • 从自然语言中识别部署意图。
    • 抽取业务参数和控制参数。
    • 判断是否缺参或存在歧义。
    • 生成用户可读的部署计划、风险提示、失败解释和最终摘要。
  3. Deterministic Orchestration Layer

    • 用 LangGraph StateGraph 固化主流程。
    • 执行人工确认、条件路由、checkpoint、重试和断点续跑。
    • 决定何时允许调用工具。
  4. 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 不可用、用户明确要求脚本模式、或需要离线执行时,整轮部署可切换为全脚本执行,但必须在真实部署前向用户确认。

执行策略选择规则:

  1. 默认策略:hybrid_node_mcp,即 HOME 走脚本 actionNODE 走 MCP。
  2. 用户明确指定 MCP使用 hybrid_node_mcp;如果 NODE MCP 不可用则停止并说明,不自动改为全脚本。
  3. 用户明确指定脚本或离线:使用 script_only,所有 action 都走 deploy.sh / deploy.ps1
  4. 用户只说“帮我部署”:默认 hybrid_node_mcp;如果 NODE MCP 不可用,询问是否切换 script_only
  5. 用户只要用法或预演:不调用 MCP也不调用脚本。
  6. 高风险动作无论 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_HOME action 固定 backend=script
  • PAM_NODE action 在 hybrid_node_mcp 策略下 backend=mcp
  • PAM_NODE action 在 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 = 120
  • LOG_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 = 2
  • first_poll_delay_sec = 2
  • per_ip_step_interval_sec = 1
  • per_ip_interval_sec = 3
  • failure_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_requestllm_extract_paramsllm_generate_plan 是智能层节点。
  • validate_llm_intentvalidate_and_normalize_paramsapply_skill_guardrails 是确定性安全节点。
  • select_execution_strategy 根据用户意图、Skill 规则和 PAM_NODE MCP 可用性选择 hybrid_node_mcpscript_onlyfake
  • 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-version
  • upload-package
  • publish-version
  • create-download-task
  • upgrade-ip
  • rollback-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_IDCLIENT_SECRET 等敏感字段是否已提供。

约束:

  • 不把 CLIENT_SECRET 明文写入普通消息。
  • 不猜测必填参数。

8.5 validate_and_normalize_params

职责:

  • 将 LLM 抽取结果映射为 DeployParamsControlParams
  • 补齐默认值。
  • 校验必填参数。
  • 对机场码、版本号、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还是手动回滚。
  • 判断用户是否明确要求 MCPAPI脚本
  • 如果用户要求生成或修改脚本,直接进入受限说明分支。

输出:

  • intent
  • mode
  • show_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

选择规则:

  1. 用户明确指定 MCP选择 hybrid_node_mcpPAM_NODE MCP 不可用则停止。
  2. 用户明确指定脚本或离线:选择 script_only
  3. 用户未指定且 PAM_NODE MCP 可用:选择 hybrid_node_mcp
  4. 用户未指定且 PAM_NODE MCP 不可用:询问是否切换 script_only
  5. 测试环境可显式选择 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 节点只做四件事:

  1. 播报即将执行的阶段。
  2. 通过 ActionRouter 按 action 归属调用 MCP 或脚本 action。
  3. 解析 key=value 输出并更新 State。
  4. 更新 checkpoint 和进度事件。

全局 action 节点:

  • get_token
  • create_version
  • upload_package
  • publish_version
  • get_node_url
  • get_online_ips
  • create_download_task
  • poll_download_progress

单 IP action 节点:

  • upgrade_ip
  • poll_upgrade_progress
  • start_ip
  • verify_ip
  • download_log
  • rollback_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_urlairportCodeapplicationNamemoduleNameversionNumber、目标 IP 等运行时状态。
  • 调用工具并统一转为 ActionResult
  • 保存工具原始返回。
  • 对敏感字段做脱敏。

MCP runner 约束:

  • 只能调用 Skill 白名单中的 PAM_NODE 工具。
  • 不能调用 PAM_HOME action。
  • rollback-ip 必须在回滚确认后调用。
  • 工具返回结果不得由 LLM 改写后写入 State。
  • PAM_NODE MCP 不可用时,不能静默切换脚本后端,除非用户确认 script_only

9.3 ScriptActionRunner

ScriptActionRunner 有两类职责:

  1. hybrid_node_mcp 策略下,固定执行 PAM_HOME action
    • get-token
    • create-version
    • upload-package
    • publish-version
    • get-node-url
  2. 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"
}

解析规则:

  1. 只将形如 KEY=VALUE 的行作为结构化结果。
  2. [INFO][WARN][FLOW] 作为日志,不参与主结果判断。
  3. 同名 key 多次出现时:
    • IP 保留为列表。
    • 其他字段默认以后出现的值覆盖先出现的值。
  4. 非零退出码视为 action 失败。
  5. stderr、非结构化 stdout 和原始输出必须保存在 ActionResult.raw_output
  6. 出现 PENDING_AGENT_CONFIRMATION(...) 时,必须转入人工确认分支。

MCP 后端解析规则:

  1. MCP tool 如果返回 JSON object直接映射到 values
  2. MCP tool 如果返回文本,先尝试按 JSON 解析,再尝试按 key=value 解析。
  3. MCP 原始返回必须保存在 raw_output
  4. MCP tool error 统一转换为 ok=falseerror_summary
  5. 结果字段名归一化为脚本 action 同款字段,例如 hashCode 归一为 HASH_CODEnodeUrl 归一为 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

  1. LangGraph checkpointer保存图执行位置和完整 State用于 interrupt 恢复和工作流续跑。
  2. 业务 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 断点续跑策略

  1. 启动时如果指定 resume_from_checkpoint=true,先读取业务 checkpoint。
  2. 校验当前核心参数与 checkpoint 参数是否一致。
  3. 核心参数不一致时,不直接续跑,必须要求用户确认重新开始或使用旧参数。
  4. 已完成的全局步骤默认跳过。
  5. create-download-task 已成功但 poll-download-progress 未完成时,从 poll-download-progress 继续。
  6. 单 IP 已成功的默认跳过。
  7. 单 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.ps1 action。
  • 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.ps1 action 入口。
  • 不调用脚本主流程。
  • CLIENT_SECRET 只写入配置文件,不进入命令行。

14.3 只说明脚本用法

适用场景:

  • 用户要求“给我脚本用法”。
  • 用户要求“生成脚本”,但 Skill 禁止生成或修改脚本。
  • 用户明确“不直接动环境”。

行为:

  • 说明现有 deploy.sh / deploy.ps1 action 用法。
  • 不写 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-version
  • upload-package
  • publish-version
  • create-download-task
  • upgrade-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-token
  • create-version
  • upload-package
  • publish-version
  • get-node-url
  • get-online-ips
  • create-download-task
  • poll-download-progress

处理:

  • 记录 last_failed_step
  • 写 checkpoint。
  • 输出失败报告。
  • 保留原始 action 输出。

15.2 单 IP 失败

以下阶段失败时只标记当前 IP 失败:

  • upgrade-ip
  • poll-upgrade-progress
  • start-ip
  • verify-ip

处理:

  • 记录失败阶段和原因。
  • 尽力执行 download-log
  • 写 checkpoint。
  • 转入回滚确认。
  • 未确认回滚前,不执行 rollback-ip

15.3 日志下载失败

download-log 失败不覆盖原始失败原因。

处理:

  • 记录日志下载失败。
  • 保留主失败阶段。
  • 报告中明确日志缺失或下载失败。

16. 安全设计

  1. CLIENT_SECRET 不进入命令行。
  2. CLIENT_SECRET 不进入普通日志、进度事件、最终报告。
  3. token 不进入最终报告。
  4. action 原始输出保存前需要做敏感字段脱敏。
  5. config.txt 或运行时配置文件权限应尽量限制为当前用户可读写。
  6. 回滚必须显式确认。
  7. 若用户要求“不落地配置文件”,真实部署流程直接终止并说明原因。
  8. 对脚本路径使用白名单,只允许当前工作目录下既有脚本。
  9. MCP 工具调用使用白名单,只允许 Skill 中定义的 PAM_NODE 工具。
  10. LLM 输出必须经过结构化校验和 Skill guardrails。
  11. LLM 不能生成可执行 shell/PowerShell 命令作为真实执行依据。
  12. 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-token
  • get-node-url
  • get-online-ips

完整部署集成测试需要人工指定测试环境和测试包,不默认纳入自动 CI。

20. 实施计划

阶段一Agent MVP

交付:

  • DeployState
  • SkillPolicy 加载器
  • LLM structured output schema
  • llm_understand_request
  • llm_extract_params
  • llm_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_ips smokeget-token/get-node-url 走脚本,get-online-ips 走 MCP。

验收:

  • 用户指定 MCP 时进入 hybrid_node_mcpHOME 阶段仍走脚本。
  • 用户未指定策略且 PAM_NODE MCP 可用时默认混合执行。
  • PAM_NODE MCP 不可用时不会静默切全脚本。
  • 回滚未确认时不会调用 MCP 回滚工具。

阶段三:全脚本后端完善

交付:

  • Shell runner 接入全部 deploy.sh --action
  • PowerShell runner 接入全部 deploy.ps1 -Action
  • 真实 stdout/stderr 收集。
  • action 超时控制。
  • 统一工作流 trace 文件。

验收:

  • 在 Windows 上可调用 deploy.ps1 action。
  • 在 Git Bash/Linux 上可调用 deploy.sh action。
  • 不调用脚本主流程。

阶段四:断点续跑完善

交付:

  • 从业务 checkpoint 恢复。
  • 参数一致性校验。
  • 已完成全局步骤跳过。
  • 已成功 IP 跳过。
  • pending rollback 恢复后继续等待确认。

验收:

  • 模拟中断后可从指定阶段恢复。
  • 参数变化时会要求用户确认。

阶段五:服务化和可视化

交付:

  • Chat Agent API。
  • FastAPI 包装。
  • SSE/WebSocket 进度事件。
  • 运行记录查询。
  • 最终报告接口。

验收:

  • 前端或调用方可实时看到进度。
  • 可通过接口完成确认和恢复。

阶段六Python 原生 API client 迁移

交付:

  • 将脚本内部 HTTP 能力逐步迁移为 Python client。
  • 保留脚本作为兼容入口。

验收:

  • Python client 与脚本 action 行为一致。
  • 关键接口都有单元测试和契约测试。

21. 风险与待决事项

  1. PowerShell 脚本当前未暴露 -TraceFile,接口级 trace 复用存在能力差异。
  2. HOME action 只能通过脚本 action 执行,脚本内部会重复获取 token。第一阶段接受该开销后续若 PAM_HOME 支持 MCP 或 Python client 后再优化。
  3. config.txt 落地包含敏感字段,需要明确文件权限和清理策略。
  4. 单 IP 是否允许并发需要谨慎评估,第一版不并发。
  5. 真实回滚策略需要业务方确认“失败后是否继续处理后续 IP”的默认行为。
  6. PAM_NODE MCP 工具名称、参数 schema 和返回 schema 需要与 MCP server 对齐。
  7. LLM 结构化输出需要稳定模型和严格 schema 校验,否则只能作为建议,不能驱动真实工具。
  8. Skill 文档如果继续演进,需要建立 SkillPolicy 的解析测试,避免规则变更后 Agent 行为漂移。
  9. 混合执行会同时依赖脚本环境和 MCP 环境,需要在启动前做两类运行时检查。

22. 推荐第一版取舍

第一版只做三件事:

  1. 用 LangGraph 实现 Agent 骨架Skill 加载、LLM 结构化理解、确认点、固定流程和 fake runner。
  2. 优先接混合工具路由HOME 脚本 action + NODE MCP形成符合当前接口能力的智能部署闭环。
  3. 再完善全脚本策略作为离线和兜底路径,不重写现有脚本。

这样能先体现智能部署用户用自然语言发起部署LLM 负责理解和计划Skill 负责约束LangGraph 负责状态和确认ActionRouter 按 HOME/NODE 归属分发到脚本或 MCP。流程稳定后再决定是否把脚本能力迁移到 Python 原生实现。