内容
# py-agent
Python 终端 AI Agent CLI。支持 ReAct 工具循环、Plan-and-Execute DAG 调度、Multi-Agent 协作,内置文件/Shell/搜索/记忆/MCP 等工具,提供 Runtime API 和 SDK 嵌入能力。
## 功能特性
- **ReAct 工具循环** — thinking / tool call / tool result / output 事件流,支持并发读取和串行写入分流
- **Plan-and-Execute** — 独立 Planner 生成 DAG,按依赖拓扑排序,并行执行无依赖任务
- **Multi-Agent 协作** — Planner → Worker 池 → Reviewer 三角色,asyncio.Queue 借还机制,失败重试 + Reviewer 审核
- **上下文压缩** — token 用量超窗口 80% 自动触发摘要压缩,可配置保留比例(aggressive/balanced/conservative)
- **工具系统** — 15 个内置工具 + MCP 动态注册,支持白名单/黑名单过滤,HITL 审批 + 审计日志
- **MCP 客户端/服务端** — stdio + Streamable HTTP,可作为 MCP server 暴露内置工具
- **Skill 系统** — builtin/user/project 三层覆盖加载,LRU 缓冲 + 懒加载注入,支持启用/禁用
- **长期记忆** — SQLite 持久化,scope 项目隔离 + 全局记忆,自动注入 system prompt
- **快照与恢复** — Agent run 前后自动创建文件级快照,支持回退
- **Runtime API** — 线程/turn/事件/后台任务,RESTful 接口
- **多模态输入** — 本地/远程图片引用,自动压缩转 data URL,不支持时降级为文本元信息
## 技术架构
### Prompt 拼接
system prompt 由 `PromptAssembler` 按 4 层组装:
```
You are Py-Agent... ← 基础身份
+ Guidelines (6 条行为规范) ← 行为约束
+ Custom instructions (custom_prompt_paths 文件内容) ← 用户自定义规则
+ Project memory (AGENT.md + 长期记忆,总计 ≤8000 字符) ← 项目上下文
+ Skill index (可用 skill 列表) ← 技能索引
```
三种运行模式在此基础上追加角色指令:
| 模式 | 追加内容 |
|------|---------|
| ReAct(默认) | 无追加 |
| Plan-and-Execute | `"You are executing one task inside a Plan-and-Execute DAG. Task id: xxx"` |
| Multi-Agent | Planner: `"Return only JSON with a steps array"` / Worker: `"Execute only the assigned step"` / Reviewer: `"Return JSON: {approved, summary, issues}"` |
另外,用户消息前可注入 Skill 内容(`load_skill` 触发,缓冲上限 3 个),Planner 和上下文压缩使用完全独立的 prompt,不走 PromptAssembler。
### 三种运行模式
```
用户输入 → QueryEngine
├─ ask() → ReAct 循环(单 Agent,while turn < 20)
├─ plan() → Planner(LLM生成DAG) → asyncio.gather 并行执行
└─ team() → Planner → Worker池(asyncio.Queue) → Reviewer → 重试
```
**ReAct 循环**:每轮 `LLM 思考 → 工具调用 → 结果注入 → 下一轮`,最多 20 轮。读工具并发(Semaphore 4)、写工具串行。HITL 审批拦截危险操作。
**Plan-and-Execute**:Planner 调用独立 LLM(不带工具,只出 JSON),生成 DAG。任务按依赖拓扑排序,无依赖的任务 `asyncio.gather` 并行执行。每个任务独立 ReAct(`history=[]`),仅通过依赖结果文本传递上下文。
**Multi-Agent**:Planner 分解任务 → Worker 从 `asyncio.Queue` 借出执行 → Reviewer 审核结果。不通过则重试(最多 2 次),反馈注入重试上下文。所有角色共享 `SkillContextBuffer`,Worker 每步后 `clear_history()` 防上下文污染。
### 配置系统
4 层叠加优先级:`默认值 → ~/.py_agent/config.json → .py_agent/config.json → 环境变量`
```python
@dataclass
class PyAgentConfig:
llm: LlmConfig # provider, model, api_key, base_url, max_tokens, temperature
render_mode: str # "inline" | "plain"
tools: ToolsConfig # enabled(白名单), disabled(黑名单), timeout, max_concurrent_read
mcp: McpConfig # servers(内联定义), auto_start
memory: MemoryConfig # compression_threshold(0.8), token_budget_mode, long_term_db_path
policy: PolicyConfig # hitl_mode, command_blacklist, path_guard
prompt: PromptConfig # personality, agent_mode, custom_prompt_paths
features: FeatureConfig # mcp/skill/memory/audit_log/context_compression/code_index 开关
```
### 工具系统
15 个内置工具,按危险等级分级:
| 工具 | 危险等级 | 只读 | 说明 |
|------|---------|------|------|
| read_file / list_dir / glob / grep | — | 是 | 文件系统读取 |
| web_search / web_fetch | — | 是 | 联网检索 |
| search_code | — | 是 | 本地代码索引搜索 |
| load_skill | — | 是 | Skill 懒加载 |
| write_file | medium | 否 | 文件写入,需写权限 |
| save_memory | medium | 否 | 长期记忆写入 |
| bash / execute_command | high | 否 | Shell 命令执行 |
| revert_turn | high | 否 | 快照恢复 |
MCP 工具动态注册为 `mcp__<server>__<tool>` 格式,同时生成虚拟 resource/prompt 工具。
工具执行流程:`executor.execute_all()` 分流 → 只读并发 + 写串行 → HITL 审批拦截 → PathGuard/CommandGuard 校验 → 审计日志记录。
## 环境要求
- Python 3.11+
- [uv](https://docs.astral.sh/uv/)
- 可选:`rg`(加速本地搜索)、Node.js 20+(Chrome DevTools MCP)
## 快速开始
```bash
git clone https://github.com/itwanger/py-agent.git
cd py-agent
uv sync --extra dev
uv run py-agent --help
```
交互模式:
```bash
uv run py-agent
```
单次查询:
```bash
uv run py-agent -p "帮我总结这个项目"
```
## 配置
优先级:`默认值 < ~/.py_agent/config.json < .py_agent/config.json < 环境变量`
```dotenv
PY_AGENT_PROVIDER=deepseek
PY_AGENT_MODEL=deepseek-v4-flash
PY_AGENT_API_KEY=your_key_here
```
支持的 provider-specific Key:`DEEPSEEK_API_KEY` / `GLM_API_KEY` / `STEP_API_KEY` / `KIMI_API_KEY`
命令行覆盖:
```bash
uv run py-agent --provider deepseek --model deepseek-v4-flash
```
连接本地模型:
```bash
PY_AGENT_PROVIDER=openai-compatible \
PY_AGENT_BASE_URL=http://127.0.0.1:11434/v1 \
PY_AGENT_MODEL=qwen2.5-coder \
uv run py-agent -p "解释这个仓库"
```
## 交互命令
```
/help /exit /clear /context
/memory /save /config /tools
/hitl /policy /audit /index
/search /plan /team /model
/skill /mcp /task /snapshot
/restore
```
## 内置工具
`read_file` `write_file` `list_dir` `glob` `grep` `bash` `web_search` `web_fetch` `save_memory` `load_skill` `search_code` `revert_turn`
写操作和危险命令经过 policy、HITL 和 audit 三重处理。工具可通过配置白名单/黑名单过滤。
## 联网工具
`web_search` — DuckDuckGo HTML 搜索,返回标题、URL 和摘要。
`web_fetch` — 抓取公开页面,拒绝 `file://`、loopback、私有地址,降低 SSRF 风险。
需登录态或 JS 渲染页面建议使用 Chrome DevTools MCP。
## MCP
连接 MCP server,远端工具动态注册为 `mcp__<server>__<tool>`:
```bash
uv run py-agent mcp init-chrome --scope project
```
通过配置文件定义服务器(`~/.py_agent/config.json` 或 `.py_agent/config.json`):
```json
{
"mcp": {
"servers": [
{"name": "my-server", "type": "stdio", "command": "node", "args": ["server.js"]}
],
"auto_start": true
}
}
```
Py-Agent 自身作为 MCP server:
```bash
uv run py-agent mcp serve --transport http --port 3000
```
## Runtime API
```bash
PY_AGENT_RUNTIME_API_KEY=dev-key uv run py-agent serve --http --port 8080
```
提供 `/v1/threads` `/v1/threads/<id>/turns` `/v1/threads/<id>/events` `/v1/tasks` 端点。
## 图片输入
```text
分析这张截图 @image:./screenshots/page.png
看看这个 @image:https://example.com/diagram.png
```
本地图片自动压缩转 data URL。模型不支持多模态时自动降级为文本元信息。
## 快照
每次 Agent run 自动创建 pre-turn / post-turn 快照,保存在 `~/.py_agent/snapshots/`。
```
/snapshot # 查看快照列表
/restore 1 # 恢复到指定快照
/snapshot clean # 清理旧快照
```
## SDK
```python
from py_agent.sdk import create_default_engine
engine = create_default_engine(cwd=".")
result = engine.ask_complete("解释这个项目")
print(result.text)
```
## 开发
```bash
uv sync --extra dev
uv run python -m ruff check .
uv run python -m pytest
uv build
```
## License
MIT. See [LICENSE](LICENSE).