2026年6月30日 2 分钟阅读

LLayer 实战教程:用 bash、curl 和 jq 构建 Unix 哲学驱动的 AI Agent

tinyash 0 条评论

AI Agent 框架层出不穷,从 LangChain 到 CrewAI,每个都有大量抽象概念、复杂的类继承关系和繁重的依赖管理。但有没有一种更轻量、更透明的方式?

LLayer 给出了一个反直觉的答案:用 bash、curl 和 jq 三个最基础的 Unix 工具,就能构建一个完整的 AI Agent。这个 MIT 开源项目只有 6041 字符的 README 文档,却完整覆盖了状态管理、上下文构建、工具调度和流式输出等 Agent 核心能力。

为什么需要 Unix 风格的 AI Agent?

现有的 Agent 框架有几个共性问题:

  • 状态沉重:内部维护复杂的类继承链和回调机制,调试困难
  • 抽象过厚:要理解完整的数据流,需要阅读数百行框架源码
  • 难以组合:很难将 Agent 的中间输出管道到其他工具做分析或过滤

LLayer 将 Agent 生命周期解构为四个独立的 shell 命令——ll-readll-contextll-evalll-print——通过标准 Unix 管道组合成完整的 REPL 循环。每个命令只做一件事,且做好。

快速上手

需要 Docker 和 Ollama,启动只需两行:

git clone https://github.com/cloudkj/llayer.git
cd llayer
docker compose up --detach
./agent

等待 Ollama 启动后,./agent 就会打开一个 REPL 终端:

> 你好,今天有什么新鲜事?
今天天气不错!有什么我可以帮你的吗?

这个 REPL 的背后,实际上是以下管道链在运行:

用户输入 → ll-read(写入历史) → ll-context(构建上下文) 
→ ll-eval(调用模型) → ll-print(展示输出)

四步管道架构拆解

LLayer 的架构极其透明。你可以独立调用每一个组件:

无状态单次调用(跳过历史记录):

echo "Hello, world" | ./ll-read | ./ll-context | ./ll-eval | ./ll-print

这条命令等价于一次完整的 Agent 交互,但没有状态持久化。每个组件的作用:

组件功能输出
ll-read将输入写入 .jsonl 历史文件触发事件
ll-context从历史文件构建模型上下文JSON 格式的上下文
ll-eval调用 Ollama API 获取响应令牌流
ll-print格式化输出到终端人类可读的消息

有状态的完整 Agent

./agent

agent 脚本将上述四个组件组合成一个 while 循环,并加入工具调度(ll-dispatch)步骤:

  1. ll-read 读取用户输入,追加为事件到 .llayer_history 文件
  2. ll-context 从历史文件中压缩出当前轮次的模型上下文
  3. ll-eval 调用本地 Ollama 模型,获取回复
  4. 如果需要工具调用,ll-dispatch 分发到对应工具,将结果追加到历史,回到步骤 2
  5. 模型输出完成后,ll-print 展示给用户

亮点功能

1. 时光回溯式调试

因为所有状态都是只追加的 .jsonl 文件,调试变得异常简单:

head -n 20 .llayer_history

cp .llayer_history .llayer_history.bak
head -n 10 .llayer_history > .llayer_history.tmp
mv .llayer_history.tmp .llayer_history
./agent

这在排查 Agent 的「幻觉循环」时极其有效——你可以在历史中逐条检查每个工具调用的输入输出,找到问题点后切片回退。

2. 管道威力:拦截和改造 Agent 流

因为所有组件都是标准 Unix 管道,你可以做很多框架中难以实现的事情:

pv 监控 Token 流速度

echo "写一篇关于 AI Agent 的文章" | ./ll-read | ./ll-context | ./ll-eval | pv --line-mode | sponge | ./ll-print

pv --line-mode 实时显示行数、速率和总数据量,sponge 缓冲全部输出后才交给 ll-print——这在基准测试 Token 流速度时非常有用。

用 grep 过滤 PII 数据

echo "我的邮箱是 test@example.com" | ./ll-read | ./ll-context | ./ll-eval | grep -v -E '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b' | ./ll-print

在模型输出到达用户之前,通过 grep 过滤掉潜在的个人信息——不需要框架级别的插件机制。

3. 通过管道注入系统提示词

(echo "你是一个名叫 Mario 的意大利水管工,用 Brooklyn 口音回答" | ./ll-read --system > .llayer_history) && ./agent

--system 标志将输入标记为系统消息,ll-context 会将其作为首条上下文传递给模型。

与框架化 Agent 的对比

维度LLayer传统框架(LangChain/CrewAI)
依赖bash + curl + jq + Ollama数百 MB 的 Python 包
状态模型追加 JSONL 文件内存对象 + 序列化
调试cat 历史文件即可需框架专门的调试 UI
组合性标准 Unix 管道框架内部 API
学习曲线熟悉 Unix 即可需学习整套抽象概念

最佳实践

  1. 在隔离环境中运行:LLayer 通过 docker-compose 启动 Ollama,模型运行在容器中,但 Agent 逻辑在宿主机。建议在开发容器或 CI runner 中使用
  1. sponge 缓冲流式输出:直接管道的 ll-eval 输出是逐 Token 的,用 spongemoreutils 包)缓冲后再处理可避免半截 Token 的解析错误
  1. 历史文件管理:长期运行的 Agent 会产生很大的 .llayer_history。定期用 ll-context 的压缩能力重建上下文,或设置 cron 定时清理旧事件
  1. 工具扩展:添加自定义工具只需写一个 bash 函数,标准输出直接变为 Agent 的输入——没有框架接口需要实现
weather() {
    curl -s "https://wttr.in/$1?format=%C+%t" | head -c 200
}

然后在 ll-dispatch 的 tool 列表中注册函数名即可。

总结

LLayer 不是要取代 LangChain 或 CrewAI——在生产级应用中,框架的抽象层是必要的。但对于理解 Agent 本质、快速原型验证、以及在资源受限环境中运行 Agent 来说,Unix 管道的方法提供了一种极有价值的补充视角。

当你下次遇到 Agent 行为不符合预期时,不妨想想 LLayer 的哲学:拆解到最小单元,用管道连接,用文本文件做状态——一切都可以 catgrep,没有什么不可见。


相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。