You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3.0 KiB
3.0 KiB
04 最小复刻清单
目标:一个你能完全讲清楚的小 Agent,不是功能全集。
建议包名 / 命令:自己定,下文用 myagent 指代。
1. 目录骨架
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. 配置(最小)
环境变量即可:
MYAGENT_API_KEY=...
MYAGENT_BASE_URL=https://api.agicto.cn/v1
MYAGENT_MODEL=deepseek-v4-flash
密钥只放用户目录或系统环境,禁止进 git。
3. 图的最小实现要点
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 体验(第一版足够)
$ 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 是你自己写的架构说明(不是拷来的)
- 你能不看代码画出数据流