OpenCode智能体+Harness:基于LangGraph的数据分析流程编排实战
1. 先理清定位OpenCode 是手Harness 是脑说实话我第一次听到OpenCode 智能体这个组合的时候心里是有点抵触的。这两年冒出来的 Agent 框架太多了今天一个名词、明天一个概念真正能落到业务里的没几个。但等我花了两周时间把 OpenCode 和 Harness 接起来跑完一整套数据分析任务之后我承认这个组合确实值得单独写一篇教程——它不是那种换个壳子的玩具而是把终端里的编码智能体和带状态编排的 Agent 架构真正打通了。先说结论OpenCode 解决的是谁来写代码、谁来执行、谁来和文件系统交互这一层它就是一个跑在终端里的 AI 编码助手你可以把它理解成 Claude Code 或 Codex 的开源平替方案支持接入多家模型供应商。而 Harness 解决的是智能体怎么思考、怎么调用工具、怎么在多个步骤之间维持状态这一层它基于 LangChain 和 LangGraph 构建负责把一次数据分析拆成加载数据→清洗→探索→建模→可视化这样的步骤图每一步让哪个模型、调哪个工具、结果存到哪都由 Harness 编排。简单打个比方Harness 是大脑和神经系统负责规划和反射OpenCode 是双手负责实际敲代码、跑命令、读写文件。数据分析这个场景恰好是这种分工的最佳试验场——因为它天然是流程化的先取数、再清洗、再分析、再出图每一步之间有依赖关系前一步的输出是后一步的输入。这种带依赖的流程正是 LangGraph 的图结构最擅长处理的。这套教程适合谁如果你已经在用 Claude Code、Codex 这类终端智能体想做更复杂的多步骤任务编排或者你在企业里想让智能体自动完成本地业务数据的查询和报表生成又或者你只是想把 LangChain/LangGraph 从能跑 Demo推进到能跑真实任务——那这篇内容基本就是照着你的需求写的。我下面会按架构理解→环境安装→核心流程→实操复现→避坑调优的顺序展开全程用真实可复现的代码和数据示例说话。2. Harness 架构三件套LangGraph 状态图、LangChain 工具层、Skill 方法论要理解 Harness先别急着看它有什么花哨功能抓住三根柱子就够LangGraph 的状态图、LangChain 的工具抽象、Skill 技能机制。这三者分别对应智能体的怎么走、用什么走、走得好不好。2.1 LangGraph把流程变成图LangGraph 的核心思想是把智能体的执行过程建模成一张有向图。传统的方式是写一个 for 循环让模型反复调用工具直到完成任务这在简单场景下没问题但一旦任务里有如果数据量太大就先采样、如果字段有缺失就先补全这类条件分支纯循环就变成了一坨难以维护的 if-else。LangGraph 的解法是引入三个概念节点Node、边Edge、状态State。节点是一个 Python 函数输入是当前状态输出是更新后的状态边决定执行完一个节点后下一步去哪个节点状态是一个 TypedDict存着整个流程共享的变量——比如原始 DataFrame、清洗后的 DataFrame、图表文件路径列表。我在 Harness 里最常用的模式是条件边。比如在数据探索节点之后加一个判断如果数据行数超过 10 万就走采样节点否则直接走建模节点。这个判断在传统代码里要写在循环体内部在 LangGraph 里就是一个独立的函数专门检查状态里的行数指标。这种解耦让每一步都能单独调试、单独替换真实项目里维护起来舒服得多。2.2 LangChain把工具变成函数Harness 里工具的底座是 LangChain 的tool装饰器。任何 Python 函数只要加上这个装饰器写清楚参数类型和 docstring模型就能学会调用它。这里有个很重要的经验工具的 docstring 质量直接决定智能体的成功率。我自己踩过这个坑。最开始给数据分析智能体定义了两个工具load_csv(path)和load_excel(path)docstring 只写了一句话加载数据文件。结果模型在遇到 .xlsx 文件时经常用错工具偶尔还会在load_csv里传入 Excel 路径。后来我把 docstring 改成tool def load_csv(path: str) - str: Load a CSV file into a pandas DataFrame and return its schema. Use this ONLY for comma-separated .csv files. For Excel files, use load_excel. Returns: column names, dtypes, row count, and first 3 rows as a string. 改完之后工具选择准确率肉眼可见地提升。模型不傻但它的信息完全来自你的工具描述——你描述得不清楚它就只能靠猜。2.3 Skill把方法论沉淀成可复用资产这是 Harness 比较有辨识度的一块。Skill 的定位是某类任务的标准作业流程。你可以把数据分析的完整方法论写成一个 Skill让智能体每次接到分析任务时先加载它再按里面的步骤执行。我参考了很多社区的 Skill 写法总结下来一个 Skill 文件通常包含三块描述description说明这个 Skill 适用于什么场景比如适用于结构化业务数据的探索性分析与可视化报告生成。步骤steps按顺序列出要执行的阶段每个阶段说明目标、输入、输出、需要调用的工具。约束constraints写明哪些事不能做比如不得删除原始数据文件不得在样本数据上拟合后直接下业务结论。为什么要特意提 Skill因为它是把一个资深数据分析师的工作习惯迁移给智能体的最直接方式。你不需要每次都在 Prompt 里重复先看缺失值、再看分布、再决定清洗策略这些内容沉淀在 Skill 里智能体需要时自己加载。这比 Prompt 工程更结构化也比微调更轻量——换模型供应商不用重新训练换数据集不用改方法论。2.4 一个最小可跑的 Harness 代理骨架理论知识说再多不如一段能跑的代码。下面是我在项目里用的最小骨架基于 LangGraph 构建只有三个节点规划、执行、总结。from typing import TypedDict, Annotated import pandas as pd from langgraph.graph import StateGraph, END from langchain_core.tools import tool from langchain_openai import ChatOpenAI class AgentState(TypedDict): task: str # 原始任务描述 data_path: str # 数据文件路径 dataframe: object # 当前 DataFrame 状态 analysis_result: dict # 分析结果汇总 report_path: str # 可视化报告输出路径 tool def load_csv(path: str) - str: Load a CSV file and return schema info. df pd.read_csv(path) return fcolumns{list(df.columns)}, rows{len(df)}, dtypes{dict(df.dtypes)} tool def summarize(df_info: str) - str: Compute descriptive statistics for the loaded dataset. # 实际实现中这里会从 AgentState 取 dataframe return ok tools [load_csv, summarize] model ChatOpenAI(modelgpt-4o, temperature0).bind_tools(tools) def plan_node(state: AgentState) - AgentState: # 让模型决定要调用哪些工具 return state def execute_node(state: AgentState) - AgentState: # 执行工具调用并更新状态 return state def finish_node(state: AgentState) - AgentState: # 汇总结果生成报告 return state graph StateGraph(AgentState) graph.add_node(plan, plan_node) graph.add_node(execute, execute_node) graph.add_node(finish, finish_node) graph.add_edge(plan, execute) graph.add_edge(execute, finish) graph.add_edge(finish, END) graph.set_entry_point(plan) app graph.compile()注意真实项目里plan_node和execute_node之间通常是循环关系不是直连——模型可能需要多次调用工具才能完成一个阶段。所以正确写法是在execute_node之后加条件边检查是否还需要继续调用工具如果不需要才进入finish_node。我在这里简化了但你要记住这个循环条件退出的模式它是 Agent 架构里最容易写错的地方。3. OpenCode 落地安装、模型接入和免费额度那点事Harness 负责脑子但最终真正落到终端里执行的是 OpenCode。这一节把安装和配置讲透。3.1 安装方式和环境检查OpenCode 的安装很简单官方提供了多种方式。我试过两种最顺的# 方式一npm 全局安装 npm install -g opencode-ai # 方式二一行脚本安装 curl -fsSL https://opencode.ai/install | bash安装完先跑一下版本检查opencode --version如果在终端里能正常输出版本号环境就 OK 了。这里提醒一句OpenCode 对 Node.js 的版本有要求建议 Node 18 以上太低的话某些功能会静默失效——别问我怎么知道的我第一次装完发现会话历史功能不生效查了半天才发现是 Node 版本太旧。3.2 模型供应商配置与免费额度OpenCode 的配置文件默认在~/.config/opencode/opencode.jsonLinux/macOS或对应系统目录下。它的模型接入方式是供应商 模型名双层结构你可以在一个配置里同时配置多家供应商然后在会话中用命令切换。我目前的配置大概是这个样子{ provider: { openai: { models: [gpt-4o, gpt-4o-mini], apiKey: sk-... }, anthropic: { models: [claude-sonnet-4-20250514], apiKey: sk-ant-... }, opencode_go: { models: [opencode-go], freeTier: true } }, model: gpt-4o, theme: dark }这里必须展开说一下上面这个opencode_go。OpenCode 有免费的 Go 套餐free tier这对预算有限的开发者来说非常友好。但免费套餐有一个硬性限制只能从命令行界面CLI内使用不能通过其他客户端或 API 方式调用。如果你绕过 CLI 直接走 API会碰到类似这样的报错error from provider (console): opencodes free tier can only be used from wi...看到这个报错别慌不是你的 API Key 错了是调用入口不对。解决方式只有一种回到 OpenCode 的 CLI 界面里用 /model 命令切回免费模型。我实测下来免费套餐在简单的数据分析任务上完全够用但遇到超长上下文或者复杂的多文件项目还是建议切到 gpt-4o 或 claude 这类付费模型质量和稳定性不在一个量级。3.3 常用命令和cc switch切换技巧OpenCode 的命令行交互做得比较顺手这里列几个我在数据分析场景里高频使用的命令用途实操说明opencode进入交互式会话直接在终端里开启对话/init初始化项目上下文让智能体扫描当前目录结构/model切换模型供应商免费切付费、付费切免费全靠它/skills查看已加载的 Skill确认分析方法论是否生效cc switch切换不同编码智能体在 OpenCode 和其他 CLI Agent 之间横跳特别说下cc switch。这个命令的本意是切换 Claude Code 和 OpenCode我在实践中发现它也能做模型 A 干规划、模型 B 干执行的笨办法——虽然不如 Harness 优雅但临时用一下很顶事。3.4 OpenCode 和 Harness 怎么对接这是全篇最关键的一个问题。两者不冲突是上下游关系。Harness 里有一步叫做执行在纯 LangChain 实践里这一步通常是自己写 Python 代码去调工具但在 OpenCodeHarness 的组合里你可以把 OpenCode 当成一个超级工具包通过命令行调用来执行复杂编码任务。tool def run_opencode(task: str) - str: Use OpenCode CLI to execute a coding task in the terminal. Returns the output of the OpenCode session. import subprocess result subprocess.run( [opencode, run, task], capture_outputTrue, textTrue, timeout600 ) return result.stdout这样做的好处是Harness 负责流程编排和业务逻辑OpenCode 负责写代码、跑脚本、处理文件。数据分析任务里那些写一段 pandas 清洗代码、生成一张 matplotlib 图表的活OpenCode 干得又快又好而下一步该清洗还是该建模这种决策交给 Harness 的状态图更可靠。各干各擅长的这是我目前觉得最合理的组合方式。4. 数据分析智能体的完整搭建流程现在进入正题怎么搭一个真正能干活的数据分析智能体。我以一个非常典型的业务场景为例给定一份销售订单 Excel自动完成数据清洗、探索性分析、趋势洞察、可视化报告生成。这个流程我从零开始搭了三版第三版算比较稳定下面按最终版的结构讲。4.1 场景定义和任务拆解在动手写代码之前先把任务拆清楚。我把销售数据分析拆成了五个阶段数据加载识别文件格式CSV/Excel、读取、记录行数与列名。数据清洗处理缺失值、去重、统一日期格式、纠正明显异常值。探索性分析EDA统计描述、分组聚合、相关性分析、异常检测。业务洞察按产品/地区/时间维度找趋势和异常点生成文字结论。报告生成按固定模板输出图表和结论到 Markdown 报告。这五个阶段不是线性的。清洗完如果发现字段类型不对要回到清洗步骤重新处理EDA 阶段发现某个维度数据太稀疏可能影响洞察结论需要返回去调整聚合粒度。这就是我不用线性管道而用 LangGraph 的原因——它天然支持这种回退和跳转。4.2 把方法论写成 Skill我把上述五个阶段的方法论沉淀成了一个 Skill 文件。这里给一个精简版的 YAML 结构name: sales-data-analysis description: 面向销售订单数据的标准分析流程适用于 CSV/Excel 格式的明细数据。 version: 1.0 steps: - id: load name: 数据加载 tools: [load_csv, load_excel] actions: - 识别文件格式并读取 - 记录列名、数据类型、行数 output: dataframe 基本信息 - id: clean name: 数据清洗 tools: [summarize_missing, deduplicate, normalize_date] actions: - 检查缺失值并决定填充或删除策略 - 去重并记录去重行数 - 标准化日期与金额字段格式 depends_on: [load] - id: eda name: 探索性分析 tools: [describe_data, group_by_dimension, correlation_analysis] actions: - 输出数值字段描述统计 - 按产品、地区、月度三个维度聚合 - 计算关键字段相关性 depends_on: [clean] - id: insight name: 业务洞察 tools: [detect_trend, find_anomaly] actions: - 识别月度销售趋势方向 - 标记超出均值 2 个标准差的异常记录 depends_on: [eda] - id: report name: 报告生成 tools: [create_chart, write_markdown] actions: - 生成至少 3 张核心图表趋势、Top 产品、地区分布 - 将结论写入 Markdown 报告 depends_on: [insight]写好之后把这个 YAML 放到 Harness 的 skills 目录下。每次智能体接到分析任务会先检索这个任务应该用哪个 Skill加载成功后才开始执行。这个机制省掉了大量 Prompt 重复而且换模型后行为依然稳定。4.3 核心节点代码清洗、EDA、报告下面这段代码是我实际在用的清洗节点逻辑不是玩具代码可以直接参考from typing import Any import pandas as pd def clean_node(state: AgentState) - AgentState: df: pd.DataFrame state[dataframe] log: list[str] [] # 1. 缺失值处理数值列中位数填充类别列众数填充 before df.shape for col in df.columns: if df[col].dtype in (float64, int64): df[col] df[col].fillna(df[col].median()) else: df[col] df[col].fillna(df[col].mode().iloc[0] if not df[col].mode().empty else 未知) log.append(f缺失值处理完成{before} - {df.shape}) # 2. 去重基于所有列判断完全重复的行 dup_count df.duplicated().sum() df df.drop_duplicates().reset_index(dropTrue) log.append(f去重行数{dup_count}) # 3. 日期标准化 if order_date in df.columns: df[order_date] pd.to_datetime(df[order_date], errorscoerce) df df.dropna(subset[order_date]) df[year_month] df[order_date].dt.to_period(M) log.append(日期字段已标准化并生成 year_month 聚合键) # 4. 金额字段统一为数值类型 if amount in df.columns: df[amount] df[amount].astype(str).str.replace(¥, ).str.replace(,, ) df[amount] pd.to_numeric(df[amount], errorscoerce) df df.dropna(subset[amount]) log.append(金额字段已清洗) state[dataframe] df state[clean_log] log return state这段代码的每一处处理都有一个为什么说三个重点中位数填充而不是均值填充金额、销量这类字段往往右偏分布均值会被极端值拉高中位数更稳健。先 dropna 再 to_numericerrorscoerce会把解析失败的值转成 NaN如果不 drop 掉后面聚合会出现大段空白。生成 year_month 聚合键这是做时间趋势分析的基础提前在清洗阶段准备好后面 EDA 节点就不用反复转换了。4.4 数据加载与文件识别细节数据加载节点有个容易忽略的坑文件格式不能只看扩展名。有些Excel其实是 CSV 改名的有些CSV实际是制表符分隔。我的加载节点加了双重保险tool def load_data(path: str) - str: Load tabular data from CSV or Excel. Auto-detects separator. if path.endswith(.csv): # 自动嗅探分隔符 import csv with open(path, r, encodingutf-8-sig) as f: sample f.readline() sep csv.Sniffer().sniff(sample).delimiter df pd.read_csv(path, sepsep, encodingutf-8-sig) elif path.endswith((.xlsx, .xls)): df pd.read_excel(path) else: return Unsupported file format return fLoaded {len(df)} rows, columns: {list(df.columns)}这里用utf-8-sig而不是utf-8是因为很多业务导出的 CSV 带 BOM 头用utf-8读会导致第一列列名出现看不见的\ufeff前缀后面所有按列名操作都会静默失败。这种问题在数据量小的时候根本发现不了等模型跑完整个流程出结果时你会发现为什么按列名过滤总是空?——八成就是 BOM 的问题。5. 全流程实操从销售订单 CSV 到可视化分析报告流程代码就位之后最关键的一步是实际跑一遍。这一节我完整记录一次执行过程包括我输入了什么、智能体输出了什么、中间哪里卡过壳。5.1 准备一份真实的测试数据我手工构造了一份 2000 行的销售订单数据包含这些字段order_id, order_date, region, product_category, quantity, unit_price, amount, customer_type。其中我故意埋了几个脏数据点10 行缺失 amount、5 行完全重复、3 行日期格式是2024/1/15而不是标准的2024-01-15、2 行地区字段写的是东区和East混用。这份数据我放在~/projects/sales-agent/data/sales_orders.csv。5.2 启动智能体和任务下发在 OpenCode 里进入项目目录先/init让智能体了解目录结构然后直接下发任务 /init 扫描完成检测到目录结构 - data/sales_orders.csv (销售订单数据) - skills/sales-data-analysis.yaml (分析方法论) - agent.py (Harness 主程序) 请对 data/sales_orders.csv 执行完整的数据分析流程按照 sales-data-analysis 方法论 输出一份 Markdown 报告到 reports/sales_report.md并生成趋势图、Top 产品图、 地区分布图三张图表。这里有一个小技巧任务描述里一定要点名方法论sales-data-analysis和指定输出产物报告路径 图表清单。如果不点名方法论智能体可能自由发挥流程五花八门不指定产物它做完分析可能只回复一段文字连图表都不生成。5.3 执行过程中的关键节点观察整轮执行大概花了 6 分钟中途我一直在观察终端输出。几个值得记录的片段清洗阶段智能体先通过load_data工具确认了数据规模然后调用清洗节点。看日志它发现了 amount 字段里有 3 行带¥符号的值触发了金额字段清洗逻辑把¥1,299.00转成了1299.0。这个细节如果不专门处理后面聚合销售额时会把这个字段当字符串处理groupby 之后全是坑。EDA 阶段它输出了一个让我比较意外的发现单价和销量的相关系数是 -0.21。这说明卖得多的产品单价反而低这个洞察如果没有人点出来光看汇总表是发现不了的。智能体在报告里写道高单价产品的销量偏低建议关注中价位产品的毛利贡献——这个结论已经有点像初级分析师写出来的东西了。报告生成阶段这里出过一次问题。智能体第一次调用create_chart时matplotlib 因为中文字体缺失图表里的销售额月份全部变成了方块。它自己从报错里定位到了是字体问题然后主动执行了以下操作# 查找系统可用的中文字体 fc-list :langzh # 没有合适的就在代码里指定 fallback import matplotlib matplotlib.rcParams[font.sans-serif] [WenQuanYi Zen Hei, Noto Sans CJK SC] matplotlib.rcParams[axes.unicode_minus] False这个智能体自己发现环境问题并自动修复的过程是 OpenCode 这类终端编码智能体最有价值的地方。普通 API 调用模式下模型遇到这种环境错误只会把报错返回给你但在 OpenCode 里它能操作终端、看到报错、改代码、重跑直到图表正常输出。5.4 最终产物长什么样执行完成后reports/sales_report.md里包含数据概览原始行数、清洗后行数、缺失值处理记录。核心图表月度销售额趋势图折线、Top 10 产品销售额柱状、地区销售额分布饼图。业务结论三条洞察全部基于 EDA 数据不包含模型凭空想象的建议。附录数据清洗日志和关键聚合表。整套流程跑完从原始 CSV 到可视化报告中间不需要人工写一行代码。这就是数据分析全流程实操的意义——不是做个 Demo 给人看而是真的把从取数到出报告这条链路打通了。6. 我能跑通但你可能还会踩的坑流程跑通了不代表没有坑。以下问题是我在反复实测中遇到的有的解决了有的只能绕但都值得你知道。6.1 免费模型额度报错的正确应对姿势上一节提到的opencodes free tier can only be used from wi...这个报错我遇到好几次。它出现的场景总结下来就两类你通过其他客户端比如 VS Code 插件、API 脚本调用 OpenCode 的免费模型。你的终端环境变量里设置了某个 API Key导致 OpenCode 误判你走的是 API 模式。解决办法很简单确保你使用的是opencode的原生 CLI 界面如果你开了多个终端窗口确认每个窗口都是通过opencode命令进入的而不是通过代理脚本。我在实践中还发现某些终端复用场景下旧的会话缓存会导致 OpenCode 以为你还在用 API 模式此时/restart一下会话通常能解决。6.2 大文件数据集和上下文窗口的冲突这是数据分析智能体最容易翻车的地方。假设你的销售数据不是 2000 行而是 20 万行模型如果尝试把整个 DataFrame 塞进上下文——哪怕只是打印前 50 行的样本和 schema——也会很快把上下文撑爆。我的做法是强制在工具描述和 Skill 里做限制constraints: - 数据加载工具只返回 schema 和前 3 行样本不返回完整数据 - 超过 5 万行时所有聚合操作先按维度压缩再分析 - 禁止在对话中打印完整 DataFrame配套的load_csv工具也要改返回的字符串只包含列名、类型、行数、前 3 行样例。模型的分析能力来自工具的计算结果不需要亲眼看完整数据。这是 Agent 数据分析设计和人在回路用 pandas 分析最本质的区别——前者靠工具拿结论后者靠眼睛看数据。6.3 模型选型分析类任务到底用哪个模型稳我在不同模型之间做了横向对比结论供参考模型工具调用准确率代码生成质量上下文处理综合推荐gpt-4o高高中数据分析首选claude-sonnet中高高中高长任务更稳opencode-go免费中中低简单任务可用轻量模型如 mini低中低低不推荐用于多步骤流程工具调用准确率是数据分析场景里最重要的指标因为一步调用错了后面全白费。gpt-4o 在bind_tools场景下表现最稳我主力用它当任务特别长、需要十几轮工具调用时Claude 的上下文跟踪能力更出色。免费模型适合跑通流程、验证思路但不适合直接上生产。6.4 误删文件和不可逆操作的防护让智能体拥有终端操作能力是一把双刃剑。它既然能创建报告就也能覆盖文件。我之前遇到过它把原始 CSV 的列顺序改掉了导致第二次执行结果和第一次不一致。解决方案是在 Harness 执行层加一个只读保护所有写操作必须先检查路径前缀只允许写入reports/、output/等指定目录原始数据目录只读。ALLOWED_WRITE_DIRS (reports/, output/) def safe_write(path: str, content: str) - str: if not any(path.startswith(d) for d in ALLOWED_WRITE_DIRS): raise PermissionError(fWrite to {path} is not allowed) with open(path, w, encodingutf-8) as f: f.write(content) return fWritten to {path}这个防护看着简单但在真实项目里能救你命。企业场景下智能体一旦能查本地业务数据库误操作的风险更高——执行了 DELETE 语句可不是闹着玩的。所以我强烈建议给智能体配的数据库账号一律只读或者只能查特定库。这是架构层必须守住的底线。7. 从能用到好用我给这套组合做的三件事流程跑通只是起点真正让这套组合在业务里站住脚我把常见的三样优化做了一遍分享出来供你参考。第一件事Skill 粒度重新拆。一开始我把整个数据分析流程写成一个 Skill结果智能体在加载时经常囫囵吞枣跳步执行。后来我把一个 Skill 拆成四个独立的小 Skill数据清洗、探索分析、趋势洞察、报告生成。每个 Skill 的目标单一、步骤清晰、工具数量控制在 3-4 个。效果立竿见影——执行完成率从 60% 出头提升到 85% 左右。第二件事给 Agent 加了一个 evaluation 环节。就是在生成报告之前加一个独立的质量检查节点对照方法论检查报告有没有遗漏核心图表、结论有没有数据支撑、有没有超出业务约束。这个节点本身不产生新内容只做校验和打回。相当于给智能体的输出加了一道质检关。这个做法最初我是从社区里一个evaluation 智能体添加方法论的讨论里学到的实践下来对最终报告质量的提升非常明显。第三件事扩展到本地业务数据库查询。企业环境里智能体最终要面对的不是 CSV而是数据库。我把load_csv工具替换成query_mysql工具并配了一个只读账号让智能体可以查本月各区域销售额这类问题。Harness 的流程不需要大改——数据加载节点从读文件变成执行 SQL后面的清洗、EDA、洞察、报告逻辑完全复用。这个扩展让我意识到这套架构的价值在于流程本身是可迁移的换数据源只是换一个工具的事。最后说一个我自己的体会OpenCode 加 Harness 这个组合真正打动我的不是说它能跑多复杂的流程而是它把智能体开发从写 Prompt 调 API推进到了编流程、定义工具、沉淀方法论的工程化阶段。你在 Harness 里画的每一张状态图、写的每一条工具描述、沉淀的每一个 Skill都是可复用、可维护的资产。这套东西用熟了之后你再看那些纯靠一个超长 Prompt 硬撑的智能体会明显感觉到两者的差距——一个是在做工程一个是在碰运气。