当前位置:首页 > 编程开发 > 正文

Kimi Hosted Agents 的三个设计,我照着写了一版,发现一个洞

约 4774 字 · 预计阅读 12 分钟
一句话总结:Kimi 发布 Hosted Agents,把 Agent 运行所需的 Harness 做成云服务:7×24 常驻、独立沙箱、可导出审计、140+ Skills,还有推理前的 Inference Hook。我照着做了个最小版本,第一版只靠 Hook 拦截,绕过 Hook 直接调沙箱就读到了另一个会话的文件。补上路径检查之后才真正隔离。

看到「Harness 做成云服务」这句话的时候,我第一反应是:这不就是给 Agent 租了个服务器吗。

往下看细节才发现不止。它解决的是「Agent 一直活着」带来的三个副作用:串味、看不见、停不下。

我用 100 行做了个最小版,过程中撞出一个洞。

一、Hosted Agents 提供的是什么

先把它的清单列清楚。

能力 内容
运行形态7×24 托管,支持长程任务与多智能体协作
扩展140+ Skills、30+ 插件,可接自有工具和数据源
隔离独立沙箱、网络权限控制
控制可随时中止会话并导出审计
拦截Inference Hook,每次推理前按企业规则过一遍
模板首批 8 个金融 Agent
准入目前只对企业认证用户开放

这份清单里有三项是「本地跑 Agent」做不到的:常驻、隔离、审计。

本地跑的时候,这三点都是默认缺失的——进程关了 Agent 就没了,所有会话共享一个工作目录,出了事只能翻自己的终端历史。

二、Harness 上云解决三个问题:常驻、隔离、审计

常驻。 本地跑 Agent 是「叫一次跑一次」。云端托管是它一直在,有消息就处理,没消息就待着。这个差别在长程任务上很致命——一个要跑几小时的任务,本地得开着电脑。

隔离。 这个最容易被低估。本地跑的时候,你同时开两个会话,它们共享一个工作目录。A 会话写了个 output.json,B 会话读到的就是 A 写的。这种串味在调试时还算好,在生产环境会出大问题。

审计。 出了问题要能回溯:谁在什么时候、用什么工具、做了什么、被拦了几次。这些在没有日志的系统里全靠回忆。

所以 Hosted Agents 不是「把 Agent 放到云上」,是「给 Agent 补上它一直缺的三个基础设施」。

三、第一版:只靠 Hook 拦,隔离绕过就破

我按这三个特性写了个最小版,一百行左右。

三个类:Hook 做推理前拦截,Sandbox 做目录隔离,Audit 记 JSONL 日志。

Hook 的规则很直白:

class Hook:
    RULES = {
        "凭证": ["sk-", "BEGIN PRIVATE KEY", "AKIA"],
        "个人身份": ["身份证", "护照号", "银行卡"],
        "越权路径": ["../", "/etc/", "C:\\Windows"],
    }

    def check(self, text):
        for kind, pats in self.RULES.items():
            for p in pats:
                if p in text:
                    return kind, p
        return None

Sandbox 一开始也简单:每个会话一个目录。

def write(self, name, content):
    with open(os.path.join(self.dir, name), "w", encoding="utf-8") as f:
        f.write(content)

def read(self, name):
    p = os.path.join(self.dir, name)
    return open(p, encoding="utf-8").read() if os.path.exists(p) else None

跑起来看着挺好:两个会话各写各的 notes.md,内容不串;带 sk- 和「身份证」的写入都被拦了。

然后我试了一件它没设计的事:绕过 Hook,直接调 Sandbox。

raw = a.read("../chan_beta/notes.md")

结果:

绕过 Hook 直调 Sandbox:'客服模板调研笔记'
-> 目录隔离被打穿了

os.path.join 不做路径规范化,../ 直接穿出去了。

问题在于我把「隔离」这件事交给了 Hook 的规则去管——只要文本里出现 ../ 就拦。但规则是字符串匹配,能拦住的只是「字面上的 ../」。换个写法(..%2f、多级拼接、符号链接)就绕过了。

规则层和隔离层混在一起,等于两层都只有一层。

四、第二版:在 Sandbox 里加真正的隔离检查

修法很直接:在 Sandbox 内部做路径解析和边界检查,不管名字长什么样。

def _resolve(self, name):
    root = os.path.realpath(self.dir)
    target = os.path.realpath(os.path.join(root, name))
    if target != root and not target.startswith(root + os.sep):
        raise PermissionError(f"越界访问:{name}")
    return target

关键是 os.path.realpath——它会把 ..、符号链接、相对路径全部解析成真实的绝对路径,然后再判断这个路径在不在本会话目录下。

再跑一遍:

过 Hook 走一遍:None
绕过 Hook 直调 Sandbox:'<拒绝> 越界访问:../chan_beta/notes.md'
-> 目录隔离挡住了

这次是真挡住了,不依赖 Hook 的规则。

Kimi Hosted Agents 的三个设计,我照着写了一版,发现一个洞

图 1:Hook 管「内容里有没有敏感词」,Sandbox 管「路径出没出圈」,各管一段

五、140 个 Skill 怎么选:检索比列表重要

数量上来之后有个新问题:140 个 Skill,模型怎么知道该用哪个?

全塞进上下文不现实——140 个 Skill 的描述加起来轻松上万 token,还没开始干活就烧掉了。而且中间那些真正相关的会被淹没(这就是上下文压缩那篇讲的分层问题)。

合理的做法是先检索再注入:

  1. 拿当前任务描述去检索
  2. 取 top-k 个 Skill 的描述注入
  3. 模型决定调哪个,再按需加载完整内容

这个「先检索、后加载」的两段式,和 Skill 本身的分层加载是同一个逻辑。 三者配合那篇讲过:描述层常驻、正文层按需、附件层引用。

Hosted Agents 说「140+ Skills、30+ 插件可接入」,真正的工作量不在「接进来」,在「进来之后怎么让它不占地方」。

六、坑清单

1. 隔离不能只靠规则。

这是本文那个洞的根因。规则是字符串匹配,隔离要的是路径解析。前者防「写出来的样子」,后者防「真实的落点」。两件事必须分开做,各在各自的层。

2. 审计日志要记「被拦的」,不只是「发生的」。

我第一版只记成功的操作,blocked 是后补的。实际排查时,被拦的记录比成功的更有用——它告诉你「有人试过什么」。

3. 同名文件是串味的高发区。

两个会话都写 notes.md,如果共享目录,后写的覆盖先写的,而且不报错。这类 bug 在单会话测试里永远发现不了。

4. 中止要能立刻生效。

「可随时中止」这句话,实现上有个细节:正在跑的工具调用要不要等它跑完?我的最小版是同步的,所以「中止」就是抛异常。异步并发的话,得有个取消信号能被每一层检查到,否则「已中止」的会话还在后台写文件。

5. 导出审计的格式要能直接进分析工具。

我用的是 JSONL(一行一条),可以直接 json.loads 逐行读,也能直接喂给 pandas。用嵌套 JSON 数组的话,大文件要整个读进内存才能解析。

七、结语

这次最有价值的不是那个最小版,是撞洞的过程。

我一开始把「安全」当成一个功能——加个 Hook,配几条规则,齐了。实际上安全是分层的:每一层只管自己那一小段,任何一层单独存在都不够。

Hook 管「内容里有没有敏感词」,Sandbox 管「路径出没出圈」,权限管「这个工具能不能调」。三段各管一件事,任何一段被绕过,还有另外两段兜着。

Hosted Agents 那种产品,卖的就是这三段的组合。 自己搭也能搭,但得先知道有哪三段。

参考资料

目录导航
  • 一、Hosted Agents 提供的是什么
  • 二、Harness 上云解决三个问题:常驻、隔离、审计
  • 三、第一版:只靠 Hook 拦,隔离绕过就破
  • 四、第二版:在 Sandbox 里加真正的隔离检查
  • 五、140 个 Skill 怎么选:检索比列表重要
  • 六、坑清单
  • 七、结语
    • 参考资料
  • 相关文章:

  • 照着 HExA 写个最小版:加 20% 探索,收敛反而慢了一倍多
  • Agent 的命令执行靠不靠谱:我用 20 条命令测了一次
  • 同一个模型自问自答有用吗:写代码测 Role-Agent 的收益
  • PenguinHarness:把 Agent 拆成文件,我写了个最小版
  • 跨任务保持上下文:和 message threads 不是一回事
  • Computer Use 的通过率怎么算:三层条件,一个判定器
  • 上下文压缩三种策略实测:省到 100 token,就得接受会漏
  • 腾讯混元 Hyra 2.0:三层 Agent 做科研,从解题变成造工具
  • 发表评论

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。