一个用 Python 构建的轻量级通用 AI Agent 框架。
| 模块 | 说明 |
|---|---|
| AgentLoop | 核心循环约 100 行,消息是唯一状态,所有能力委托给插件 |
| ToolRegistry | 动态工具注册,@tool_parameters 装饰器声明工具,6 个内置工具 |
| SandboxExecutor | subprocess 沙箱,内存/CPU/超时限制,危险命令强制走沙箱 |
| HookManager | 6 个生命周期扩展点,内置日志/重试/追踪/预算监控 Hook |
| MemoryManager | AutoCompact token 压缩,超预算时用 LLM 生成摘要 |
| SkillLoader | Markdown 技能文件(YAML frontmatter + prompt),按需/always 加载 |
| SubAgentManager | asyncio 后台任务委托,ParentChannel 实现 mid-turn injection |
# 安装(使用 uv,更快)
uv sync # 只装运行时依赖
uv pip install -e ".[dev]" # 一次性装完运行时+开发依赖
# 配置 API Key
cp .env.example .env
# 编辑 .env,填入 OPENAI_API_KEY 或 ANTHROPIC_API_KEY
# 运行(OpenAI,默认)
uv run python cli.py --model gpt-4o-mini "Hello"
# 运行(Anthropic)
uv run python cli.py --provider anthropic --model claude-sonnet-4-20250514 "Hello"
# 交互模式
uv run python cli.py --interactive
# 运行测试
uv run pytest tests/ -v| 工具 | 权限级别 | 说明 |
|---|---|---|
Read |
read_only | 读取文件,支持行数限制 |
Write |
read_write | 写入文件,自动创建父目录 |
Bash |
dangerous | 沙箱执行 shell 命令(超时/资源限制) |
WebSearch |
read_only | DuckDuckGo HTML 搜索 |
WebFetch |
read_only | 获取网页内容,支持截断 |
Grep |
read_only | 正则搜索文件/目录 |
agent/
├── loop.py # AgentLoop 核心(~100行)
├── llm.py # LLM Protocol + ToolCallDelta
├── openai_llm.py # OpenAI Chat Completions 实现
├── anthropic_llm.py # Anthropic Messages API 实现
├── message.py # Message dataclass + 快捷构造
├── result.py # RunResult + StopReason + ToolCallMade
├── tools/
│ ├── base.py # Tool ABC + @tool_parameters 装饰器
│ ├── registry.py # ToolRegistry
│ ├── sandbox.py # SandboxExecutor
│ └── builtin/ # 6 个内置工具
├── hooks/
│ ├── manager.py # HookManager + Hook Protocol
│ └── builtin/ # 4 个内置 Hook
├── memory/
│ └── manager.py # MemoryManager + AutoCompact
├── skills/
│ └── loader.py # SkillLoader + Skill dataclass
└── subagent/
├── manager.py # SubAgentManager
├── protocol.py # ParentChannel(asyncio.Queue)
└── parent_channel_hook.py # mid-turn injection 实现
skills/ # 技能文件目录
├── code-review.md
└── research.md
messages → LLM → tool_calls? → [execute tools] → append results → repeat
↓
no tools → return content
AgentLoop.run() 是唯一的状态管理者,messages 是唯一的可变状态。所有子系统(工具执行、记忆管理、子 Agent 委托)均通过依赖注入持有引用。
from agent.tools import Tool, tool_parameters, ToolRegistry
@tool_parameters(
name="MyTool",
description="做什么",
parameters={"type": "object", "properties": {"arg": {"type": "string"}}}
)
class MyTool(Tool):
read_only = True
async def execute(self, arg: str, **kwargs) -> str:
return f"result: {arg}"
registry = ToolRegistry()
registry.register(MyTool())from agent.hooks import HookManager, Hook
class MyHook(Hook):
async def before_iteration(self, iteration, messages): ...
async def after_llm_call(self, response): ...
async def before_tool_execute(self, tool_call): ...
async def after_tool_execute(self, tool_call, result): ...
async def on_error(self, error): ...
async def on_completion(self, result): ...
agent = AgentLoop(hooks=HookManager([MyHook()]), ...)MemoryManager.compact_if_needed() 在每次工具调用轮次后检查 token 预算,超限时触发压缩:
- 保留所有
role=system消息 - 保留最近 N 条对话
- 中间部分调用 LLM 生成一段摘要
memory = MemoryManager(max_tokens=80_000, recent_window=10, llm=openai_llm)subagent_id = await subagent_manager.delegate(
task="搜索相关信息",
tools=[WebSearchTool(), WebFetchTool()],
model="gpt-4o-mini",
llm=openai_llm,
)
# 后台运行,结果通过 ParentChannel 注入父 agent 当前轮次- 创建
agent/tools/builtin/my_tool.py,继承ToolABC,使用@tool_parameters - 在
agent/tools/__init__.py中 import 并加入get_default_tools() - 注册到
ToolRegistry
- 实现
HookProtocol(6 个方法,可以空实现) - 传入
HookManager([MyHook()])
在 skills/ 目录创建 .md 文件:
---
name: my-skill
description: 技能描述
tools: [Read, Bash]
always: false
---
# 技能标题
这里是指示 prompt...Python 3.11+ / asyncio / httpx / typer / tiktoken(可选)
详细架构设计见 docs/superpowers/specs/:
2026-05-06-general-purpose-agent-design.md— 架构设计2026-05-06-reference-projects-analysis.md— 参考项目分析