AgentHub 实战手记(六):给任务列一张清单,但别把打勾当成做完
做一件事时,脑子里记着“先查资料,再整理答复”还算轻松。事情一多,查到一半去处理别的,再回来,就容易忘掉刚才停在哪里。 Agent 处理多步骤任务时,也需要一个地方记下:准备做什么,正在做什么,还有什么没处理。 这次整理的是 10 月 19 日完成的 Todo 主程序集成。新增的 todo_write 已经进入 AgentHub 原有的工具表,与知识检索共用模型循环、Hooks 和运行观察器。命令行入口也能直接运行这套流程。 不过,给一件事打勾很容易,确认它真的做完要难一些。这一版的清单负责保存状态和发出提醒,完成标记仍由调用方提交,业务结果还得另外核对。 先说清楚:这次提交的是整张清单todo_write 接收一个 JSON 对象,其中的 todos 是完整清单。例如,查询条款刚开始时,可以提交: 123456{ "todos": [ {"content": "查询拆封耳机退货条款", "status": "in_progress"}, ...
AgentHub 实战手记(五):给工具调用加上 Hook,让“先等等”真的生效
上一篇写权限判断时,我把“允许、询问、拒绝”拆进了独立函数。不过,函数能算出结果,和工具真的会停下来,中间还隔着一步。 想象一下:门口的检查员已经说了“先等等”,里面的工具却照常开工。规则写得再清楚,也只是多了一句提醒。 这次整理的是 10 月 15 日接入 AgentHub 主工程的 Hook。现在,程序在工具执行前会调用登记好的检查,读完结果,再决定要不要进入 Execute。工具执行之后和模型准备结束时,也都有了对应的处理位置。 我最想弄清楚的是:回调把话说出来以后,主流程究竟有没有照着做。 先给四个时机安排位置Agent 的主循环原本就有顺序:组织消息、请求模型、解析回复、执行工具、回填结果。Hook 是在这些确定的位置,调用外部登记的函数。 这一版接入了四种事件: 事件 触发时机 主流程怎样使用结果 UserPromptSubmit 第一次请求模型之前 将返回的背景追加到消息中,保留原问题;回调报错则结束本次运行 PreToolUse 找到工具后、调用 Execute 前 阻断或检查失败都会跳过工具,并把未执行的原因反馈给模型 PostTool...
关于部分栈问题的求解
栈问题我们可以将其简单抽象为:什么时候进栈,什么时候出栈。虽然听起来有点像把大象装进冰箱分成几步这种垃圾问题,但是的确是我们在求解栈问题时候最先应当考虑的问题。 题目1(有效的括号 leetcode-20)给定一个只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号。 示例12输入:s = "()"输出:true 解题思路这个题,是一道非常经典经典经典的题,从大一做matrix的时候就已经接触到他了,我们按照出入栈的条件思路来考虑他:当匹配到左括号的时候入栈,如果栈顶的左括号和要匹配的右括号是匹配的,那我们就把栈顶的元素弹出来,如果不是,那我们就直接return false了,因为显然(])这一看就无法匹配,而且([)]这显然也不是有效的括号排列。所以就直接获得代码: 代码实现1234567891011121314151617181920212223242526class Solution ...
关于区间问题的解
区间问题看起来和滑动窗口很像,但是我在做本次分享最后一题的时候,相通了一句话,从本质上来说,区间问题就是在求交集/并集的过程,我们只要先把区间分类给划分好,就可以解决大部分的问题了,再搞清楚所解题目到底是求交集还是并集,就迎刃而解了。 题目1(汇总区间 leetcode-228)给定一个 无重复元素 的 有序 整数数组 nums 。 区间 [a,b] 是从 a 到 b(包含)的所有整数的集合。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个区间但不属于 nums 的数字 x 。 列表中的每个区间范围 [a,b] 应该按如下格式输出: “a->b” ,如果 a != b“a” ,如果 a == b 示例12输入:nums = [0,1,2,4,5,7]输出:["0->2","4->5","7"] 解题思路这道题首先可以先套我们刚刚的思路,思考他是求并集还是求交集,那么我们可以简单的看出来,他明显是在求并集的,从示例...
AgentHub 实战手记(四):工具想动手,先把权限问明白
图片缩放能跑起来以后,我又开始琢磨另一个问题:一句“把图片缩放一下”,里面其实藏着好几个动作。 图片可能在允许目录之外,要发送给一个外部服务,保存时还可能覆盖同名文件。任务听起来很简单,真正动手之前,却需要把这些事情分别问清楚。 昨晚新增的独立权限判断,就是在整理这份规则。今天回头看代码,我想把其中的三个角色拆明白:发生了什么、哪些操作已经获批,以及最后应该怎么办。 这一版先完成判断函数 Evaluate。它还没有接入 Agent 的执行循环,下面讲的是已经写出的策略逻辑。 先把事实、授权和决定放在不同的位置如果把所有信息都塞进一个结构体里,写着写着就容易混淆:文件在目录外,是一个事实;允许访问目录外,是一项授权。两者回答的问题不同。 所以这里分成了三个值类型: 123456789101112131415161718type Facts struct { ToolName string TouchesPrivate bool OutsideAllowedArea bool ServiceAllowed boo...
AgentHub 开发手记(一):用 Go 跑通 ReAct 和第一个真实工具
最近我在用 Go 写一个叫 AgentHub 的项目,想把 AI Agent 从概念变成自己能看懂、能运行的程序。 第一阶段的目标很具体:给程序一个自然语言任务,让模型选择工具,程序执行工具,再把结果交回模型,最后得到回答。最开始用 Echo 验证流程,接着把已有的图片处理服务接进来。 这篇记录的是 2026 年 9 月 10 日的开发过程:项目骨架、图片工具注册,以及随后对忽略规则的修正。 先把模型、工具和循环分开项目刚开始时,我把主要代码分成了三部分: 部分 负责什么 模型客户端 把消息发给 GLM,取回模型回复 工具 执行具体操作,比如回显文本、缩放图片 Agent 内核 维护消息历史,解析回复,选择工具并控制循环 这样分的直接好处是,图片处理的细节可以留在图片工具里。Agent 内核只需要知道工具叫什么、能做什么,以及怎么调用它。 工具接口很小: 12345type Tool interface { Name() string Description() string Execute(ctx context.C...
AgentHub 开发手记(二):补上解析测试,让运行过程看得见
上一篇记录了 AgentHub 跑通图片处理的过程。任务能够完成以后,新的问题也出现了:如果结果不对,我怎么知道是哪一步出了问题? 模型回复、解析器、工具和外部服务连在同一条调用链里,只看最终答案,很难定位原因。因此接下来的改动集中在两个地方:让文本解析能应对已知的格式变化,再把每轮调用记录下来。 这篇记录的是 2026 年 9 月 22 日对解析器、运行轨迹和工程计划的完善。 文本协议需要处理实际出现的格式这一版 AgentHub 用 Action、Action Input 和 Final Answer 从模型回复里提取决策。最开始的实现主要针对格式规整的文本。 但标签可能出现不同写法。例如,以下都是用于说明解析行为的样例: 1Action:echo 1**Action**: echo 还有内容放到下一行的情况: 1234Action: echoAction Input:第一行第二行 如果解析器只认最规整的单行格式,这些变化就可能造成工具名没有提取出来,或输入内容丢失。 这次修复的做法很直接:先统一全角冒号,再按行拆分标签和值,清理标签周围的空白和星号;遇到 Action I...
AgentHub 开发手记(三):让回答有依据,补上检索、用量统计与参数校验
前两个阶段,AgentHub 已经能通过模型选择工具,并记录模型和工具的调用过程。接下来,我想让它处理一个更接近业务的问题:根据商店提供的资料回答售后咨询。 这件事把几个问题放到了一起:回答依据从哪里来,每轮请求到底带了多少内容,以及模型给出的工具参数应该怎样检查。 这篇记录的是截至 2026 年 10 月 9 日完成的知识检索、模型用量统计和独立图片参数校验。这里的演示商店政策都是练习用的虚构资料。 先做一条能跟清楚的检索链路我先把演示商店的退货、保修和运费政策写进 Markdown 文档,用二级标题划分片段,再增加 knowledge_search 工具。 工具接受空格分隔的关键词,比如: 1耳机 拆封 退货 当前执行过程是: 检查上下文是否已取消,拒绝空关键词输入。 读取知识文档,按二级标题拆分片段。 将关键词和片段转换为小写,做子串匹配。 一个片段只要命中任意关键词,就加入结果。 返回片段内容,并附上来源文件名。 因此,工具返回给模型的是资料片段,模型再根据这些片段生成回答。 返回格式会包含这样的来源标识: 12来源:after_sales.md## 七天退货 把来...
对于股票问题集合的总结(多状态状态机DP)
这篇文章作为股票问题的集合,篇幅过长,故而不放示例进来,如需查看完整题目,请移步leetcode。 题目1(买卖股票的最佳时机-leetcode-121)给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。 解题思路这道题是问题的开端,这里的最大利润的思想会延续到后面的所有题之中,这里的本意很好理解,就是我们需要找到一个低点和高点,进行买入和卖出,寻求利润的最大点,这里暗藏的条件是:1.同时只能持有一支股票。2.不能在同一天进行买入和卖出。3.买入卖出无手续费。4.买入卖出无冷静期。但就这题而言,我们就可以显然得到一个暴力解:维护两个指针,使用双重循环去找到一个maxProfit=max(maxProfit,price[j]-price[i])。那么我们显然不能使用这个时间复杂度到了O(n^2)的方案了,这样一点都不优雅,我们就思考能不能...
状态机DP无冷却期有交易次数股票问题III
题目给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 示例1234输入:k = 2, prices = [2,4,1]输出:2解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。 解题思路这道题的解决方案实际上承袭了II的思路,只不过有个地方需要考虑,它引入了一个至多交易次数,所以我们只需要再引入一个j作为一个次数的衡量基准就行了,II的题解见状态机DP无冷却期股票问题II,这里我们需要注意的是:每一天都有一个这样的表| 最多允许卖出 j 次 | 不持有 hold = 0 | 持有 hold = 1 ||—-|—-|—-|| j = 0 | memo[i][0][0] | memo[i][0][1] || j = 1 | memo[i][1][0] | memo[i][1][1] || j = 2 | memo[i][2][0] ...
