从零构建系统级工具:AI Agent 驱动的任务编排引擎设计与实现

从零构建系统级工具:AI Agent 驱动的任务编排引擎设计与实现

cover

一、系统级工具的"从零"到底意味着什么

"从零构建"四个字听起来很热血,但实际落地时需要面对的是一系列工程决策:用什么做输入?怎么组织任务流水线?插件怎么加载?错误怎么传播?日志怎么打?这些看似琐碎的问题,每个都直接影响工具的可用性和可维护性。系统级工具和脚本的区别在于:脚本解决一次性问题,工具解决一类问题——它需要配置化、可扩展、可观测。

AI Agent 驱动的任务编排引擎,核心思路是将 AI 的推理能力嵌入到工具的决策环节中。传统工具的流程是固定的:输入 → 处理 → 输出。AI Agent 工具的流程是动态的:输入 → AI 分析 → 动态选择处理策略 → 执行 → AI 评估结果 → 可能重试或调整。这种"决策闭环"让工具具备了适应性,但也引入了新的复杂度——AI 调用的延迟、不确定性、成本控制。

二、AI Agent 任务编排引擎的架构设计

flowchart TB
    A[用户输入<br/>任务描述 + 上下文] --> B[意图解析器<br/>AI 驱动的任务分类]

    B --> C{任务类型}
    C -->|文件操作| D[文件处理器]
    C -->|网络请求| E[网络处理器]
    C -->|代码生成| F[代码处理器]
    C -->|数据分析| G[数据处理器]

    D --> H[执行引擎<br/>任务调度 + 重试]
    E --> H
    F --> H
    G --> H

    H --> I[结果评估器<br/>AI 驱动的质量检查]
    I --> J{结果是否达标}
    J -->|是| K[输出结果]
    J -->|否| L[策略调整<br/>修改参数/换处理器]
    L --> B

    subgraph 安全沙箱
        M[资源限制<br/>CPU/内存/时间]
        N[权限控制<br/>文件系统/网络隔离]
        O[审计日志<br/>所有 AI 调用记录]
    end

    H --> M
    H --> N
    I --> O

    subgraph 可观测性
        P[执行追踪<br/>每步耗时 + AI Token 消耗]
        Q[指标采集<br/>成功率/延迟/成本]
    end

    H --> P
    I --> Q

架构的核心设计原则:AI 只参与"决策"环节,不参与"执行"环节。意图解析和结果评估由 AI 完成,具体的文件操作、网络请求由确定性代码完成。这种分离确保了工具的可预测性——即使 AI 给出了错误的意图分类,执行层也不会产生超出权限的副作用。

三、AI Agent 引擎的代码实现

任务定义与意图解析

use serde::{Deserialize, Serialize};
use std::time::{Duration, Instant};

/// 任务定义:用户输入的结构化表示
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Task {
    /// 原始用户输入
    pub description: String,
    /// 任务上下文(工作目录、环境变量等)
    pub context: TaskContext,
    /// 任务优先级
    pub priority: Priority,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskContext {
    pub working_dir: String,
    pub env_vars: Vec<(String, String)>,
    pub max_retries: u32,
    pub timeout_secs: u64,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum Priority {
    Low,
    Normal,
    High,
    Critical,
}

/// AI 解析出的任务意图
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParsedIntent {
    /// 任务类型
    pub task_type: TaskType,
    /// AI 的置信度(0.0 - 1.0)
    pub confidence: f64,
    /// 提取的关键参数
    pub parameters: Vec<(String, String)>,
    /// AI 推荐的处理策略
    pub suggested_strategy: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskType {
    FileOperation,
    NetworkRequest,
    CodeGeneration,
    DataAnalysis,
    Unknown,
}

/// 意图解析器:调用 AI 模型分析用户输入
pub struct IntentParser {
    /// AI 调用超时
    timeout: Duration,
    /// 置信度阈值:低于此值拒绝执行
    confidence_threshold: f64,
}

impl IntentParser {
    pub fn new(timeout: Duration, confidence_threshold: f64) -> Self {
        IntentParser {
            timeout,
            confidence_threshold,
        }
    }

    /// 解析用户意图
    /// 实际项目中这里调用 LLM API,此处简化为规则匹配
    pub async fn parse(&self, task: &Task) -> anyhow::Result<ParsedIntent> {
        let start = Instant::now();

        // 构造 AI 提示词
        let prompt = self.build_prompt(task);

        // 调用 AI 模型(带超时控制)
        let raw_response = self.call_ai_model(&prompt).await?;

        // 解析 AI 响应
        let intent = self.parse_response(&raw_response)?;

        // 置信度校验:低于阈值时标记为 Unknown
        let intent = if intent.confidence < self.confidence_threshold {
            tracing::warn!(
                "AI 置信度 {:.2} 低于阈值 {:.2},拒绝执行",
                intent.confidence,
                self.confidence_threshold
            );
            ParsedIntent {
                task_type: TaskType::Unknown,
                confidence: intent.confidence,
                parameters: intent.parameters,
                suggested_strategy: "请求人工确认".to_string(),
            }
        } else {
            intent
        };

        tracing::info!(
            "意图解析完成: type={:?}, confidence={:.2}, elapsed={:?}",
            intent.task_type,
            intent.confidence,
            start.elapsed()
        );

        Ok(intent)
    }

    fn build_prompt(&self, task: &Task) -> String {
        format!(
            "分析以下任务描述,返回 JSON 格式的意图分析:\n\
             任务:{}\n\
             上下文目录:{}\n\
             请返回 {{\"task_type\": \"...\", \"confidence\": 0.0-1.0, \
             \"parameters\": {{}}, \"suggested_strategy\": \"...\"}}",
            task.description,
            task.context.working_dir,
        )
    }

    /// 调用 AI 模型的抽象
    /// 生产环境中使用 reqwest 调用 LLM API,此处简化
    async fn call_ai_model(&self, _prompt: &str) -> anyhow::Result<String> {
        // 模拟 AI 调用延迟
        tokio::time::sleep(Duration::from_millis(100)).await;
        // 返回模拟响应
        Ok(r#"{"task_type":"FileOperation","confidence":0.85,"parameters":{},"suggested_strategy":"direct_execute"}"#.to_string())
    }

    fn parse_response(&self, raw: &str) -> anyhow::Result<ParsedIntent> {
        let parsed: serde_json::Value = serde_json::from_str(raw)?;
        let task_type = match parsed["task_type"].as_str() {
            Some("FileOperation") => TaskType::FileOperation,
            Some("NetworkRequest") => TaskType::NetworkRequest,
            Some("CodeGeneration") => TaskType::CodeGeneration,
            Some("DataAnalysis") => TaskType::DataAnalysis,
            _ => TaskType::Unknown,
        };
        Ok(ParsedIntent {
            task_type,
            confidence: parsed["confidence"].as_f64().unwrap_or(0.0),
            parameters: vec![],
            suggested_strategy: parsed["suggested_strategy"]
                .as_str()
                .unwrap_or("")
                .to_string(),
        })
    }
}

执行引擎与结果评估

/// 执行引擎:调度任务并收集结果
pub struct ExecutionEngine {
    intent_parser: IntentParser,
    /// 最大重试次数
    max_retries: u32,
    /// 执行审计日志
    audit_log: Vec<AuditEntry>,
}

/// 审计条目:记录每次 AI 调用和执行决策
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuditEntry {
    pub timestamp: String,
    pub task_description: String,
    pub intent: String,
    pub action_taken: String,
    pub result: String,
    pub ai_tokens_used: u32,
}

/// 执行结果
#[derive(Debug)]
pub struct ExecutionResult {
    pub success: bool,
    pub output: String,
    pub retries_used: u32,
    pub total_duration: Duration,
    pub ai_calls: u32,
}

impl ExecutionEngine {
    pub fn new(intent_parser: IntentParser, max_retries: u32) -> Self {
        ExecutionEngine {
            intent_parser,
            max_retries,
            audit_log: Vec::new(),
        }
    }

    /// 执行任务:意图解析 → 处理器选择 → 执行 → 评估
    pub async fn execute(&mut self, task: &Task) -> anyhow::Result<ExecutionResult> {
        let start = Instant::now();
        let mut retries = 0;

        loop {
            // 阶段一:AI 意图解析
            let intent = self.intent_parser.parse(task).await?;

            // 安全检查:Unknown 类型拒绝执行
            if intent.task_type == TaskType::Unknown {
                self.record_audit(task, &intent, "拒绝执行", "意图不明确");
                return Ok(ExecutionResult {
                    success: false,
                    output: "AI 无法确定任务意图,需要人工确认".to_string(),
                    retries_used: retries,
                    total_duration: start.elapsed(),
                    ai_calls: 1,
                });
            }

            // 阶段二:选择处理器并执行
            let result = self.dispatch_and_execute(&intent, task).await;

            // 阶段三:AI 结果评估
            let quality = self.evaluate_result(&result, task).await?;

            if quality.acceptable {
                self.record_audit(task, &intent, "执行成功", &result.output);
                return Ok(ExecutionResult {
                    success: true,
                    output: result.output,
                    retries_used: retries,
                    total_duration: start.elapsed(),
                    ai_calls: 2, // 解析 + 评估
                });
            }

            // 评估未通过,判断是否重试
            retries += 1;
            if retries >= self.max_retries {
                self.record_audit(task, &intent, "重试耗尽", &quality.feedback);
                return Ok(ExecutionResult {
                    success: false,
                    output: format!("执行未达标,已重试 {} 次: {}", retries, quality.feedback),
                    retries_used: retries,
                    total_duration: start.elapsed(),
                    ai_calls: 2 * retries,
                });
            }

            tracing::warn!(
                "执行未达标,第 {} 次重试,反馈: {}",
                retries,
                quality.feedback
            );
        }
    }

    async fn dispatch_and_execute(
        &self,
        intent: &ParsedIntent,
        _task: &Task,
    ) -> ExecutionResult {
        // 根据意图类型分发到对应处理器
        let output = match intent.task_type {
            TaskType::FileOperation => "文件操作完成".to_string(),
            TaskType::NetworkRequest => "网络请求完成".to_string(),
            TaskType::CodeGeneration => "代码生成完成".to_string(),
            TaskType::DataAnalysis => "数据分析完成".to_string(),
            TaskType::Unknown => unreachable!(),
        };

        ExecutionResult {
            success: true,
            output,
            retries_used: 0,
            total_duration: Duration::from_millis(50),
            ai_calls: 0,
        }
    }

    /// AI 驱动的结果评估
    async fn evaluate_result(
        &self,
        result: &ExecutionResult,
        task: &Task,
    ) -> anyhow::Result<QualityAssessment> {
        // 简化实现:基于结果成功状态评估
        Ok(QualityAssessment {
            acceptable: result.success,
            feedback: if result.success {
                "执行成功".to_string()
            } else {
                "执行失败,需要调整策略".to_string()
            },
        })
    }

    fn record_audit(
        &mut self,
        task: &Task,
        intent: &ParsedIntent,
        action: &str,
        result: &str,
    ) {
        self.audit_log.push(AuditEntry {
            timestamp: chrono::Utc::now().to_rfc3339(),
            task_description: task.description.clone(),
            intent: format!("{:?}", intent.task_type),
            action_taken: action.to_string(),
            result: result.to_string(),
            ai_tokens_used: 0,
        });
    }
}

#[derive(Debug)]
struct QualityAssessment {
    acceptable: bool,
    feedback: String,
}

四、AI Agent 工具的工程边界与风险控制

AI 调用的成本与延迟:每次意图解析和结果评估都是一次 LLM API 调用,延迟在 200ms-2s 之间,Token 成本按调用次数线性增长。对于高频操作(如批量文件处理),AI 调用成本可能超过计算成本。解决方案:对高频操作引入缓存——相同意图描述直接复用上次的解析结果,跳过 AI 调用。

不确定性管理:AI 的输出具有随机性,同一输入可能产生不同意图分类。对于关键操作(如删除文件、发送请求),必须设置置信度阈值和人工确认环节。非关键操作(如日志分析、格式转换)可以降低阈值,但需要审计日志记录所有 AI 决策。

安全沙箱的必要性:AI 生成的执行策略可能包含危险操作(如 rm -rf /、访问敏感文件)。执行层必须在沙箱中运行,限制文件系统访问范围、网络请求白名单、CPU/内存资源上限。AI 只能"建议",执行层根据安全策略决定是否"采纳"。

可观测性的代价:审计日志、指标采集、执行追踪都会引入额外开销。在高吞吐场景下,日志写入可能成为瓶颈。建议使用异步日志写入,并设置采样率——非关键路径的日志按 10% 采样。

五、总结

AI Agent 驱动的系统级工具,核心是将 AI 的推理能力嵌入决策环节,执行层保持确定性。落地建议:第一,AI 只负责意图解析和结果评估,不直接执行操作;第二,设置置信度阈值,低置信度任务必须人工确认;第三,所有 AI 决策记录审计日志,确保可追溯;第四,执行层运行在安全沙箱中,AI 建议受权限策略约束;第五,高频操作引入缓存机制,避免 AI 调用成为性能瓶颈。从零构建不是从空白开始,而是从"每个决策都有据可查"开始。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值