|
|
# 04 最小复刻清单
|
|
|
|
|
|
目标:一个你能完全讲清楚的小 Agent,不是功能全集。
|
|
|
|
|
|
建议包名 / 命令:自己定,下文用 `myagent` 指代。
|
|
|
|
|
|
## 1. 目录骨架
|
|
|
|
|
|
```text
|
|
|
my-agent/
|
|
|
pyproject.toml
|
|
|
README.md
|
|
|
src/myagent/
|
|
|
__init__.py
|
|
|
cli.py # argparse:--model / --session
|
|
|
config.py # 读环境变量或用户目录 ini/yaml
|
|
|
llm.py # 只创建 ChatOpenAI(base_url, api_key, model)
|
|
|
prompt.py # 静态 system + 动态 cwd/tree
|
|
|
graph.py # StateGraph:llm_call / tool_node
|
|
|
tools/
|
|
|
fs.py # read_file, list_dir, replace_in_file
|
|
|
shell.py # execute_command + 确认回调
|
|
|
session.py # sqlite checkpointer
|
|
|
tests/
|
|
|
test_graph_smoke.py
|
|
|
test_path_sandbox.py
|
|
|
```
|
|
|
|
|
|
第一版**不要**:textual、mcp、skills、subagent、语音、多厂商。
|
|
|
|
|
|
## 2. 配置(最小)
|
|
|
|
|
|
环境变量即可:
|
|
|
|
|
|
```text
|
|
|
MYAGENT_API_KEY=...
|
|
|
MYAGENT_BASE_URL=https://api.agicto.cn/v1
|
|
|
MYAGENT_MODEL=deepseek-v4-flash
|
|
|
```
|
|
|
|
|
|
密钥只放用户目录或系统环境,禁止进 git。
|
|
|
|
|
|
## 3. 图的最小实现要点
|
|
|
|
|
|
```text
|
|
|
State = { messages, llm_calls }
|
|
|
|
|
|
START → llm_call → (有 tool_calls?)
|
|
|
是 → tool_node → llm_call
|
|
|
否 → END
|
|
|
```
|
|
|
|
|
|
硬性要求:
|
|
|
|
|
|
- 工具异常要变成 ToolMessage 文本,不能把整个图打崩
|
|
|
- 一轮多个 tool_calls 可以先串行,跑通再并行
|
|
|
- `thread_id` 用参数传入,默认 `default`
|
|
|
|
|
|
## 4. 工具验收
|
|
|
|
|
|
| 工具 | 必须有的约束 | 怎么测 |
|
|
|
|------|----------------|--------|
|
|
|
| read_file | 只能读 cwd 内;限制行数 | 读 `../` 应拒绝 |
|
|
|
| list_dir | 跳过 `.git` / `node_modules` / `.venv` | 在本项目根目录跑 |
|
|
|
| replace_in_file | old_text 必须唯一匹配 | 改一个函数名再读回来 |
|
|
|
| execute_command | 超时;打印命令等 y/N | 输入 `n` 应取消 |
|
|
|
|
|
|
## 5. CLI 体验(第一版足够)
|
|
|
|
|
|
```text
|
|
|
$ myagent
|
|
|
> 请总结当前目录 README
|
|
|
[think] ...
|
|
|
[tool] read_file README.md
|
|
|
[final] ...
|
|
|
|
|
|
> /clear
|
|
|
> /exit
|
|
|
```
|
|
|
|
|
|
没有气泡也没关系。日志清晰比好看重要。
|
|
|
|
|
|
## 6. 测试底线
|
|
|
|
|
|
- `test_path_sandbox.py`:逃出 cwd 失败
|
|
|
- `test_graph_smoke.py`:mock LLM 返回一次 tool_call 再返回纯文本,断言 tool 被调用、最终 END
|
|
|
|
|
|
没有 mock 测试,不要进入阶段 4。
|
|
|
|
|
|
## 7. 对照 Qoze 时允许借鉴的“形状”
|
|
|
|
|
|
可以借鉴:
|
|
|
|
|
|
- 两节点 ReAct 图
|
|
|
- 静态/动态 prompt 分离
|
|
|
- 文件路径沙箱
|
|
|
- checkpoint 的 thread_id 思路
|
|
|
|
|
|
不要复制:
|
|
|
|
|
|
- 整份 `system_prompt.py` 长文案
|
|
|
- Textual CSS 和像素 logo
|
|
|
- 十几个厂商的 `initialize_llm` 分支
|
|
|
- 被注释掉的浏览器工具堆
|
|
|
|
|
|
## 8. 完成定义(Definition of Done)
|
|
|
|
|
|
当下面全是“是”,阶段 3 才结束:
|
|
|
|
|
|
- [ ] 新仓库能独立 `pip install -e .` 跑起来
|
|
|
- [ ] 只用 DeepSeek 兼容接口
|
|
|
- [ ] 四件套工具都有单测或手工脚本
|
|
|
- [ ] 会话可恢复
|
|
|
- [ ] README 是你自己写的架构说明(不是拷来的)
|
|
|
- [ ] 你能不看代码画出数据流
|