1. 项目概述一个基于状态机的自主LLM智能体如果你正在构建或使用LLM智能体大概率遇到过这样的困境你把所有能调用的工具、API、函数都一股脑儿塞给模型然后满怀期待地发出指令。结果呢模型要么在几十个选项里犹豫不决浪费大量token去“思考”该用哪个要么干脆选错工具执行了风马牛不相及的操作。这背后的核心问题是上下文过载和决策空间爆炸。Haath这个项目就是为解决这个问题而生的。它不是一个简单的“工具调用框架”而是一个运行在有限状态机FSM内部的自主LLM智能体。简单来说它给智能体的“思考”过程加上了红绿灯和导航地图。智能体在任何时刻都只知道自己当前在哪个“路口”状态以及从这个路口能合法地走向哪几条“道路”有效状态转移。它看不到整个城市的全貌也看不到那些无关的、遥远的工具从而避免了决策混乱。我花了不少时间深入研究了它的核心协议ASMP和配套工具clrun发现这套设计思路非常巧妙。它特别适合那些需要多步骤、有条件分支、且工具集复杂的自动化任务比如根据用户查询自动进行网络搜索、分析结果、生成报告并发送邮件或者监控系统日志在特定条件下触发诊断、修复等一系列操作。对于智能体开发者、自动化工程师或者任何希望将LLM能力更可靠、更经济地集成到工作流中的人来说Haath提供了一个极具潜力的新范式。2. 核心架构与设计哲学拆解要理解Haath不能只看它本身必须把它和它的两个“左膀右臂”——ASMP和clrun——放在一起看。这三者构成了一个完整的智能体执行栈。2.1 有限状态机FSM为何是智能体的“最佳拍档”传统的智能体架构可以比喻为一个拥有“上帝视角”的指挥官。它面前摊开着一张包含所有可能行动的巨大地图工具列表每次行动都需要重新审视整张地图。这不仅低效而且容易出错。Haath采用的FSM架构则将任务分解为一系列离散的状态。每个状态代表任务流程中的一个特定步骤或情境。关键在于每个状态都明确定义了状态提示用自然语言描述当前步骤的目标和上下文。有效转移从当前状态可以合法进入的下一个状态列表。阶段工具仅在此状态下可用的工具和资源。可选技能一个可动态加载的、更复杂的技能模块通过Open Agent Skill规范仅在需要时引入。这种设计带来了几个根本性优势降低Token消耗与推理负担模型每次决策时上下文窗口里只有当前状态的信息极大减少了无关token的干扰让模型更专注于当前步骤的“最优解”。提升决策可靠性通过服务器端ASMP严格定义的有效转移约束了模型的行动空间。模型无法“异想天开”地跳到一个未定义的步骤从机制上避免了无效或危险的操作序列。实现工作流的结构化与模块化整个任务流程被图形化、代码化。你可以像设计流程图一样设计智能体的行为每个状态和转移都可以被版本控制、测试、复用和分享。2.2 ASMP定义智能体行为的“交通法规”ASMP是这一切的基石。你可以把它理解为一套用于定义和驱动智能体状态机的协议和服务器实现。它提供标准的HTTP端点让智能体通过网关能够GET /frame获取当前的状态帧包含提示、下一步选项、工具等。POST /transition请求转移到下一个状态。POST /invoke在当前状态下调用一个工具。ASMP服务器维护着状态机的权威定义。当Haath智能体想要“学习”或优化一个工作流时它实际上是通过API向ASMP服务器发送请求来动态地添加、删除或修改状态和转移。这意味着智能体的“经验”可以沉淀为可持久化、可共享的工作流定义文件而不是消失在模型的短期记忆里。2.3 clrun智能体与真实世界交互的“手和脚”智能体有了“大脑”LLM和“行动规则”ASMP FSM它还需要与外部世界交互的能力。这就是clrun的用武之地。clrun是一个为智能体设计的命令行运行时环境。它的核心价值在于处理交互式命令行工具很多安装程序、配置工具是交互式的TUI基于文本的用户界面。clrun可以模拟按键输入让智能体能够自动化完成这些流程而不仅仅是执行简单的单行命令。提供结构化输出clrun执行命令后返回的不是纯文本而是结构化的YAML包含output标准输出、hints可能的下一步建议、warnings等字段。这为LLM解析结果提供了极大便利。作为ASMP的远程CLI客户端这是clrun与Haath/ASMP集成的精髓。ASMP的每个状态都可以暴露一个动态的CLI端点GET /runs/{run_id}/cli。clrun可以连接到此端点使得智能体在特定状态下能通过一个统一的CLI接口与状态机交互执行该状态允许的操作。这让状态转移在体验上就像在终端里输入不同的命令一样自然。2.4 Haath智能的“调度中心”与“学习引擎”Haath自身则扮演着协调者和进化引擎的角色。它内置的网关负责配置管理统一管理LLM供应商、API密钥、预算策略通过集成Waterfall网关。请求路由与编排接收用户或系统的任务请求向ASMP查询当前状态将状态帧和用户指令组合后发送给LLM解析LLM的响应选择转移或调用工具再驱动ASMP或clrun执行。工作流进化基于任务执行的结果和反馈Haath可以决定是否以及如何修改底层的ASMP状态机定义从而实现工作流的自我优化。实操心得理解端口分工在本地部署时Haath网关默认运行在28657端口而OpenClaw等其他项目常用18789端口避免了冲突。ASMP服务通常由Haath网关内部挂载在/asmp路径下或者作为独立服务运行。清楚每个组件的监听端口和API路径是后续调试和集成的关键。3. 核心工作流程与执行循环详解让我们跟随一个智能体完成一次任务的全过程来感受Haath体系是如何协同工作的。假设我们有一个“获取天气并生成简报”的工作流它包含GatherLocation获取位置、FetchWeather获取天气、GenerateSummary生成摘要三个状态。3.1 单次执行循环的八个步骤任务触发用户通过Haath网关API或UI发起任务“给我生成一份北京今天的天气简报”。状态帧获取Haath网关向ASMP服务器可能是内置的发送请求GET /runs/{new_run_id}/frame。ASMP返回初始状态例如GatherLocation的帧内容包括提示语“请确定需要查询天气的城市”、可用的工具可能有一个“地点解析器”、以及有效的下一个状态[“FetchWeather”]。LLM决策Haath网关将当前状态帧和用户原始指令组合形成给LLM的提示然后通过Waterfall网关如果配置了发送给选定的LLM如GPT-4。提示大致是“你当前处于‘GatherLocation’状态目标是确定城市。你可以使用‘地点解析器’工具。用户说‘给我生成一份北京今天的天气简报’。请决定你的下一个动作。”解析与行动LLM返回一个结构化的响应比如{“action”: “invoke”, “tool”: “location_parser”, “input”: “北京”}。Haath网关解析此响应。工具调用Haath网关向ASMP服务器发送POST /runs/{run_id}/invoke调用“地点解析器”工具输入为“北京”。ASMP执行工具逻辑可能调用一个内部函数或微服务返回标准化结果例如{“city”: “Beijing”, “country”: “CN”}并自动或根据逻辑将状态机推进到FetchWeather状态。新一轮状态获取Haath网关再次获取FetchWeather状态的状态帧。新的帧可能包含提示“请使用天气API查询指定城市的天气”、工具“天气查询API”、以及参数上一步输出的city和country。CLI/外部执行LLM决定调用“天气查询API”。这个调用可能通过Haath网关直接发起HTTP请求也可能如果该工具被定义为通过clrun执行一个命令行脚本例如调用curl访问天气服务则由Haath网关驱动clrun去执行。clrun返回结构化的天气数据。状态推进与循环天气数据被返回给ASMP状态可能推进到GenerateSummary。LLM根据之前所有步骤的上下文这些上下文由ASMP维护在本次运行run_id的会话中生成最终简报。任务完成ASMP状态机进入终态。3.2 动态工作流演进的实现Haath最强大的特性之一是工作流可以在运行时被修改。以上面的流程为例假设在多次运行后Haath发现用户经常在生成简报后追问“明天的天气怎么样”。现有的工作流在GenerateSummary后就结束了无法处理这个追问。此时Haath的“学习引擎”可以启动分析Haath记录到在终态之后频繁出现同类新请求。决策它决定扩展工作流。执行Haath通过ASMP的管理API在GenerateSummary状态后新增一个状态HandleFollowUp并添加一个从GenerateSummary到HandleFollowUp的转移条件例如当用户输入包含“明天”时。同时为HandleFollowUp状态配置相应的工具再次调用天气API和提示。固化这个修改后的状态机定义可以被导出为一个JSON/YAML文件。下次部署时可以直接加载这个更完善的工作流。这就是“工作流进化”将经验固化为了可执行的结构化知识。注意事项状态设计的粒度设计状态时粒度把控很重要。状态太粗如“处理用户请求”就失去了约束和分步指导的意义状态太细如“打开API连接”、“发送请求”、“读取响应”会导致状态数量爆炸管理复杂。一个好的原则是一个状态应对应一个明确的、可验证的“子目标”或“决策点”。例如“验证用户身份”、“获取数据”、“分析结果”都是不错的粗粒度状态。4. 环境搭建与核心组件部署实操理论讲完了我们动手把Haath及其生态跑起来。这里会以本地开发环境为例给出详细的步骤和避坑指南。4.1 前置准备与依赖安装假设你的系统是 macOS/Linux并已安装 Node.js (18), Python (3.9), 和 Git。# 1. 克隆所有相关仓库 git clone https://github.com/cybertheory/haath.git git clone https://github.com/cybertheory/asmp.git git clone https://github.com/cybertheory/clrun.git # 2. 安装ASMPPython SDK和服务器 cd asmp pip install -e . # 安装Python SDK # ASMP本身是一个协议服务器实现可能需要根据语言选择。 # 这里假设使用其TypeScript SDK作为服务器它通常被Haath网关集成。 cd .. # 3. 安装clrun cd clrun npm install # 或使用其推荐的安装方式可能是 pip 或 cargo请查阅clrun的README # 如果是Node.js项目 npm run build cd .. # 4. 安装Haath网关依赖 cd haath/gateway npm install4.2 启动Haath网关集成ASMPHaath网关是一个Next.js应用它已经集成了ASMP TypeScript SDK。# 在 haath/gateway 目录下 # 首先可以运行测试确保环境正常可选但推荐 HAATH_DATA_DIR$(mktemp -d) npm test # 启动开发服务器 npm run dev默认情况下网关会在http://localhost:28657启动。访问这个地址你应该能看到Haath的配置仪表板。网关的配置如LLM设置会持久化在~/.haath/haath.json文件中。关键配置点通过UI或API配置Agent配置设置默认的模型、温度等参数。Waterfall网关集成如果你想使用Waterfall来管理和计量LLM调用需要在这里配置Waterfall网关的地址和API密钥。这是实现“财务感知”的关键。ASMP端点网关内部已经挂载了ASMP在/asmp所以ASMP服务器的地址通常是http://localhost:28657/asmp。4.3 理解并运行一个示例工作流Haath项目可能自带示例工作流。我们需要理解如何加载和执行它。步骤一定义或加载FSM工作流本质是一个符合ASMP规范的JSON定义。你可以通过Haath网关的API来上传或激活一个工作流。# 假设有一个简单的 simple_flow.json 工作流定义文件 curl -X POST http://localhost:28657/api/v1/workflows \ -H Content-Type: application/json \ -d simple_flow.json步骤二启动一个运行实例创建工作流后你需要启动一个具体的“运行”。curl -X POST http://localhost:28657/asmp/runs \ -H Content-Type: application/json \ -d {workflow_id: your_workflow_id_here}这个请求会返回一个run_id它是跟踪这次具体任务执行的唯一标识。步骤三使用clrun连接并交互这是最体现其设计哲学的一步。你可以使用clrun以“远程CLI模式”连接到这个正在运行的状态机。# 假设 clrun 已安装并可用 clrun asmp attach http://localhost:28657/asmp/runs/{run_id}/cli执行后你的终端会变成一个受状态机驱动的交互界面。clrun会从ASMP获取当前状态所暴露的“动态CLI”命令列表。你或自动化的Haath智能体输入的指令会被映射到状态机允许的操作上并驱动状态转移。4.4 配置LLM网关Waterfall以实现成本管控对于生产级应用直接调用OpenAI、Anthropic等API会有成本失控的风险。Haath设计上与Waterfall网关集成提供了解决方案。部署或连接Waterfall网关按照Waterfall文档部署其网关服务或使用其云服务。假设网关地址为http://localhost:8080。在Haath网关中配置在Haath的UI配置页面找到Waterfall设置项。Waterfall Gateway URL: 填入http://localhost:8080API Key: 填入你的Waterfall API密钥。Default Provider/Model: 在Waterfall网关中配置的模型别名如gpt-4。效果此后所有Haath网关发往LLM的请求都会先经过Waterfall网关。Waterfall会进行计量、限流、负载均衡如果你配置了多个供应商并将使用情况记录到其仪表板中。这样你就能清晰地知道每个智能体、每个工作流消耗了多少成本。避坑指南初次运行的常见问题端口冲突确保28657端口未被占用。如果冲突可以在gateway/.env文件中修改PORT环境变量。ASMP路径404确保Haath网关服务正常运行并且其集成的ASMP SDK路由正确挂载。检查网关日志。clrun连接失败确认run_id正确且该运行实例处于活动状态未结束。检查ASMP服务器返回的CLI端点是否有效。Waterfall网关连接超时确保Waterfall网关服务已启动且网络可达。检查Haath配置中的URL和API密钥是否正确。5. 高级应用构建自定义技能与复杂工作流掌握了基础部署后我们来探索如何发挥Haath的真正威力——创建适应你自己业务逻辑的智能体。5.1 设计并实现一个自定义ASMP状态机假设我们要构建一个“智能客服工单分类与路由”工作流。第一步定义状态我们需要用JSON或YAML定义状态机。以下是一个高度简化的示例结构{ workflow_id: ticket_triage, initial_state: receive_ticket, states: { receive_ticket: { hint: 你收到了一份新的用户工单。请阅读内容并理解问题。, transitions: [categorize_ticket], tools: [ { name: extract_ticket_info, description: 从工单文本中提取关键信息如产品名称、错误代码、用户情绪等。, handler: http://your-backend/tools/extract // 指向实际处理该工具的HTTP端点 } ] }, categorize_ticket: { hint: 根据提取的信息将工单分类为‘技术问题’、‘账单问题’或‘功能咨询’。, transitions: [route_tech, route_billing, route_general], resources: { categories: [技术问题, 账单问题, 功能咨询], routing_rules: 技术问题转给工程部账单问题转给财务部功能咨询转给产品部。 } }, route_tech: { hint: 工单属于技术问题。请将其分配给合适的工程师并发送确认通知。, transitions: [finalize], tools: [assign_to_engineer, send_notification] }, route_billing: { ... }, route_general: { ... }, finalize: { hint: 工单已路由完成。更新工单状态并记录处理日志。, is_terminal: true, tools: [update_ticket_status] } } }第二步实现工具处理器每个tool定义中的handler指向一个HTTP端点。你需要实现这些端点。例如extract_ticket_info工具的处理函数使用Python FastAPI示例from fastapi import FastAPI, HTTPException from pydantic import BaseModel app FastAPI() class TicketRequest(BaseModel): ticket_text: str app.post(/tools/extract) async def extract_ticket_info(request: TicketRequest): # 这里可以集成NLP模型或规则引擎来分析工单文本 # 这是一个简单示例 text request.ticket_text.lower() info {} if error in text or bug in text: info[category_hint] 技术问题 elif charge in text or payment in text: info[category_hint] 账单问题 else: info[category_hint] 功能咨询 # 返回结构化的提取结果 return { output: info, hints: f建议分类为{info[category_hint]}, warnings: [] if info[category_hint] else [未能明确分类] }第三步注册并运行工作流将定义好的JSON通过Haath网关API上传然后启动一个运行实例。智能体就会按照这个状态机来一步步处理工单。5.2 利用clrun自动化复杂CLI操作很多运维、部署任务依赖于命令行。clrun可以让智能体安全、可靠地执行它们。假设我们需要一个“服务器健康检查”状态。在对应状态的tools中可以定义一个通过clrun执行的工具{ name: check_disk_usage, description: 检查指定服务器的磁盘使用率如果超过阈值则告警。, handler: clrun://local, // 表示通过本地clrun执行 command: ssh {{server}} df -h / | tail -1 | awk {print $5} | sed s/%//, parameters: [ {name: server, type: string, required: true} ] }当LLM决定调用此工具时Haath网关会驱动clrun执行该SSH命令解析返回的磁盘使用率百分比并将结果以结构化YAML格式返回给状态机供后续状态如“发送告警”判断使用。5.3 实现工作流的动态进化与合并这是Haath的杀手级特性。你可以通过编程方式或基于规则来修改运行中的状态机。场景在“工单分类”工作流运行一段时间后发现很多关于“API速率限制”的工单被误分类为“技术问题”实际上它们属于“配置问题”。操作导出当前工作流通过ASMP APIGET /workflows/ticket_triage导出当前定义。分析并修改在导出的JSON中找到categorize_ticket状态。在其resources.routing_rules中增加关于“API速率限制”的规则描述。或者更复杂一点在categorize_ticket和route_tech之间新增一个判断状态check_for_rate_limit并配置相应的工具来识别此类问题。合并更新通过ASMP APIPATCH /workflows/ticket_triage提交更新后的定义。Haath网关和所有后续的运行实例都将使用这个优化后的版本。你也可以将多个团队开发的、针对不同场景的工作流如ticket_triage,server_deploy,data_backup合并成一个更大的、可组合的智能体技能库实现能力的复用和积累。经验之谈工具设计的“幂等性”与“安全性”为智能体设计工具时必须格外注意。工具执行应尽可能幂等多次执行同一操作效果相同和安全避免破坏性操作。对于高风险操作如rm -rf, 数据库DROP要么通过状态机设计严格限制其触发条件要么在工具实现中加入二次确认或模拟运行模式。永远不要给智能体一个不受限制的shell.exec()工具。6. 性能调优、问题排查与最佳实践将Haath用于实际项目时以下几个方面的考量至关重要。6.1 性能与成本优化策略优化方向具体措施预期收益状态设计保持状态提示hint简洁、目标明确。将冗长的背景信息放在resources中模型可按需参考。减少每个决策步骤的Prompt长度直接降低Token消耗和延迟。工具设计工具接口设计应粒度适中功能单一。避免一个工具做多件事这会让模型困惑。工具返回应结构化、简洁。提高工具调用的准确率和效率减少不必要的LLM调用去解析混乱的输出。LLM网关务必使用Waterfall或类似网关。设置预算、速率限制并利用其缓存功能如果支持。为不同工作流配置不同模型如简单分类用GPT-3.5复杂推理用GPT-4。精确控制成本防止意外超支。通过缓存和模型路由优化响应时间与开销。异步与并行分析工作流将其中没有依赖关系的状态或工具调用设计为可并行。ASMP协议本身支持异步操作可以设计非阻塞的状态转移。大幅提升复杂工作流的整体执行速度。6.2 常见问题排查速查表问题现象可能原因排查步骤智能体在某个状态“卡住”不执行转移。1. LLM返回的action格式不符合ASMP预期。2. 请求的next_state不在当前状态定义的transitions列表中。3. 工具调用失败或超时。1. 检查Haath网关日志查看从LLM收到的原始响应。2. 检查当前状态的transitions定义确认目标状态是否合法。3. 检查工具处理端点的日志和可用性。clrun连接ASMP CLI失败。1.run_id不正确或运行已终止。2. ASMP服务器未正确配置动态CLI端点。3. 网络或防火墙问题。1. 确认run_id有效且状态机未处于终态。2. 直接访问http://asmp_server/runs/{run_id}/cli看是否返回CLI定义。3. 使用curl测试网络连通性。Waterfall网关计量不准或请求失败。1. Haath网关中Waterfall配置错误。2. Waterfall网关自身故障或限流。3. 模型别名配置错误。1. 核对Haath配置中的URL和API Key。2. 查看Waterfall网关自身的监控和日志。3. 在Waterfall面板检查模型别名映射是否正确。工作流修改后不生效。1. 修改未成功提交到ASMP服务器。2. 新的运行实例使用了旧的缓存定义。3. 工作流ID引用错误。1. 使用API确认工作流定义已更新。2. 确保创建新run时指定了正确的工作流版本或ID。3. 检查创建运行实例的请求体。6.3 安全与运维最佳实践最小权限原则运行Haath网关、clrun以及工具后端服务的系统账户应仅拥有完成其职责所必需的最小权限。特别是clrun执行的命令要严格审查。输入验证与沙箱对所有从LLM或用户端传入最终用于工具调用或命令执行的参数进行严格的验证和转义。考虑对clrun执行环境进行沙箱化隔离例如使用Docker容器。审计与日志确保Haath网关、ASMP服务器、clrun以及所有自定义工具都有完整的操作日志。记录每个run_id的完整状态转移历史、LLM请求/响应、工具调用输入输出。这对于调试、审计和后续的工作流分析至关重要。版本控制工作流将ASMP工作流的JSON/YAML定义文件纳入Git等版本控制系统。每次对智能体行为的重大修改都应对应一个工作流版本的提交便于回滚和协作。监控与告警监控关键指标LLM API调用延迟与错误率、状态机平均完成时间、clrun命令执行成功率。为异常情况如连续失败、成本超阈值设置告警。从我实际整合和测试的经验来看Haath这套体系最大的价值在于它将智能体的“行为编程”从模糊的提示词工程转变为了清晰的状态机工程。它迫使你将复杂任务分解明确每一步的输入、输出和边界条件。初期设计状态机需要一些额外开销但一旦构建完成其可靠性、可维护性和可进化性是传统“扁平工具调用”模式难以比拟的。尤其对于企业级需要稳定、可控、可审计的AI自动化场景这种结构化的方法提供了坚实的基础。