Skip to content

LB623/OmniClaw

Repository files navigation

🦞 OmniClaw

基于手写 Agent Loop 的本地单智能体 AI 工作台
让大模型在可控边界内使用文件、命令、长期记忆、动态技能与定时任务

项目定位 · 快速开始 · 系统架构 · 记忆与上下文 · 安全体系 · 技能扩展

Python 3.11+ Manual Agent Loop Terminal Interface SQLite Policy Guard 242 tests passed

🎯 项目定位

OmniClaw 是一个终端原生的本地 AI Agent 运行框架。系统采用标准的 agent -> tools -> agent 循环:由一个 LLM Agent 负责理解请求、选择工具并完成多步任务, 确定性的运行时组件负责权限、路径、命令、持久化和审计。

它不是把模型直接接入 Shell 的聊天封装,而是围绕本地 Agent 的长期运行补齐以下工程能力:

  • 单智能体工具循环:减少路由调用、状态分叉和多 Agent 协作开销。
  • 分层记忆:近期完整轮次、增量摘要、长期用户画像各自承担不同职责。
  • 确定性安全边界:高风险意图、命令策略、路径校验和执行后端逐层拦截。
  • 持久化运行:SQLite state store、定时任务、线程切换和进程状态可以跨会话保留。
  • 动态技能:只注册技能元数据,使用时再加载完整说明和结构化清单。
  • 可观测性:模型输入、工具调用、工具结果和生命周期事件写入 JSONL 审计日志。

Important

OmniClaw 仍处于积极开发阶段。默认 Shell 策略优先保证可控性,不支持管道、重定向、 通配符、解释器包装,以及未经审批的删除、覆盖和远程 Git 操作。

🔍 白盒化 Agent 运行时

OmniClaw 不试图解释 LLM 的内部推理过程,而是把模型外部的执行行为纳入确定性的本地运行时管理。

模型负责理解任务和选择工具;文件、命令、网络、记忆、上下文、定时任务和审计日志则由可测试的 本地组件负责执行、约束和记录。

这使系统具备清晰的工程边界:

  • 可观测:每次模型输入、工具调用、工具结果和生命周期事件写入 JSONL 审计日志。
  • 可测试:Agent loop、工具策略、路径沙盒、上下文裁剪和任务调度都有单元测试覆盖。
  • 可回滚:取消或异常时回滚当前轮次新增消息,避免污染后续上下文。
  • 可控:高风险命令、路径越界、SSRF 和工具调用超预算由确定性策略拦截。

简言之,LLM 推理本身仍是黑盒,但 OmniClaw 将 Agent 运行时做成白盒。

✨ 核心能力

能力 当前实现
Agent 运行时 手写单智能体 agent <-> tools 循环
白盒治理 模型外部行为可观测、可测试、可回滚、可审计
本地文件 限定在 workspace/office/,支持读取、写入、目录浏览和写前备份
命令执行 静态策略分级,shell=False,参数数组执行
网络读取 仅允许公网 HTTPS 文本,阻断本机、内网和保留地址
上下文管理 Token Budget、完整轮次裁剪、增量摘要、超大结果转存
长期记忆 独立用户画像文件与 SQLite 对话状态
定时任务 单次、每小时、每天和每周任务,SQLite 事务存储
技能系统 Markdown 元数据懒加载与 skill.json 结构化执行
运行控制 异步模型/工具调用、超时、取消、异常轮次回滚
审计监控 JSONL 事件日志与独立终端 Monitor

🚀 快速开始

环境要求

  • Python 3.11+
  • macOS 或 Linux
  • 至少一个可用的模型 API Key,或本地 Ollama 服务

安装

git clone https://github.com/your-account/OmniClaw.git
cd OmniClaw

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .

Anthropic 和 Ollama 使用可选 Provider 依赖:

python -m pip install langchain-anthropic
#
python -m pip install langchain-community

配置模型

推荐使用交互式配置向导:

omniclaw config

向导会选择 Provider、模型、API Key 和 Base URL,并在写入 .env 前测试连接。 也可以手动创建配置:

cp .env.example .env

OpenAI 兼容接口示例:

DEFAULT_PROVIDER=deepseek
DEFAULT_MODEL=deepseek-chat
OPENAI_API_KEY=your-api-key

支持 OpenAI、DeepSeek、阿里云、MiniMax、Moonshot、SiliconFlow、腾讯混元、智谱、 Anthropic、Ollama 以及自定义 OpenAI 兼容服务。

启动

omniclaw run

OmniClaw 终端主界面
终端原生异步 REPL,启动时展示当前 Provider 与模型

常用 REPL 命令:

命令 作用
/help 查看快捷命令
/clear 清空终端显示,不删除持久化状态
/new 创建新对话线程,继续共享画像、文件和定时任务
/cancel 取消当前模型或工具执行;流式输出期间可按 Ctrl+C
/token-budget 查看当前上下文 Token 预算
/token-budget <正整数|reset> 修改后续轮次预算,或恢复启动配置
/exit 退出当前会话
Esc + Enter 输入换行

/token-budget 修改的是发送给模型的历史消息预算,不等于模型的完整上下文窗口。 设置在当前进程内生效并跨 /new 保留;重启后重新读取 OMNICLAW_CONTEXT_TOKEN_BUDGET。运行时还会根据模型总窗口扣除系统提示词、 工具 schema、输出预留和安全余量;总窗口由 OMNICLAW_MODEL_CONTEXT_WINDOW 配置。

在另一个终端查看实时审计事件:

omniclaw monitor

Monitor 会区分“日志可读取”和“主程序在线”。即使进程被强制终止,也会通过 PID 存活性检查避免将旧日志误判为运行中实例。

🏗️ 系统架构

OmniClaw 当前只有一个负责推理的 Agent 节点。工具、记忆、安全和持久化都是该 Agent 之外的确定性运行时组件。

flowchart LR
    U["终端 REPL"] --> Q["异步输入队列"]
    Q --> A["手写 Agent Loop"]
    A -->|"调用工具"| T["ToolExecutor"]
    T --> A
    A -->|"最终回复"| U

    A --- C["上下文管理"]
    A --- P["用户画像"]
    A --- S["SQLite State Store"]
    T --- F["文件与命令工具"]
    T --- H["定时任务"]
    T --- K["动态技能"]
    A --- L["JSONL 审计日志"]
Loading

一次完整请求的执行过程:

  1. REPL 将用户输入写入异步队列,AgentSession 创建本轮运行任务。
  2. Agent 先处理内部提醒事件、高风险批量删除意图和上下文预算。
  3. 模型从 13 个默认工具、动态技能和调用方自定义工具中选择能力。
  4. 手写 ToolExecutor 在执行前完成预算、重复抓取和安全拦截,再返回工具结果。
  5. 无工具调用时输出最终回复,消息与摘要由 SQLite state store 持久化。
  6. 取消或异常时回滚本轮新增消息,避免污染后续会话状态。

选择单智能体架构的原因:

  • 减少额外的路由模型调用、首包延迟和 Token 成本。
  • 避免路由 JSON 不稳定导致任务进入错误 Worker。
  • 所有工具只需在一个注册表中维护。
  • 自定义工具能够直接进入模型的 bind_tools
  • 手写 loop 让工具执行前审批、预算治理、取消和状态恢复更容易验证。

详细设计见 当前系统架构

🧠 记忆与上下文

OmniClaw 不把所有历史消息无限塞入模型,也不直接按消息数量粗暴截断。系统将记忆拆成 “近期对话、任务摘要、长期画像、持久化状态、外部产物”五类。

flowchart LR
    H["完整历史消息"] --> B{"超过 Token Budget?"}
    B -->|"否"| R["保留完整轮次"]
    B -->|"是"| K["最近完整轮次"]
    B -->|"是"| O["较早完整轮次"]
    O --> S["增量融合摘要"]
    K --> N["下一次模型输入"]
    S --> N
    P["长期用户画像"] --> N
    D["SQLite State Store"] <--> H
    X["超大工具结果"] --> F["Artifact 文件"]
    F --> N
Loading
层级 作用
近期完整轮次 保留最近的 HumanMessage -> AIMessage -> ToolMessage 链,不拆散工具调用
增量摘要 将较早任务、已完成步骤、关键决策和下一步动作融合进现有摘要
用户画像 保存稳定偏好和背景信息,不与短期任务摘要混在一起
SQLite state store 保存消息、摘要和线程状态,进程重启后可以恢复
Artifact 工具结果超过默认 6,000 字符时保存完整原文,上下文只保留预览和路径

默认上下文预算为 12,000 Token。优先使用 tiktoken 估算;不可用时回退到字符启发式。 摘要模型失败时会使用最近消息生成规则化降级摘要,主对话不会因此中断。

OmniClaw 自动更新上下文摘要
达到预算阈值后压缩较早轮次,并保留当前任务所需信息

🛡️ 安全体系

安全判断不依赖模型“自觉”。OmniClaw 在模型前、工具前、路径解析和进程执行位置设置 确定性防线。

flowchart LR
    U["用户请求"] --> I["意图前置检查"]
    I -->|"批量破坏请求"| X["拒绝"]
    I --> A["模型选择工具"]
    A --> C["命令策略"]
    C -->|"DENY"| X
    C -->|"REQUIRE_CONFIRM"| X
    C -->|"ALLOW"| P["路径与链接校验"]
    P -->|"越出工作区"| X
    P --> E["受限执行后端"]
    E --> O["工具结果"]
    O --> L["JSONL 审计"]
Loading

1. 🚫 Agent 前置保护

  • 模型调用前拒绝“删除全部文件”“清空工作区”等批量破坏请求。
  • 用户随后回复“确认”“继续”也不能创建审批凭证。
  • 同一工具和参数连续失败 3 次后停止重试。
  • 模型或工具异常时回滚当前轮次新增消息。

2. 🚦 命令策略

命令被划分为三个风险等级:

等级 行为 示例
ALLOW 允许进入执行后端 pwdlsmkdir
REQUIRE_CONFIRM 当前版本阻断 rm file.txtmv、Git 清理
DENY 永久拒绝 sudorm -rf .、解释器命令、git push --force

策略同时拒绝管道、重定向、变量展开、通配符、命令替换和通过路径直接调用可执行文件。

3. 📁 路径沙盒

  • 文件工具只能访问 workspace/office/
  • 拒绝绝对路径和 ../ 路径穿越。
  • 使用 realpath + commonpath 重新校验符号链接目标。
  • 覆盖写入前保存备份,并使用临时文件原子替换。

4. 📦 执行后端

默认本地后端使用参数数组和 shell=False。设置 OMNICLAW_EXECUTION_BACKEND=docker 后,可将已通过策略的命令放入禁网、只读根文件系统、 移除 Linux capabilities 且限制 CPU、内存和 PID 的容器中执行。

Warning

这是应用层纵深防护,不等同于虚拟机或专用沙箱。处理完全不可信代码时,应使用 Docker 后端,并继续限制宿主机挂载、容器权限和敏感凭证。

OmniClaw 拒绝危险操作
高风险命令由确定性策略阻断,普通自然语言确认不能绕过

🧰 工具能力

OmniClaw 默认注册 13 个工具:

类别 工具
文件 list_office_filesread_office_filewrite_office_file
执行 execute_office_shell
网络 fetch_https_text
基础能力 calculatorget_current_timeget_system_model_info
记忆 save_user_profile
定时任务 schedule_tasklist_scheduled_tasksmodify_scheduled_taskdelete_scheduled_task

fetch_https_text 是受限网页读取工具,不是搜索引擎。它只接受明确的公网 HTTPS URL, 限制响应大小,并在每次重定向后重新执行 SSRF 校验。

🧩 技能扩展

动态技能存放在:

workspace/office/skills/<skill-name>/
├── SKILL.md
└── skill.json

SKILL.md 提供名称、描述和使用说明;skill.json 声明固定入口、权限和参数:

{
  "entrypoint": ["echo", "{message}"],
  "permissions": ["shell.read_only"],
  "parameters": {
    "message": {
      "required": true,
      "description": "输出文本"
    }
  }
}

加载流程:

扫描 SKILL.md 元数据
        ↓
只向模型注册名称和描述
        ↓
需要时使用 help 读取完整说明
        ↓
使用 run 提交清单声明的结构化参数
        ↓
统一经过命令策略和执行后端
  • 技能目录扫描结果缓存 60 秒。
  • 完整说明使用 LRU 缓存,单次最多注入 3,000 字符。
  • 未知参数、缺失参数、未知权限和未声明占位符会被拒绝。
  • 没有 skill.json 的旧技能默认只能读取帮助,不能执行自由命令。

⏰ 定时任务与持续运行

定时任务由独立 SQLite 数据库存储。Heartbeat 动态等待最近任务的截止时间;任务发生增删改时, 通过 asyncio.Event 立即唤醒并重新计算,不使用固定间隔轮询。

flowchart LR
    U["自然语言提醒"] --> A["Agent"]
    A --> T["schedule_task"]
    T --> D["tasks.sqlite3"]
    D --> H["Heartbeat"]
    H -->|"到期"| E["内部结构化事件"]
    E --> R["直接输出提醒"]
Loading

OmniClaw 定时提醒
提醒到期后通过内部事件输出,不需要再次调用模型

💡 使用示例

❯ 分析 office 目录中的销售数据,生成 Markdown 摘要

[✓] 完成调用: list_office_files
[✓] 完成调用: read_office_file
[✓] 完成调用: write_office_file

OmniClaw
分析结果已写入 report.md。
❯ 删除工作区中的所有文件

OmniClaw
批量删除全部文件或清空工作区属于高风险操作,当前版本不会执行。

OmniClaw 中文对话
Markdown 渲染、中文交互和清晰的最终回复

⚙️ 配置参考

模型

Provider DEFAULT_PROVIDER Key
OpenAI openai OPENAI_API_KEY
DeepSeek deepseek OPENAI_API_KEY
阿里云 DashScope aliyun OPENAI_API_KEY
MiniMax minimax OPENAI_API_KEY
Moonshot moonshot OPENAI_API_KEY
SiliconFlow siliconflow OPENAI_API_KEY
腾讯混元 tencent OPENAI_API_KEY
智谱 zhipu OPENAI_API_KEY
Anthropic anthropic ANTHROPIC_API_KEY
Ollama ollama 不需要
其他兼容服务 other OPENAI_API_KEY

运行时

环境变量 默认值 说明
OMNICLAW_WORKSPACE <project>/workspace 状态、记忆、任务和文件根目录
OMNICLAW_LANG zh Agent 提示语言,支持 zhen
OMNICLAW_EXECUTION_BACKEND local localdocker
OMNICLAW_CONTEXT_TOKEN_BUDGET 12000 启动时的历史消息 Token 预算;运行中可用 /token-budget 修改
OMNICLAW_MODEL_CONTEXT_WINDOW 65536 模型完整上下文窗口,用于请求硬包络校验
OMNICLAW_CONTEXT_OUTPUT_RESERVE_TOKENS 1024 为模型输出预留的 Token
OMNICLAW_CONTEXT_SAFETY_MARGIN_PERCENT 10 完整上下文窗口的安全余量百分比
OMNICLAW_MAX_TOOL_CALLS_PER_TURN 5 每轮工具调用次数硬上限
OMNICLAW_MAX_HTTPS_FETCHES_PER_TURN 3 每轮 HTTPS 抓取硬上限
OMNICLAW_TOOL_BUDGET_UNITS 8 每轮加权工具预算
OMNICLAW_TOOL_RESERVE_UNITS 2 只供读取和验证工具使用的收尾预算
OMNICLAW_TOOL_BUDGET_SOFT_PERCENT 50 进入节制调用阶段的剩余预算百分比
OMNICLAW_ARTIFACT_THRESHOLD_CHARS 6000 工具结果转存阈值
OMNICLAW_MAX_WRITE_BYTES 1000000 单文件写入上限
OMNICLAW_MAX_FETCH_BYTES 200000 HTTPS 文本响应上限
OMNICLAW_LLM_TIMEOUT_SECONDS 90 模型调用超时
OMNICLAW_TOOL_TIMEOUT_SECONDS 60 工具节点超时

完整示例见 .env.example

双预算运行时

OmniClaw 同时治理模型的认知资源和行动资源:

  • 上下文预算:优先保留最近完整轮次;单个最新轮次仍过大时,只压缩模型输入副本, 保留消息类型、工具调用和工具结果之间的协议结构。
  • 工具预算:同时限制调用次数、HTTPS 抓取次数和加权单位。普通工具成本为 1, 网页抓取和写入类操作通常为 2,Shell、Python 和删除类操作为 3
  • 软阈值:剩余预算降至默认 50% 后,提示模型优先选择高信息增益调用。
  • 收尾预算:最后默认 2 个单位只开放读取、计算和状态检查类工具,禁止开始新的写入或探索。
  • 硬终止:任一硬预算耗尽后,模型改用未绑定工具的实例,只能基于已有证据回答。

硬终止不是正确性保证。最终回答会携带终止原因,并要求区分“已确认事实”“未确认事项” “结论”和“当前限制”,防止在证据不足时将推测写成事实。

🐳 Docker

Docker Compose 使用独立命名卷保存容器内工作区和日志,不会直接读写宿主机现有的 workspace/

cp .env.example .env
docker compose build
docker compose run --rm omniclaw

运行隔离测试:

docker compose run --rm test

更多说明见 Docker 指南

💾 数据目录

workspace/
├── state.sqlite3
├── tasks.sqlite3
├── current_thread_id
├── memory/
│   └── user_profile.md
├── artifacts/
├── backups/
│   └── office/
└── office/
    └── skills/

logs/
└── <thread-id>.jsonl

workspace/logs/.env 默认被 .gitignore 排除。

🧪 开发与测试

python -m pip install -e .
python -m pytest tests/ -q

当前测试基线:

242 passed

测试覆盖 Agent loop 结构、异步运行时、上下文裁剪、Artifact、任务调度、Provider、 动态技能、路径沙盒、命令策略、执行后端、线程状态和 Monitor。

📁 项目结构

OmniClaw/
├── entry/
│   ├── cli.py
│   ├── main.py
│   └── monitor.py
├── omniclaw/core/
│   ├── agent.py
│   ├── runtime.py
│   ├── context.py
│   ├── artifact_store.py
│   ├── execution.py
│   ├── provider.py
│   ├── skill_loader.py
│   ├── heartbeat.py
│   ├── task_store.py
│   ├── logger.py
│   └── tools/
│       ├── builtins.py
│       ├── sandbox_tools.py
│       └── command_policy.py
├── tests/
├── docs/
├── Dockerfile
├── compose.yaml
└── setup.py

📚 文档

🚧 当前限制

  • REQUIRE_CONFIRM 已完成风险识别,但尚未接入真人审批界面。
  • Shell 工具不支持管道、重定向、通配符和解释器命令。
  • 文件工具主要面向 UTF-8 文本,不处理通用二进制文件。
  • Docker 执行后端依赖宿主机 Docker daemon,默认仍使用本地受限后端。
  • 进程必须持续运行,定时任务才能按时触发。
  • Web Search 仍处于设计阶段,尚未进入默认工具集。

📄 许可证

本项目使用 MIT License

🙏 设计参考

项目在产品形态和交互上参考了以下开源项目,核心运行时、安全策略和上下文管理由 OmniClaw 独立实现:

About

Local single-agent AI workbench powered by LangGraph

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages