Skip to content

Repository files navigation

Knuth Agent Framework

Knuth 是一个本地优先的 Agent 运行时框架。

它不是只给 LLM 包一层 CLI。Knuth 更关心的是:一次 agent 运行过程中,模型看到了什么、工具为什么会被调用、审批卡在哪一步出现、进程中断后应该从哪里继续。这些信息都应该能被记录、恢复和解释。

如果只想做一个简单聊天入口,Knuth 可能显得有点重。它适合那些需要工具调用、人工审批、运行历史、Web/CLI 多端入口,甚至以后要做回放和调试的 agent 系统。

最大特点

1. 运行历史是事件,不是临时状态

Knuth 把一次运行写成一串事件:用户消息、模型输出、工具调用、审批、工具结果、运行结束等。当前状态只是从这些事件算出来的。

这样做的好处很直接:

  • crash 后可以知道运行停在哪;
  • 审批通过后执行的是当时冻结的那个工具调用,不是重新让模型猜一次;
  • 派生状态坏了可以用 knuth admin refold 从事件重建;
  • 调试时能看到完整 timeline。

2. 模型流和运行时事件分开

LLM streaming 里的 delta、reasoning、tool call chunk 属于 InferenceEvent。这些是模型边界的低层事件。

Runtime 关心的是另一层:run 创建了、模型完成了、工具等待审批、工具执行结束、run 被中断了。这些是 RuntimeEvent

这两层分开后,CLI、Web UI、日志和恢复逻辑不用直接依赖某个 provider 的流格式。

3. 工具调用可审批、可恢复

模型发起 tool call 后,Knuth 不会把它当成一段马上执行完的临时代码。Runtime 会先记录工具批次,再交给 ToolBroker 做参数校验和策略判断。

默认策略很保守:受信内置读工具可以直接跑;写文件、shell、python 需要审批;没有宿主可信规则的动态/client tool 即使自报低风险也默认请求审批。

如果进程在外部写操作中间挂了,Knuth 不会自动重试。它会把结果标成 unknown,让人确认到底发生了什么。

4. 中断不是暂停

这里有个刻意的区别:

  • pause 是“这件事以后还能接着做”;
  • interrupt 是“当前这次尝试被用户停掉了,不要偷偷重放”;
  • continue_run 是用户又说了一句话,开启下一轮。

这个区别对 agent 很重要。否则 Ctrl+C、审批退出、工具等待、真正的 crash 很容易混在一起。

5. 大输出不塞进上下文

shell 输出太长时,Knuth 会把完整 stdout / stderr 存到本地 artifact 文件里,只把摘要和路径放进模型上下文。模型需要细看时,可以再用文件工具去查。

这比简单截断更可靠,也不会把 ledger 变成一个大 blob 仓库。secret 也会在写入事件和 artifact 前做默认脱敏。

6. 包边界比较清楚

现在所有东西还是 in-process,但包已经按边界拆开:core、LLM、tool、runtime、CLI、AG-UI、IM host。以后某一层要换成服务进程,不需要重写整个项目。

7. 动态 Workflow 不绕过运行时

Knuth IM 支持经过显式审批的 JavaScript Workflow。脚本可以用稳定 call_key 并发调用多个 Agent,但不能直接访问文件、shell、网络或环境变量;这些能力仍由 child Run 的普通工具和 审批获得。Workflow Agent、结果和停止/暂停行为都复用现有 Run、ledger 与 policy,而不是 另建一套不可观察的执行器。

包结构

.
├── packages/
│   ├── knuth-core/      # 共享模型:消息、事件、run、工具、审批、artifact、skills
│   ├── knuth-llmd/      # LLM client 协议和 LiteLLM 适配
│   ├── knuth-toold/     # 工具协议、注册、执行、内置工具
│   ├── knuth-runtime/   # agent loop、ledger、上下文、审批、恢复
│   ├── knuth-cli/       # 命令行入口和 CLI 本地工具
│   ├── knuth-agui/      # AG-UI / FastAPI / SSE 适配层
│   └── knuth-im/        # Web/IM host,负责装配 runtime
├── apps/
│   └── knuth-im-web/    # Next.js + Electron UI
├── docs/                # 设计文档和 ADR
├── tests/               # 测试
├── AGENTS.md            # 仓库内 agent 工作约定
└── pyproject.toml       # uv workspace 配置

核心包的分工:

Import 作用
knuth-core knuth.core 消息、事件、run、工具等共享数据模型。
knuth-llmd knuth_llmd LLM client 协议,以及基于 LiteLLM 的实现。
knuth-toold knuth_toold 工具 manifest、registry、broker、内置工具和 skill 工具化。
knuth-runtime knuth_runtime 编排 LLM、工具、ledger、审批、恢复和上下文。
knuth-cli knuth_cli knuth 命令行入口。
knuth-agui knuth_agui 把已有 AgentRuntime 暴露成 AG-UI 服务。
knuth-im knuth_im 装配 Web/IM 场景需要的 runtime,并启动后端。

开发者先读 当前架构领域词汇;需要了解设计原因时, 通过 ADR 索引 选择相关决策,不必遍历全部历史文档。

安装与配置

Knuth 使用 uv,Python 版本要求 >=3.12

uv sync --dev

最小配置可以写在仓库根目录的 .env

KNUTH_MODEL=gpt-4.1
KNUTH_BASE_URL=https://api.openai.com/v1
KNUTH_API_KEY=...

也可以放到用户配置文件里:

~/Library/Application Support/knuth/knuth-cli/knuth.yaml   # macOS 常见位置

常用环境变量:

环境变量 说明
KNUTH_MODEL 模型名。没有 provider 前缀时默认按 openai/<model> 处理。
KNUTH_BASE_URL OpenAI-compatible API 地址。
KNUTH_API_KEY API key。
KNUTH_TIMEOUT 模型请求超时,默认 60 秒。
KNUTH_SYSTEM_PROMPT 额外 system prompt。
KNUTH_AUTH_MODE api_keychatgpt
KNUTH_CHATGPT_TOKEN_DIR ChatGPT token 目录。
KNUTH_SKILL_ROOTS skill 目录,多个路径用系统 path separator 分隔。
KNUTH_SKILL_HOT_RELOAD 是否热加载 skills。
KNUTH_LITELLM_CALLBACKS LiteLLM callbacks,例如 Langfuse。

使用 Langfuse v3 时,把 KNUTH_LITELLM_CALLBACKS=langfuse_otel 与 Langfuse 的 public key、secret key、host 一起放入环境或根目录 .env。未显式配置 callback 时默认不 向外部观测服务发送模型输入输出。

CLI 使用

一次性运行:

uv run knuth run "总结这个仓库"

附加图片输入,可重复使用 --image

uv run knuth run --image screenshot.png "分析这个界面"

进入交互模式:

uv run knuth run

显式开启 Auto Mode;当前工作目录就是 workspace,只自动批准该目录内的 write_file/edit_file,其他工具和目录外写入仍需人工审批:

uv run knuth --permission-mode auto run

交互模式里可以直接输入问题,也可以用 slash command:/help/tools/resume/status/usage/pending/interrupt/exit

常用命令:

# 最近的 runs
uv run knuth runs --limit 20

# 当前可用工具
uv run knuth tools list

# 查看状态和事件
uv run knuth status <run_id>
uv run knuth events <run_id>

# 恢复 paused / waiting 状态
uv run knuth resume <run_id>

# 处理工具审批
uv run knuth approvals --run-id <run_id>
uv run knuth approve <approval_id>
uv run knuth deny <approval_id>

# crash 后恢复运行中状态
uv run knuth recover [run_id]

# 人工确认 unknown 的外部写结果
uv run knuth resolve <tool_call_id> --outcome succeeded --note "confirmed manually"

# 从事件日志重建投影
uv run knuth admin refold

调试时可以打开完整事件日志:

uv run knuth --debug run "..."

日志会写到:

~/.knuth/debug/<run_id>.jsonl

默认工具

CLI / IM 默认会注册这些工具:

工具 说明
read_file 读取文本文件。
write_file 写文件。默认需要审批;Auto Mode 下工作区内自动批准。
edit_file 精确字符串替换。默认需要审批;Auto Mode 下工作区内自动批准。
glob 按 glob 找文件。
grep 用 ripgrep 搜索内容。
rlm_capture 把当前 run 最近一条真实用户消息保存为有界 RLM artifact。
rlm_query 对当前 run 的 RLM artifact 做有界 slice 或 literal search。
skill 加载当前轮可用的动态或内置 skill;默认包含 rlm
shell 运行 shell 命令。需要审批。
python 运行 Python 片段。需要审批。

路径按普通 OS 语义处理:绝对路径就是绝对路径,相对路径相对于当前进程工作目录。访问控制放在 policy 层,而不是工具里偷偷改路径。

当前只有 rlm_query 参与 pure tool cache。cache key 同时绑定工具 revision、参数、run、 artifact SHA-256 和 policy digest;命中仍会产生普通 durable tool completion。删除或损坏 cache 只会造成 miss,不影响历史恢复,也不用于缓存写操作。

Web / AG-UI / IM

knuth-agui 是协议适配层。它接收一个已经构造好的 AgentRuntime,把 runtime events 翻译成 AG-UI 事件,通过 FastAPI / SSE 给前端使用。它不负责选模型、选工具或写 prompt。

history 与 live tail 使用同一个固定-watermark cursor feed:先 attach,再分页 replay,最后去重 tail。浏览器 subscriber 非阻塞;队列溢出只重连该连接,不拖慢 agent。IM 切回正在运行的 会话时使用 observation-only attach,不会误 resume 或改变当前工具目录。

knuth-im 是一个现成 host,可以直接启动:

uv run knuth-im

常用参数:

uv run knuth-im \
  --host 127.0.0.1 \
  --port 8000 \
  --db-path ~/.knuth/knuth-im.db \
  --workspace /path/to/workspace \
  --auth-token "$KNUTH_IM_AUTH_TOKEN"

对应环境变量:

参数 环境变量 默认值
--host KNUTH_IM_HOST 127.0.0.1
--port KNUTH_IM_PORT 8000
--db-path KNUTH_IM_DB_PATH ~/.knuth/knuth-im.db
--workspace KNUTH_IM_WORKSPACE 当前目录
--auth-token KNUTH_IM_AUTH_TOKEN
--env-file KNUTH_IM_ENV_FILE .env

前端在 apps/knuth-im-web

# 后端
uv run knuth-im

# 前端
cd apps/knuth-im-web
npm install
npm run dev

默认连接 http://127.0.0.1:8000。需要改地址时设置 NEXT_PUBLIC_KNUTH_AGUI_URL

Electron 开发入口:

cd apps/knuth-im-web
npm run electron:dev

在代码里使用 Runtime

最小例子:

from knuth_llmd import InferenceConfig, LiteLLMInferenceClient
from knuth_runtime import build_sqlite_runtime

runtime = build_sqlite_runtime(
    inference_client=LiteLLMInferenceClient(
        model="gpt-4.1",
        base_url="https://api.openai.com/v1",
        api_key="...",
    ),
    inference_config=InferenceConfig(timeout_s=60),
)

result = await runtime.run_once("总结这个项目")
print(result.answer)

需要多轮控制时,用 startcontinue_runresume

async with runtime.start("读取 README 并总结") as session:
    result = await session.result()

async with runtime.continue_run(result.run_id, "再短一点") as session:
    result = await session.result()

测试里可以用 build_memory_runtime(...)。本地长期运行建议用 build_sqlite_runtime(...)

Skills

Knuth 可以把本地 skill 暴露成一个工具。默认搜索这两个目录:

<project>/.knuth/skills
~/.agents/skills

每个 skill 是一个目录,里面放 SKILL.md。目录名需要和 skill 名一致。Runtime 会读取这些 skills,并把 catalog 提供给模型。 CLI 与 AG-UI host 会在整个进程生命周期内启动一次 skill watcher;自行嵌入 runtime 的长期 运行 host 应使用 async with runtime.host_lifespan(): 包住服务主循环。

相关配置:

KNUTH_SKILL_ROOTS="/path/to/project-skills:/path/to/user-skills"
KNUTH_SKILL_HOT_RELOAD=true
KNUTH_SKILL_HOT_RELOAD_DEBOUNCE_MS=1000

开发

这个仓库是 uv workspace。运行 Python 命令时尽量用 uv run

# 安装开发依赖
uv sync --dev

# 全部测试
uv run python -m unittest discover tests

# 常用单测
uv run python -m unittest tests.test_runtime
uv run python -m unittest tests.test_cli
uv run python -m unittest tests.test_agui_spike

调试脚本:

uv run python scripts/runtime_event_tui.py
uv run python scripts/llmd_event_probe.py
uv run python scripts/llmd_event_tui.py

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages