让 AI 主动“找人帮忙”:从 humanlayer/skills 看下一代 Agent 工作流 🛠️
当 Agent “卡壳”时,它在想什么?
先设想一个场景:你部署了一个智能客服 Agent,它负责自动处理用户退换货请求。某天订单数据库延迟,Agent 拉取不到用户的订单号。传统架构下,Agent 会抛出异常,然后客服工单系统里出现一条谁也看不明白的报错日志。
更令人窒息的是:如果你告诉 Agent “当 API 失败时,发邮件给仓库负责人”。Agent 真会这么做吗?它大概率会因为“找不到收件人地址”或者“API 返回 500”而你又在提示词里加了“不要放弃请求”,于是它就开启了自我脑补循环——连续调用 10 次 API,或者告诉你“用户不存在”。
核心问题在于:我们给予 Agent 的工具,全是冷冰冰的 API 通道(读文件、写数据库、调接口),唯独缺少了“人类交互”这条通道。
humanlayer/skills 就是为此而生的。它并不是让你编写一个“找人前先写请示邮件”的慢速流程,而是提供一组可复用的“技能(Skills)预置包”,让你用声明式的方式定义:“这个节点,需要走人工审批”、“那个动作,请直接给某人发 Slack”。它把 Agent 从“孤军奋战”的代码循环里拯救出来,赋予它们“开口询问”的能力。
拆开看:一个“技能包”里到底藏了什么?
我们知道 OpenAPI Schema 定义了 API 接口,LangChain 用了 @tool 装饰器纯函数式定义工具,而 humanlayer/skills 的项目结构更像是一册“技能标准指南”。它不依赖特定的 LLM 厂商,而是尝试框定一套“让 Agent 能和人类双向沟通”的协议。
在移动端、邮件、聊天工具爆炸的时代,Agent 的技能应当被赋予“多栖属性”。在仓库中你往往会看到类似于这样的定义:
from humanlayer import HumanLayer
from skills.slack import notify, request_approval
hl = HumanLayer(
api_key="hl_...",
# 下面两条路径便是在“人-机回环”里节省时间的关键
contacts={
"oncall": lambda ctx: [ctx.slack_user("U04XXX"), ctx.whatsapp("+861390...")]
},
)
def notify_incident(payload: dict) -> str:
"""只有当严重级别为 critical 时,才直接轰炸负责人手机"""
if payload["severity"] == "critical":
# 异步等待模式:这里的“等待”,会让 Agent 从 API 循环中暂时脱离
approval = hl.request_human_approval(
contact_channel="oncall",
message=f"⚠️ 系统故障 {payload['message']},是否执行回滚?"
)
if not approval.approved:
return "用户拒绝了操作,尝试改用备份策略..."
return "绕过人工审批,已直接处理(低风险)"
看明白了吗?这里面有两个很微妙的设计:第一,它允许工具定义里携带“人”作为另一个 API 端点——只不过这个端点的延迟阈值是“人类可接受范围”(比如 5 分钟到 24 小时)。第二,它把“审批”设计成一种待办资源的 state-machine,只有当用户点击鼠标表态后,那个 await 才会释放。
这是革命性的思路转变:你不必再为 Agent 写死 if user_ops == "admin" 的判断逻辑,技能包能直接帮你“拉微信专属群聊”,甚至实现“超过 10 分钟未响应,自动 SMS 二次唤醒”。这就叫 Escalation Skill(升级技能)。
为什么对开发者/团队有致命吸引力?
很多人觉得:“这不就是一个把 AI 接入 Slack 通知的封装吗?我自己也能写。” 但拆分来看,它解决了两个日常开发中被无限低估的场景:
- 契约即文档(Contract as handler):Agent 的 Tool 若运行在 Serverless 环境,一旦遇阻就得冷启动重启整个会话。Skills 提供了一种持久化的离线交接机制。任务卡住时,Agent 可以“假死退场”,把状态交付给另一个通道里的真人处理。你能想象这种代码给运维机器人带来的安全感吗?
- 回调函数的不只是 LLM 调用:以前的函数调用是一锤子买卖。这里提供了“询问-等待-响应”的完整生命周期。比如在自动代码评审技能里,如果小助手发现 PR 中出现了密钥泄露,它可以选择直接静默修复,也可以选择只发送高亮告警,一边等待开发手动 patch。
我们放大视角来看,这套思路本质上是在改造 RPA(机器人流程自动化)的“最后 5% 的异常处理”——跳过规则引擎,直接交给上下文理解能力更强、情绪安抚能力更佳的“人类”来处理。
5 分钟快速上手:让人列为你“兜底”
假设你想给 AI 增加“需要时让同事帮我跑一遍 SQL 验证”的技能包,你不需要整晚加班调 ChatGPT 的 JSON Mode。基础玩法如下:
# 安装 HumanLayer 核心与内置 Skills(概念示意)
pip install humanlayer
git clone https://github.com/humanlayer/skills
cd skills
export HUMANLAYER_API_KEY="hola-demo"
接着,初始化一个触发器连接。这里的哲学是你“开着 WebSocket 挂服务”,本质上是给 Agent 一双始终能听到人类指令的耳朵:
# agent_talking_to_human.py
import humanlayer
from skills.sql_validator import DatabaseValidator
llm = YourGPTApp()
# 核心逻辑:不直接执行高风险行为,经由 human-in-the-loop 传达
db = DatabaseValidator(timeout="60s")
def run_context():
query_plan = llm.understand("帮我把上海客户的预付款清零,别查漏了")
# 人类确认入口:让远程值班人 review
confirmed = humanlayer.human_confirm(
contact=["slack: #data-ops"],
prompt=f"Agent 拟执行: {query_plan}"
)
# 人类一旦回复“跑了跑了我确认没问题”,此函数便会立刻因事件驱动而恢复执行
if confirmed:
result = db.ok_to_execute(query_plan, bypass_checks_for_env=true)
humanlayer.notify("✅ 已通知数据运维执行计划")
return "定时任务已挂载——一切在人力监督下完成。"
当你启动该 Agent 时,它面对从未见过的数据表不会清空;遇到权限边缘时,它会直接抛一个“打断”处理:将 Slack 频道里相关同事 @提到。此时人类并不是在繁琐地写 SQL 去教 Agent,而是做最后的点头或摇手。
场景总结与扩展思考:AI 的“礼貌”值得刻意设计 💡
纵观 humanlayer/skills,它传递出一种信号:一个好的 AI Agent 交互,不是“永不打扰人”,而恰是“在正确的时机,打扰正确的人”。这套技能不是为减少交互而存在,而是为让每一次交互都拥有“决策切面”的价值。
你可以把这种模式无缝迁移到企业内部审批流、开发者运维平台,甚至用在你独自 side-project 的脚本自动化上——让它变成你的“自动化副驾驶”,遇到长尾问题直接传呼机联系你(别等了,直接问)。
开发者的未来操作系统也许将是这样:所有 Agent 必须配备一个“Human Contact Handle”地址。当它们遇到语义歧义或敏感操作时,不再吐出乱码,而是主动闪现一句:“请求人员介入审批,请于 24h 内回应。” 就像
404 Not Found页面不仅仅是错误码,而是一个漂亮的“重试 + 提工单”入口,Agent 的 API 设计也一样。
下一次你再感叹 LLM 的上下文长度不够,不妨换个思路:如果你把“请教同事”这件事本身定义为一种 API,你的工作流就永远不会真的死锁。快去后台 fork 一版,试着把一个简单的 AI 自动回复器升级成会“敲人 Slack 私聊窗口”的带情绪有温度的 Agent 吧。🔥