用Harness构建投研智能体:做交易领域的Claude Code 1. 从投研痛点出发为什么交易场景需要智能体工程先聊一个很多量化团队都绕不开的困境投研流程看似自动化程度很高但真正跑起来全是手工作业。数据抓取、研报摘要、策略回测、因子筛选、风险归因……每一步都有现成的工具但步骤与步骤之间的衔接几乎靠人肉搬运。我见过不少团队的“自动化”其实就是把十几个脚本按顺序手工触发一遍美其名曰流水线实际上换个数据源或者加个新业务需求就得改半天代码。李昱琦在 Panda AI 做的事情本质上就是要把这种“点状工具”变成“端到端智能体”。他提到用 Harness 重构投研核心思路不是再写一个更大的系统而是把研究流程本身交给一个能自主规划、调用工具、持续迭代的智能体来跑。这个概念听着很熟对吧Claude Code 在编程领域解决的问题——让模型理解长上下文、自主读写代码文件、执行命令、根据报错自我修正——在投研领域几乎是一一对应的刚需模型需要读取大量研报和数据需要调用回测引擎和数据库需要根据结果调整策略参数。所以“做交易领域的 Claude Code”这个定位非常精准。Claude Code 解决的是“让 AI 写代码”这件事的工程化问题而 Panda AI 想解决的是“让 AI 做投研”这件事的工程化问题。两者表面上功能完全不同底层的智能体架构思维却是相通的。我在实际体验 Harness 这类智能体框架时最大的感受是它真正补齐了“规划-执行-反馈”的闭环。普通对话式 AI 你问一句它答一句但投研不是问答是一条链先确认研究目标再定数据需求然后抓数、清洗、建模、回测、归因最后输出报告。每一步的结果都可能影响下一步的策略这恰恰是智能体框架最擅长处理的事情。2. Harness 与 Claude Code 的底层逻辑异同2.1 Claude Code 做对了什么Claude Code 之所以在开发者圈子里口碑很好不是因为它能“聊天写代码”而是它把编码这个任务拆成了可执行的子任务链。我记得它最核心的设计就是两个一是长上下文管理让模型能记住一个大型代码库的结构和约定二是工具调用它可以直接读写文件、执行终端命令、跑测试、看报错。这两点合在一起模型就不再是一个“建议生成器”而是一个“协作者”——它会自己发现问题、验证假设、修复错误。这里有个很关键的细节Claude Code 的“工具调用”不是一次性的而是带反馈循环的。写完代码跑一遍单测红了就改绿了再继续。这个“行动-观察-调整”的循环是它和普通 AI 编程助手的本质区别。投研也一样回测失败、数据缺失、因子不显著都需要智能体自己感知、自己调整而不是停下来等人来处理。2.2 Harness 的设计哲学与适用边界Harness 是更偏底层的智能体编排框架它提供的是让开发者能构建专用智能体的脚手架。你可以理解成Claude Code 是已经组装好的成品Harness 是一套零件和组装说明书。它对标的是 LangChain、LangGraph 这类 Agent 编排层但更强调“可控”和“可观测”。我实际拆过 Harness 的架构它最核心的概念其实就三个Task任务定义智能体要做什么有明确目标和验收标准Skill技能可复用的原子能力比如“读取CSV”“调回测接口”“生成图表”Orchestrator编排器决定任务如何拆解成子任务、按什么顺序调用哪些技能。这三个概念组合起来就能打造一个“只做投研”的专用智能体而不是一个什么都聊两句的通用助手。这和 Claude Code 的“只做编码”是同一个思路领域专用、边界清晰、工具内置、反馈闭环。不过 Harness 也不是银弹。它上手门槛比直接用 Claude Code 高不少毕竟你要自己定义任务拆解逻辑和技能集。很多人拿它当 LangChain 用结果发现上手很陡。我自己的体会是如果你要解决的是一个相对固定的流程问题比如“每周生成行业研究报告”Harness 价值极高如果你要的是“陪我头脑风暴一下策略方向”那大可直接用通用对话没必要上框架。2.3 从“AI 编程”到“AI 投研”的映射李昱琦把交易领域对标 Claude Code映射关系其实非常清晰编程场景投研场景项目代码库历史行情库、研报库、财务数据库函数与接口因子库、回测引擎、风险模型编译器/解释器报错数据异常、回测警告、归因误差单元测试样本外测试、参数敏感性检验linter/type checker数据一致性校验、逻辑完整性检查版本控制策略版本管理、研究过程留痕这样一对比你就明白为什么投研是最适合智能体落地的领域之一了。它有明确的目标函数收益、回撤、夏普有标准化的数据接口有可验证的实验框架这简直是智能体天然的试验场。3. 实操拆解用 Harness 搭建一个投研智能体的核心步骤这里不聊玄的直接说我在参考 Panda AI 的思路后用 Harness 跑通一个“研报复盘因子初筛”智能体的完整过程。它不一定和 Panda AI 的生产环境完全一致但思路和骨架是通用的。3.1 环境与工具准备先说明Harness 的安装方式更新很快我这里用的是比较稳定的版本路径。整体上分三步# 1. 以 Python 项目形态创建环境避免污染全局 python -m venv .harness-env source .harness-env/bin/activate # 2. 安装核心harness包与依赖 pip install harness-core langchain langgraph # 3. 验证安装确认能正常加载skill模块 harness-cli --version这一步有个容易踩的坑很多人把 langchain 和 langgraph 当成二选一但其实 Harness 的编排器往往需要两者配合一个管工具调用链一个管状态图流转。我建议都装上省得后续跑示例时报找不到模块的错。另外特别强调一下模型选型。Harness 本身只是编排骨架脑子还是靠大模型。李昱琦在专访中提到他们很早就接入了 DeepSeek 系列的推理模型原因很直白一是国产模型在中文研报理解上确实有优势二是 DeepSeek 在长文本和工具调用上表现稳定性价比更适合大批量投研任务。我自己也用 DeepSeek 接 Harness 跑过注意要把模型参数里的temperature调低到 0.3 以下否则智能体在决策时会太“发散”影响回测策略的一致性。3.2 定义 Skill 技能集Skill 是 Harness 里最容易被低估的部分。很多人上来就写大而全的 Skill结果一个 Skill 里塞了十几个函数复用性极差。我建议按“单职责原子技能”来设计。以投研场景为例我实际定义了这些 Skillread_report_pdf(path)读取 PDF 研报并提取关键段落支持多页拼接fetch_index_data(code, start, end)拉取指数行情数据自动处理停牌和除权clean_missing_value(df)按列策略填充缺失值保留填充日志run_backtest(strategy_func, data)执行回测并返回净值、回撤、换手率generate_summary(text, max_words)调用模型生成长文本摘要默认压缩到 20% 长度。这里有个设计心得每一个 Skill 都应该有一份清晰的输入输出说明docstring并且是带缓存设计的。投研数据重跑很常见同一个月的研报你会反复分析不做缓存的话每次都重新读 PDF、重新拉行情既慢又烧接口额度。我的做法是在 Skill 上包一层cache_result装饰器按参数哈希做本地缓存命中就直接返回。3.3 编写任务编排逻辑Task 编排是 Harness 里最体现“重构投研”价值的部分。传统的投研流程是线性的读研报-提观点-拉数据-验证-写总结。但 Harness 里我会把它改成有分支的图结构from harness import Task, SkillRouter def build_investment_agent(): # 核心任务1解析研究目标 parse_task Task( nameparse_goal, goals从用户输入中提取研究标的、时间范围和核心假设, skills[extract_entities, parse_timeline] ) # 核心任务2动态数据补全 data_task Task( namecollect_data, goals如果检测到数据缺失自动选择补全路径, skills[fetch_index_data, fetch_fund_flow, clean_missing_value], fallbackfetch_reverse_index ) # 核心任务3逻辑验证与迭代 verify_task Task( nameverify_hypothesis, goals对研报观点做量化验证输出显著性结论, skills[run_backtest, cal_sharpe, wald_test], iterations3 ) return SkillRouter([parse_task, data_task, verify_task])这段代码里有两个细节值得展开。第一data_task的fallback参数。投研里常遇到某个行情源数据不完整的情况早期我写的 Agent 遇到这种情况直接终止后来发现太死板。Harness 支持指定 fallback 技能比如主源缺数据时自动用备源补这样 Agent 就不会因为一个源异常就全盘失败。第二verify_task的iterations3。这是智能体和普通脚本的又一个关键区别如果第一次回测结果不显著脚本只会输出“不显著”而智能体会尝试调整参数范围、更换时间段、换数据频率再试。迭代上限一定要设否则遇到一个坏因子会无限调参最后过拟合到历史数据里出不来。我通常设 2~3 次迭代并且要求每次调整都必须记录调整理由方便事后追溯。3.4 接入反馈与可观测机制“做交易领域的 Claude Code”这句话里最容易被忽略的是后半句中的工程化属性。Claude Code 之所以耐用是因为它对整个操作过程有完整的日志什么命令执行了、什么文件改动了、为什么这么改。投研智能体也必须这样。我在 Harness 里加了一个回调钩子每次 Task 完成都会把结果写到一份结构化日志里class InvestmentLogger: def on_task_start(self, task_name, params): log_meta(actiontask_start, tasktask_name, paramsparams) def on_skill_call(self, skill_name, result): log_meta(actionskill_call, skillskill_name, result_summaryhash(result)) def on_task_end(self, task_name, success): log_meta(actiontask_end, tasktask_name, successsuccess)这样跑完一轮研究你得到的不仅是一份投资结论还有完整的“研究过程审计轨迹”。这在投研场景里意义非常大——你永远可以回答“这个结论是怎么来的”这个问题。做投资决策跟写代码一样最贵的不是犯错而是犯了自己都不知道的错。4. 四个高频问题与排查经验4.1 Agent 跑了半天结果逻辑断裂为什么症状一个多任务智能体看起来每一步都执行了但最终结论和中间分析对不上。比如研报摘要说得是看好新能源但因子分析的输出却指向消费板块。排查方向大概率是任务编排时上下文传递出了问题。Harness 每个 Task 默认只接收上游 Task 的摘要输出而不是全部中间过程。如果你的下游任务需要看上游的某个中间细节必须在 Task 连接器里显式声明要引用哪个变量。我之前就在SkillRouter里漏传了research_target结果下游任务自作主张用了自己解析出的标的两个任务各跑各的。解决办法很简单在 Task 之间使用显式的上下文契约把要传递的字段一一列出来。投机取巧一点的办法是在 Task 名称里带上关键参数比如collect_data__target001696调试时一眼就能看出链路对不对。4.2 智能体在工具调用时反复报错症状run_backtest这个 Skill 明明单独跑没问题但一旦放进 Harness 编排里就频繁报参数类型错误。排查方向先查 Skill 的输入校验再看编排器有没有对中间结果做类型转换。我遇到过最愚蠢的一次上游传的是 numpy 数组下游按 list 接入Python 不会报错但回测引擎直接给结果算错了。后来我在每个 Skill 入口加了一行断言强制转换到明确类型def run_backtest(strategy_func, data): assert isinstance(data, pd.DataFrame), data必须为DataFrame data data.copy() ...另一个高频问题是 Skill 超时。比如读取一个超大 PDF 可能超过编排器默认的超时时间AI 就会误判为工具失败然后自作主张换了一条逻辑链。我建议把处理大文件的 Skill 超时时间放宽到 600 秒并且在 Skill 内部分步骤打印进度让编排器知道“还在跑没死”。4.3 深度推理模型接入后走不动症状把 Harness 接入 DeepSeek 后Agent 输出质量很高但每一步决策都特别慢一个原本 2 分钟跑完的任务拖到 15 分钟。排查方向十有八九是思维链输出太长。投研场景很多决策本来就不需要深度推理比如“数据缺失用均值填充”这种直接让模型给个选择就行。我的经验是给 Harness 编排器配两套模型快速模型如 DeepSeek 的小参数版本负责路由、分类、摘要这类轻量决策强推理模型负责假设验证、策略生成这类复杂任务。这样既保证质量又不会所有环节都在“深度思考”。这也是我在同类 Agent 工程里最推荐的一个性能优化手段没有之一。4.4 回测结果不可复现症状同一个策略同一个数据区间跑两次回测得到的净值序列居然不一样。排查方向先别怀疑 Harness大概率是数据源本身有实时更新。比如你拉的是“截至今日”的数据第一次跑是盘中数据第二次跑多收了一根日K结果自然不一样。我在投研场景里的规范是所有回测数据必须按日期快照冻结。具体做法是拉数据时拼接一个data_date字段并保证从固定表里读取而不是从上游实时接口拿。另外如果代码里用了多线程或者并行采样记得固定随机种子。Harness 的编排过程本身是顺序的但如果你在 Skill 内部用了np.random那就必须np.random.seed(42)。这类问题排查起来特别隐蔽我被坑过一次之后直接在 Skill 基类里强制设置了默认随机种子并在日志里记录种子值后面再也没出现过复现不了的问题。5. 从“工具链”到“团队工作流”的升级思考聊了这么多 Harness 的技术细节最后想回到“重构投研”这件事本身。我特别认同李昱琦提到的一个观点现在很多团队对 AI 在投研中的应用还停留在“用 AI 写周报”“用 AI 做摘要”这种浅层替代阶段这其实没有改变工作的本质。真正有想象力的是把它变成一个新的协作角色——一个能自主完成“假设-验证-归因”循环的研究助手。从这个角度看投资领域构建智能体和软件开发领域构建 Claude Code 最大的共同点是都是在打造一个“可信任的代理”。代码领域你要信任它不会偷偷删文件投研领域你要信任它不会用一个有幸存者偏差的数据集得出乐观结论。这种信任不能靠模型自觉必须靠工程机制来保证。Harness 这类框架之所以有价值就是因为它把“审计”“回滚”“验证”“约束”这些工程概念带进了智能体的构建中。我自己的实践体会是构建一个能真正落地的投研智能体难点从来不在模型能力而在流程的工程化程度。你越是把任务边界定义清楚越是把技能设计得单薄可复用越是把每一步决策都记录在案智能体的表现就越稳定、越可靠。这和写高质量代码的逻辑一模一样。最后分享一个小技巧在上线之前找一个已经跑过很多遍的历史研究案例把它的完整流程和数据喂给智能体让它从头到尾重演一遍然后对比两边当时的决策逻辑和最终结论。这个“重演测试”能最快暴露你在任务编排里的疏漏比任何单元测试都管用。我每次构建新的智能体工作流都会这么干一遍基本上跑两三轮之后这个智能体就可以放心去处理新任务了。如果你也想在自己的领域做类似的智能体重构我的建议是不用一上来就追求大而全从一个你天天在做的重复流程开始先跑通最小闭环再逐步叠加数据源和技能。等哪天它处理流程化任务已经不需要你操心细节了你就能腾出手来去做那些真正需要人类判断力的事了。