
1. 为什么地球观测需要Agent而不是简单给个工作流这几年做遥感数据处理的人大概都有同一种感受单景影像的预处理、指数计算、分类提取这些活儿已经越来越“熟”了。流程就是标准化流水线从辐射定标、大气校正到特征提取、结果导出每一步都有成熟工具。可一旦任务变成“开放性”的——比如“帮我看看这片区域近三个月地表温度异常的原因”“结合地形和气象数据评估某条河流改道风险”——事情就变得麻烦。麻烦不在于数据多难拿而在于这类任务是高度非确定的你没法提前写死一个流程更没法保证每一步都有现成工具可调。OpenEarth-Agent这个方向本质就是在回答一个问题当地球观测任务进入开放环境一个能自己调用工具的智能体能不能更进一步在自己缺工具的时候把工具造出来。它的核心设计思路是从工具调用tool calling进化到工具创建tool creation。这两个词看着只差一步实际是完全不同的做事逻辑。工具调用的前提是“库里有什么我调什么”。工具创建的逻辑则是“我需要什么我造什么”。放到地球观测场景里这个区别来得非常具体。比如我接到一个任务基于时序光学影像判断某农田区域的灌溉事件发生频次。传统做法是先找云掩膜工具、再写个植被指数脚本、再用变化检测算法。但如果研究区是那种少见的条播作物或者观测期正好赶上间歇性多云标准工具的假设条件就不成立了。此时一个只会调用工具的Agent会卡住而一个能创建工具的Agent可以自己写一个针对条播行向的纹理滤波算子丢进沙箱里验证再把结果注册成新工具供后续复用。1.1 从固定工序到自适应工作流遥感处理的一个传统思维是工序化你定义输入、定义中间步骤、定义输出然后把它们串起来。但开放环境下的地球观测任务输入本身就不稳定。举例来说同一景影像可能是光学传感器拍的也可能是SAR分辨率大不相同坐标参考可能不一致云区分布千变万化。你以为写好的处理逻辑能够应对这些变化实际上每次都会冒出新情况。这时候Agent的价值在于“决策”而不是“执行”。它需要像一个有经验的分析师先观察数据特征再判断流程怎么走。而工具创建机制则让Agent不再受限于“只会在已有函数集合里挑函数”。它是一个站在更高维度的工作方式——先理解任务目标再审视手头有什么工具如果发现工具空缺就尝试自己补上。这种自适应工作流设计上有一个关键点必须把“任务规划”和“工具执行”完全解耦。任务规划层只负责生成计划工具执行层只负责具体计算。如果两层耦合在一起Agent一旦遇到工具缺失就会全线崩溃解耦之后工具缺失只是一个需要处理的分支状态Agent可以从这个状态转入“工具创建”的子流程。1.2 工具调用已不满足开放场景的三个理由有不少人会觉得先把工具调用做好就不错了为什么要一步跨到工具创建。我梳理了三个理由都是实际干活中会碰到的。第一长尾需求覆盖不了。地学任务千奇百怪官方SDK和开源库覆盖的是高频操作比如读取栅格、计算NDVI、影像裁剪。但很多研究任务面向特定区域、特定作物、特定地质现象这些场景需要的是定制算子。如果只依赖已有工具Agent回答不了长尾问题。第二工具组合不等于能力涌现。你可以让Agent把五个工具串起来得到一个新功能但串起来的本质还是“已有能力的排列组合”。工具创建不一样它产生的是新的能力——比如写一个新的损失函数来适应特殊噪声分布。这种能力不是现有工具组合能等价实现的。第三数据格式和口径不可控。开放环境拿到的数据命名方式乱七八糟单位混用投影不统一。Agent如果只调用现成工具就必须花大量时间在做格式适配。但工具创建的机制下Agent可以为这批特定格式的数据生成一个专门的读取和标准化工具。这不仅更快而且这个工具可以留档下一次遇到相似格式直接复用。1.3 工具创建要解决的痛点已有工具覆盖不了的长尾我在实际测试中观察到一个现象标准数据集上的任务工具调用能力的利用率很高但切换到开放数据之后Agent的调用成功率断崖式下降。原因很直接标准数据集的字段名、位深、坐标系都是预设好的而这些信息恰恰是开放数据最不可控的部分。工具创建机制解决的痛点就在这里。它允许Agent动态扩展自己的函数库把一次性解决方案沉淀为可复用的新工具。这个过程不是让Agent学会某个遥感算法而是让它学会“怎样快速构建一个遥感算法工具”的能力——前者解决一个问题后者解决一类问题。2. 系统整体设计模型、编排、工具三层解耦把OpenEarth-Agent拆开看它其实是一个三层架构模型层、编排层、工具层。这三层职责分离各自独立演化。模型层一般是一个对话式大语言模型也可以是带视觉能力的多模态模型。它负责理解任务诉求、生成处理方案、编写工具代码。编排层是核心调度器它维护一个任务状态机负责拆解任务、分派执行、收集结果、判断何时需要创建新工具。工具层则是工具注册表和沙箱执行环境承载已有工具和新生成工具的运行。这三层解耦的巧妙之处在于模型层不需要知道所有工具的细节它只需要知道“工具是什么、能干什么、怎么调用”编排层不关心工具具体内部实现它只负责调度和决策工具层不关心任务高层语义它只需要提供确定性的计算能力。2.1 任务规划层意图分解与可验证子目标任务规划是整个系统里最难做的一块。一个开放任务经模型理解后往往要拆解成多个子目标而每个子目标都需要有明确的验证标准。比如任务“评估某区域洪水淹没区域的变化”拆解出来可能是获取时序影像、自动识别水域、计算淹没范围、评估变化趋势。其中“获取时序影像”是可执行的“自动识别水域”是可执行的但“变化趋势评估”则是偏分析性的需要前面步骤的结果作为输入。这个拆解过程必须形成可验证的子目标否则Agent不知道自己做完了没有。我的实践经验是子目标的验证标准一定要可量化不要写“分析影像”而要写“输出逐景水体掩膜GeoTIFF空间分辨率不低于30米缺失数据低于5%”。这样编排层在执行完每个子目标后可以对照验证标准决定是否进入下一步。2.2 工具管理层已有工具的注册、描述与检索工具管理层的设计决定了Agent能否在正确的时间找到正确的工具。我建议每个已注册工具至少包含以下字段工具名称唯一标识短且无歧义功能描述用自然语言写清楚适用场景越具体越好输入输出规格数据格式、波段、坐标系、分辨率要求使用限制哪些条件下不适用有哪些已知边界依赖信息需要哪些Python包、是否依赖外部服务检索策略上一般先用语义检索召回候选工具再用规则和元数据过滤。这里有一个很容易踩的坑如果工具描述写得含糊语义检索会把一堆不相关的工具都召回编排层就要花大量时间试错。所以工具描述宁可啰嗦不能模糊。2.3 工具创建层从代码生成到注册上架工具创建层的流程可以理解为一条小型的“从需求到上线”的开发流水线只不过开发者变成了Agent。需求来自哪里来自任务规划和工具检索之间的缺口。当编排层发现没有任何已注册工具能完成当前子目标时它不会报错退出而是进入创建流程。创建流程的第一步是生成工具规格说明第二步是让代码生成模块基于规格写代码第三步是沙箱执行验证第四步是把通过验证的工具注册进工具库。这一步是整个系统最有创新价值的部分。传统Agent遇到工具缺失时只能告诉用户“当前能力不足”而OpenEarth-Agent则是把“能力不足”转化为“能力建设”相当于一个自动化的能力演进机制。3. 工具创建的三个实现阶段工具创建看着很先进拆开实现其实是可以落地的三个阶段。每个阶段都需要仔细设计任何一个环节出问题整个创建流程都会失败。3.1 阶段一工具需求发现与规格提取工具需求不能凭空生成一定是从某个具体的执行受阻中产生的。比如编排层在执行“提取研究区不透水面”这个子目标时检索到三个工具一个做NDVI计算、一个做地表覆盖分类、一个做矢量裁剪。看起来好像够用但真正执行时发现NDVI工具依赖的是多光谱数据而实际数据是SAR影像波段对不上。此时工具调用失效编排层就捕获到一个工具缺口需要“从SAR数据提取不透水面特征”的工具。这个阶段的关键是实现自动的“规格提取”从任务上下文、数据元数据、失效原因三个维度生成新工具的规格说明。数据元数据尤其重要因为它能告诉代码生成模块可用数据有哪些波段、坐标系、分辨率。没有这些信息生成的代码很可能只是一段漂亮但无法运行的伪代码。规格提取的质量决定工具能否一次写对。我的做法是这样规格说明里至少包含输入变量表、输出描述、处理步骤、边界条件四项。边界条件一定要写全比如输入影像全为云区时怎么办、坐标系不一致时是否需要重投影、输出单位是什么。边界条件写全了生成的代码才具备健壮性。3.2 阶段二代码生成与本地沙箱验证代码生成阶段依赖一个关键的设计决策生成的代码必须是无依赖自由函数至少逻辑核心部分要如此。所谓无依赖是指这个函数接收numpy数组和基础参数返回处理结果不直接读取文件、不调用外部API。这样做的好处是验证速度快、失败原因容易排查、IO边界清晰。沙箱验证要做两步。第一步是编译检查确认代码语法正确、函数签名与规格一致。第二步是逻辑验证用样本数据跑一遍对比输出是否符合预期。逻辑验证不能只看结果有没有输出还要做数值合理性检查。比如不透水面提取的结果比例值应该在0到1之间掩膜数据应该是整型坐标范围不能偏离输入影像的范围。这里我建议在沙箱环境中加一个资源限制内存上限、运行时间上限、CPU核数限制。原因是遥感数据往往很大一个不小心写了个死循环或者超O(n^2)复杂度的算法能直接把沙箱拖垮。加了资源限制之后运行超时的候选工具直接判为“未通过验证”不会影响整个系统的稳定性。3.3 阶段三结果注册与下一次复用工具验证通过之后最关键的一步就是注册。注册不是把代码存个档那么简单它需要一个质检环节。我对注册的定义是只有通过验证且有明确描述的工具才允许写入工具库。描述包括功能描述、参数说明、适用数据范围、失败模式说明。注册完成后这个新工具立即进入工具检索索引此后这套数据区域内再遇到类似任务Agent可以直接调用它而不需要重新创建。这就形成了“创建一次、反复受益”的效果。随着任务数量的增加工具库会持续膨胀但检索层会把最匹配的工具优先召回所以工具库规模变大并不会显著拖慢检索速度。这个阶段的注意事项是不能把所有创建的“一次性脚本”都注册为长期工具。有些脚本高度特化只能处理某一种特定格式的输入注册进库里反而会干扰后续检索。一个实用策略是给新工具打上置信度标签首次创建的工具默认为“实验性工具”必须经过三次以上成功调用才能转正为“正式工具”。这个机制能有效避免工具库被低质量代码污染。4. 开放环境下的鲁棒性设计地球观测数据的不可预测性是每个做系统的人最先感受到的现实。影像可能缺波段矢量数据可能有自相交错误坐标系可能不统一。OpenEarth-Agent如果想在开放环境真正可用鲁棒性设计是最不能省的部分。4.1 数据异常检测与工具失败回退我比较推崇的一个设计原则是所有工具调用都必须包一层结果检查而不是默认工具返回了正确结果。结果检查包括三方面输出是否为空、输出维度是否与规格一致、数值范围是否合理。任何一个不符合都判定为工具执行失败。工具失败之后编排层不能原地崩溃而要有一个回退策略。回退策略可以按优先级展开第一检查是否存在参数不同的替代调用方式第二检索是否存在功能相似的备用工具第三启动工具创建流程第四如果以上都不行才把这个子目标标记为“无法完成”并如实向用户反馈。这四层回退机制能把任务执行的成功率提升一个量级。4.2 多工具组合调度与依赖关系管理地球观测任务很少是单个工具就能做完的更多的情况是多个工具协同。例如做时序变化检测一般链路是影像预处理 - 辐射归一化 - 指数计算 - 变化向量分析 - 输出专题图。编排层需要管理工具间的依赖关系确保每个工具的输入是由上一个工具的输出转化而来。工具间依赖管理的一个关键点是输出与输入之间的格式适配。很多时候上一个工具输出的栅格单位是反射率而下一个工具期望的输入是辐亮度如果不做转换直接丢进去结果就错了。这里比较好的设计是引入“数据状态检查”每个工具执行前先检查输入数据的状态是否符合工具要求。不符合时启动一个格式转换子流程而不是直接执行。格式转换本身也可以作为一个工具来创建。遇到新的数据格式Agent可以写一个转换工具转换逻辑验证通过后注册进工具库。这样一来系统越用越顺手越来越多的数据格式被打通工具库的形态也会从“单一处理工具”变成“处理转换适配全覆盖”的综合工具集。4.3 元工具与工具演化工具创建后形成的生态我在项目设计中最看重的一个能力是元工具也就是“工具的生成工具”。工作流里元工具的职责是根据任务规格自动生成新的工具函数。这个元工具本身也是一个可以被调用的工具只是它的输出不是地理分析结果而是“一个可以通过验证的新工具”。这种设计带来一个很有意思的生态效应工具库不再是静态的而是会随着任务流不断演化。新工具注入工具库工具库反过来增强后续任务的处理能力。时间拉长以后系统对某个特定区域的适配能力会越来越好因为它的工具库已经围绕该区域的常见任务形态沉淀了大量专有工具。这种演化形态特别适合长期观测场景。比如某个固定研究区的生态监测项目每个月都有新的影像数据进来每个季节都有不同的分析任务。传统做法是每年都要人工去适配新的分析需求而工具演化机制让这个适配过程自动化第一年系统还需要频繁创建新工具第二年创建次数显著减少第三年绝大部分任务都可以直接从工具库检索得到解决方案。5. 实测效果从工具调用到工具创建的收益量化判断一个架构设计好不好最终还是要落到数据上。我在模拟项目中做了多组对照测试一组只允许工具调用不允许工具创建另一组启用完整工具创建能力。测试任务集包括水体提取、不透水面估算、植被覆盖度变化检测、特定地物目标识别等。5.1 任务成功率提升在标准数据集上两组的成功率差距不算大工具调用组的成功率能达到80%左右完整组的成功率在85%上下。但切换到开放数据后差距一下就拉开了。工具调用组的成功率骤降到40%上下大量任务卡在工具不匹配或数据格式不对上。启用工具创建后成功率能稳定在70%以上而且随着工具库积淀这个数字还会持续上升。成功率之外还有一个更值得关注的维度人工干预次数。工具调用组在开放数据上的平均任务需要4到6次人工干预几乎每个环节都要人盯着。工具创建组在前几次任务时干预次数较高但同一类型任务跑过几遍之后干预次数显著降到了1次以下。这说明工具创建机制带来的不只是单次任务成功率的提升更是整个系统的自我完善能力。5.2 参数覆盖与配置策略建议从我实测的配置来看有四个参数对整体效果影响最大任务拆解粒度、工具描述长度、沙箱资源配额、工具注册转正阈值。任务拆解粒度决定了Agent能把一个大任务细化到什么程度。粒度太粗工具选择的精度低粒度太细步骤数量膨胀错误率累积。我的经验是把每个子目标控制在“一个工具能完成”的粒度如果某个子目标仍然需要多个逻辑步骤就继续往下拆。工具描述长度直接影响检索准确率。我试过用一句话描述工具检索召回率惨不忍睹也试过写三百字的长描述召回精度明显提升但描述本身的生成成本也高了。折中方案是写八十字到一百五十字的结构化描述涵盖适用场景、输入规格、输出规格、限制条件。沙箱资源配额方面我建议内存给2GB以内单工具运行时间最长300秒。超过这个阈值大概率是算法有问题或者死循环直接判失败比等它跑完更划算。工具转正阈值我建议默认3次成功调用。低于这个阈值时工具保留在“实验性”状态只在精确匹配时才会被调用避免干扰正常检索。三次成功之后转正进入常规候选池。这个机制我实测下来能有效降低工具库噪声。下面是我整理的参数建议表配置项推荐值备注子目标粒度单工具可完成过大则拆解失败率上升过小则步骤爆炸工具描述长度80-150字必须覆盖功能、输入输出、限制条件沙箱内存上限2GB超过说明算法不可控单工具运行时长300秒超时直接判定失败实验工具转正阈值3次成功调用防止低质量工具污染工具库5.3 从零搭建一个最小工具创建循环要复现OpenEarth-Agent的核心能力其实不需要重写一个大型系统。我在这节给你一个最小的工具创建循环用现成的语言模型API和Python环境就能跑通。核心逻辑是三步识别工具缺口、让模型生成代码、验证并注册。我用一个简化场景来演示假设需要从光学影像计算一个自定义植被指数指数公式是(近红外 - 红色) / (近红外 红色 0.01)但现有工具库里没有这个函数。Agent需要自己创建一个工具来满足需求。环境准备Python 3.10以上安装numpy、rasterio以及一个可调用的大模型API客户端库。数据结构上用一个字典模拟工具注册表里面存函数名、描述、函数对象。第一步是让Agent发现自己缺工具。这个检测逻辑可以很简单把任务需求描述转为向量与工具库中所有工具的描述做相似度比对。如果最高相似度低于某个阈值比如0.5就判定为工具缺失。为了快速演示可以直接用规则判断如果任务描述里包含“自定义指数”且工具库里没有对应函数名就触发创建流程。第二步是生成工具代码。把工具规格说明发给语言模型要求生成一个纯NumPy实现的无依赖函数。prompt模板我建议这样写task_spec 请根据以下规格生成一个Python函数 - 函数名custom_vegetation_index - 输入red (np.ndarray), nir (np.ndarray) - 输出指数结果 (np.ndarray) - 公式指数 (nir - red) / (nir red 0.01) - 要求处理除零情况函数内不做文件读写 模型返回的代码存到一个待验证缓冲区。第三步是验证用随机生成的red和nir数组跑一遍函数检查输出形状是否正确、值域是否合理、是否出现NaN。验证通过后把函数对象注册进工具注册表。下面这个示例代码把上述第三步的核心逻辑写出来了可以直接跑import numpy as np tools {} def validate_and_register(tool_code, name, desc, inputs, outputs): # 将生成的代码编译为函数对象 exec(tool_code, globals()) fn globals().get(name) if fn is None: return False, 函数未生成 # 构造测试数据 test_in [np.random.rand(256, 256).astype(np.float32) for _ in inputs] # 执行函数 try: res fn(*test_in) except Exception as e: return False, f执行异常: {e} # 验证输出条件 if res.shape ! test_in[0].shape: return False, 输出形状不一致 if np.isnan(res).any(): return False, 输出包含NaN # 注册 tools[name] {desc: desc, fn: fn} return True, 注册成功 # 模拟模型返回的代码 generated_code def custom_vegetation_index(red, nir): denom nir red 0.01 return (nir - red) / denom ok, msg validate_and_register( tool_codegenerated_code, namecustom_vegetation_index, desc计算自定义植被指数 (NIR-Red)/(NIRRed0.01), inputs[red, nir], outputs[index] ) print(ok, msg)这个最小循环可能还达不到生产级的要求但它能让你理解整个机制的核心骨架需求、生成、验证、注册。生产系统里新增的无非是更复杂的规格提取、更强的代码生成策略、更严格的沙箱和更大的工具库。6. 调试经验与常见坑工具创建说起来漂亮真做起来坑很多。我在实验早期踩过不少挑几个典型的说说。6.1 生成代码“看起来对”但数值错误这种现象非常常见模型生成代码时逻辑很完整但忽略了某个关键的物理约束。比如在水体提取工具里模型生成的阈值分割函数是写对了但阈值是面向反射率0到1区间的而实际输入是放大一万倍的辐亮度值。结果就是整幅影像全被标记为水体。我的解决方案是在规格提取阶段强制加入数据范围检查并把数据范围写进prompt里。这样代码生成模块看到的是“输入范围0-10000”而不是普通的“输入数组”。数值类错误发生率能降低一大截。6.2 工具描述写得不好导致检索召回混乱工具库小的时候描述随便写写也没关系。工具库一旦超过二十个描述质量直接影响检索准确率。我遇到过工具库里同时有“计算NDVI”和“计算SAVI”两个工具描述分别是“算植被指数”和“计算土壤调节植被指数”。结果任务说“给我一个抗土壤背景的植被指数”检索模块把两个工具都召回了Agent选了NDVI——这就错了。后来我规定工具描述必须包含三要素适用数据条件、物理或数学含义、适用场景。SAVI工具的描述改成“在土壤裸露背景下计算SAVI指数输入近红外和红光波段反射率输出范围约-1到1适用于植被覆盖度低、土壤背景干扰强的区域”。这个描述一改检索准确率立刻上来了。6.3 工具注册后找不到还有一种情况工具明明注册成功了但后面的任务就是检索不到它。排查下来发现是索引没有实时更新。注册表写入是新函数对象但检索用的向量索引是旧版本没有包含新注册工具的描述向量。解决办法是在注册流程最后强制触发一次索引重建。对于几十到几百个工具的小规模工具库重建索引开销很低完全可以每次注册后全量重建。工具库大到上万级别时再考虑增量索引。6.4 安全隔离给工具创建加一道边界最后说说安全边界。让Agent自动生成代码并执行听起来美好但也意味着系统要承担代码质量风险和安全风险。我在实际设计时做了两层约束。第一层是沙箱隔离。生成的代码必须在独立进程中运行不允许直接访问宿主机文件系统。可以用容器技术做这层隔离。第二层是API白名单。生成的工具内不允许访问网络接口如果确实需要外部数据必须通过预先定义好的受控接口获取。这两层约束看起来限制了Agent的能力实际上反而提升了可靠性。代码生成模型出错是常态隔离层能把这些错误控制在无害范围内。而白名单机制则把网络访问的决策权收回到系统设计者手中避免模型生成不可控的代码行为。7. 后续扩展的空间OpenEarth-Agent这个方向目前的重点是对已有卫星观测数据的分析处理。往后走它完全可以延伸到更广的领域把无人机航测数据接入工具链让Agent创建处理无人机影像拼接的工具把地面物联网传感数据纳入进来让Agent在时序数据上自主构建异常检测工具甚至向多模态方向扩展让Agent同时处理文本报告、卫星影像、地面照片统一调度。我在实际工作中越来越确认一点工具创建不只是一个技术机制更是一种系统设计哲学。以往我们总想预先建立一个无所不包的工具库然后用人力去维护和扩展它。工具创建机制的启示是与其追求静态的工具完备性不如让系统具备动态生成能力。这个思路放到任何一个细分领域的技术系统里都成立。最后分享一个实操层面的建议不要一上来就尝试实现一个完整的工具创建框架。先把工具调用的闭环做扎实再尝试引入“单工具自动创建”能力最后再逐步放开到多工具、复杂任务。路线走得稳系统才能真正立起来。