Comprehensive Coding Agent / 综合编码 Agent(纯 Python 实现)¶
Production-ready AI coding agent (Claude + pure Python tools) implementing Chapter 2 techniques—no CLI tool dependencies.
生产级 AI 编码 Agent:落地第 2 章技术,纯 Python 工具实现,无命令行工具依赖。
English¶
Overview¶
A production-ready AI coding agent built with Claude, implementing techniques from Chapter 2 with pure Python tools—no command-line dependencies required.
Code map¶
- Run first:
python quickstart.pyin a disposable workspace (after provider setup). - Start here:
agent.py::CodingAgent.run(the CLI wrapper inmain.pyis a separate presentation layer). - Core behavior: tool selection, trajectory turns, patch application and test feedback are in agent.py; tool schemas live in tools.json.
- State / protocol: system_state.py::SystemState, workspace snapshots and structured tool results.
- Verifier: test/lint execution plus the acceptance checks; inspect the failure path before the provider adapter.
- Experiment variable: read/search depth, patch strategy and verification budget.
- Skip on first pass: pure-Python compatibility wrappers, colorized CLI output and long tutorial examples.
Key Features¶
Pure Python Implementation¶
All tools implemented without command-line dependencies:
- ❌ No
grep,rg(ripgrep),findcommands needed - ❌ No dependency on system utilities
- ✅ 100% pure Python implementations
- ✅ Works with the repository root Python 3.12 environment
- ✅ Especially designed for Mac users without command-line tools
Complete Tool Suite¶
All 16 tools from tools.json fully implemented:
File Operations (Pure Python):
Read- File reading with image/PDF/notebook supportWrite- File writing with auto lint checkingEdit- Search and replace editingMultiEdit- Multiple edits in one operation
Search Tools (Pure Python, no rg/grep dependency):
Grep- Pure Python regex search with full ripgrep feature parity- Full regex support
- Case insensitive search
- Context lines (before/after/around)
- Line numbers
- Multiline mode
- Glob filtering
- File type filtering
- Multiple output modes
Glob- File pattern matchingLS- Directory listing
Shell Operations:
Bash- Persistent shell sessionsBashOutput- Background job outputKillBash- Terminate shells
Project Management:
TodoWrite- Task list managementExitPlanMode- Plan mode exit
Advanced:
NotebookEdit- Jupyter notebook editingWebFetch- Web content fetching (stub)WebSearch- Web search (stub)Task- Sub-agent launcher (stub)
System Hint Techniques (Chapter 2)¶
- Timestamps: Every message and tool result timestamped
- Tool Call Counting: Warns after 3+ repeated calls
- TODO List Management: Explicit task tracking
- Detailed Error Information: Rich error context
- System State Awareness: Working directory, OS, Python version
- Environment Information: Dynamic state in context
Terminal Environment¶
- Persistent Shell Sessions: Commands in same shell
- Working Directory Tracking: Directory changes persist
- Background Execution: Long-running command support
Auto Lint Detection¶
After Write/Edit/MultiEdit:
- Python syntax checking
- JavaScript/TypeScript checking
- Errors appear immediately in tool results
Project Structure¶
coding-agent/
├── agent.py # Main agent implementation
├── system_state.py # System state tracking
├── tool_registry.py # Tool name → implementation mapping
├── tools/ # All tool implementations
│ ├── __init__.py
│ ├── base.py # Base tool class
│ ├── bash_tool.py # Shell execution
│ ├── bash_output_tool.py # Background job output
│ ├── kill_bash_tool.py # Shell termination
│ ├── read_tool.py # File reading
│ ├── write_tool.py # File writing
│ ├── edit_tool.py # File editing
│ ├── multi_edit_tool.py # Multiple edits
│ ├── grep_tool.py # Pure Python regex search (no rg!)
│ ├── glob_tool.py # File pattern matching
│ ├── ls_tool.py # Directory listing
│ ├── todo_write_tool.py # TODO management
│ ├── exit_plan_mode_tool.py
│ ├── notebook_edit_tool.py
│ ├── web_fetch_tool.py
│ ├── web_search_tool.py
│ ├── task_tool.py
│ └── shell_session.py # Shell session management
├── tools.json # Tool definitions
├── system-prompt.md # System prompt
├── config.py # Configuration
├── requirements.txt # Dependencies
└── README.md # This file
Installation¶
# From the repository root: use the shared Chapter 5 environment
uv sync --locked --python 3.12 --extra ch5
# Activate it before changing directories:
# macOS/Linux:
source .venv/bin/activate
# Windows PowerShell: .\.venv\Scripts\Activate.ps1
# Windows cmd: .venv\Scripts\activate.bat
# pip fallback when uv is not installed:
# python -m pip install -e ".[ch5]"
cd chapter5/coding-agent
# Single-project compatibility path, still supported during migration:
# python -m pip install -r requirements.txt
# Set up environment
cp .env.example .env
# Edit .env and configure your provider
Configuration¶
Edit .env file:
# Choose your provider (anthropic, openai, or openrouter)
PROVIDER=anthropic
# Add API key for your chosen provider
ANTHROPIC_API_KEY=your-anthropic-api-key
# or
OPENROUTER_API_KEY=your-openrouter-api-key
# or
OPENAI_API_KEY=your-openai-api-key
# Select model appropriate for your provider
DEFAULT_MODEL=claude-sonnet-5
See PROVIDERS.md for detailed provider configuration guide.
Requirements¶
Core dependencies:
- Python 3.12 for the root
ch5install anthropic- For Anthropic APIopenai- For OpenAI/OpenRouter APIpython-dotenv- For configuration
Optional (for enhanced features):
PyPDF2- For PDF readingrequests,beautifulsoup4,html2text- For WebFetch
No command-line tools needed! Works on macOS without Homebrew packages.
Supported Providers¶
- Anthropic - Direct Claude API access
- OpenRouter - Access to Claude, GPT, Gemini, Llama, and more
- OpenAI - Direct GPT API access
The agent automatically handles the different API formats for each provider.
OpenRouter as a universal fallback¶
You do not need a direct Anthropic or OpenAI key to run the agent. If the
requested direct provider's key is missing, the agent transparently falls back
to OpenRouter (via the OpenAI-compatible SDK) as long as
OPENROUTER_API_KEY is set:
PROVIDER=anthropicwithANTHROPIC_API_KEY→ Anthropic SDK, unchanged (default behavior).PROVIDER=anthropicwithoutANTHROPIC_API_KEY(butOPENROUTER_API_KEYset) → routed through OpenRouter.PROVIDER=openaiwithOPENAI_API_KEY→ OpenAI SDK, unchanged.PROVIDER=openaiwithoutOPENAI_API_KEY(butOPENROUTER_API_KEYset) → routed through OpenRouter.
When falling back, the native model id is prefixed/mapped to an OpenRouter id:
| Requested model | OpenRouter id used |
|---|---|
claude-sonnet-* (e.g. claude-sonnet-5) |
anthropic/claude-sonnet-4.6 |
claude-haiku-* |
anthropic/claude-haiku-4.5 |
claude-opus-* / other claude-* |
anthropic/claude-opus-4.8 |
gpt-* / o1-* (e.g. gpt-5.6-luna) |
openai/<model> |
already prefixed (vendor/model) |
passed through unchanged |
So a user with only an OPENROUTER_API_KEY can run, e.g.:
# No ANTHROPIC_API_KEY needed — falls back to OpenRouter automatically
python main.py --provider anthropic --model claude-sonnet-5 -p "..."
# gpt-5.6-luna routed through OpenRouter (no OPENAI_API_KEY needed)
python main.py --provider openai --model gpt-5.6-luna -p "..."
Set PROVIDER=openrouter explicitly (with a vendor/model id) if you want to
target a specific OpenRouter model without any mapping.
Usage¶
CLI entry (main.py)¶
main.py is the recommended entry with a unified argparse UI. Run
python main.py --help for full Chinese help:
Main flags:
| Flag | Description |
|---|---|
| (no args) | Interactive chat (default) |
-p, --prompt "task" |
Non-interactive: one task then exit (scripts / CI) |
--list-tools |
Offline list of registered tools (no API key) |
--provider {anthropic,openai,openrouter} |
Override .env PROVIDER |
--model NAME |
Override .env DEFAULT_MODEL |
--base-url URL |
Override API base URL (gateway / OpenAI-compatible) |
--max-iterations N |
Max agent iterations per task (default 50) |
--no-color |
Disable color (auto-off without TTY) |
Quick self-check (offline, no API key)¶
$ python main.py --list-tools
共 16 个工具:
Task Launch a new agent to handle complex, multi-step tasks autonomously.
Bash Executes a given bash command in a persistent shell session ...
Glob - Fast file pattern matching tool that works with any codebase size
Grep A powerful search tool built on ripgrep
...
End-to-end example: real coding task¶
With .env configured (see Configuration), one command creates and runs a script:
Successful terminal structure (illustrative; turns/calls depend on model):
✓ Agent initialized successfully
You: 创建 hello_world.py ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔧 Calling tool: Write
✓ Completed (call #1)
✓ No lint errors
File: hello_world.py
🔧 Calling tool: Bash
✓ Completed (call #2)
Output:
Hello, World!
Hello, Alice!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Task completed!
Iterations: 2
Tool calls: 2
Success markers: Agent calls
WritethenBash, real script output appears, ends with✅ Task completed!. (quickstart.pyis a scripted version of the same task.)
Interactive chat (default)¶
Features:
- 🎨 Color-coded output for better readability
- ⚡ Real-time streaming responses
- 🔧 Live tool execution display
- 📊 Built-in status command
- 💬 Conversation history
- 🔄 Reset command to start fresh
In-session commands:
/help- Show help message/quitor/exit- Exit the CLI/reset- Reset conversation history/clear- Clear the screen/status- Show agent status (tool calls, TODOs, etc.)
Other example scripts (API key required)¶
python quickstart.py # basic quickstart (same task as e2e above)
python example_complex_task.py # complex multi-step task
python example_with_system_hints.py # system hint techniques demo
Programmatic Usage¶
from agent import CodingAgent
agent = CodingAgent(api_key="your-key")
for event in agent.run("List all Python files"):
if event["type"] == "text_delta":
print(event["delta"], end="", flush=True)
elif event["type"] == "done":
print("\n✅ Done!")
Pure Python Grep Implementation¶
The Grep tool is fully implemented in pure Python without any dependency on grep, rg, or other command-line tools. It provides all the features of ripgrep:
# Example: Search for pattern in files
{
"name": "Grep",
"input": {
"pattern": "def.*test",
"path": "/path/to/search",
"output_mode": "content",
"-i": True, # Case insensitive
"-C": 3, # 3 lines context
"-n": True, # Show line numbers
"glob": "*.py", # Only Python files
"multiline": False # Single line matching
}
}
Features:
- ✅ Full regex support (Python
remodule) - ✅ Case insensitive search (
-i) - ✅ Context lines (
-A,-B,-C) - ✅ Line numbers (
-n) - ✅ Multiline mode
- ✅ Glob filtering (
globparameter) - ✅ File type filtering (
typeparameter) - ✅ Output modes:
content,files_with_matches,count - ✅ Head limit
- ✅ Recursive directory search
- ✅ Binary file skip
- ✅ Hidden file/directory skip
Architecture¶
Modular Tool System¶
Each tool is implemented as a separate class inheriting from BaseTool:
class MyTool(BaseTool):
@property
def name(self) -> str:
return "MyTool"
def _execute_impl(self, params: Dict[str, Any]) -> Dict[str, Any]:
# Tool implementation
return {"result": "success"}
Tool Registry¶
ToolRegistry maps tool names to implementations:
registry = ToolRegistry()
tool = registry.get_tool("Grep", system_state)
result = tool.execute(params)
System State¶
SystemState tracks:
- Current working directory
- Tool call counts
- TODO list
- Shell sessions
- Environment info
System Hints¶
System hints are injected before each LLM call:
<system_hint>
# System State
Current Time: 2025-10-12 15:30:45
Working Directory: chapter5/coding-agent
OS: Darwin
Python: Python 3.12.0
# Tool Call Statistics
- Grep: 2 calls
- Write: 1 calls
# Current TODO List
✅ [1] Search for files (completed)
🔄 [2] Implement feature (in_progress)
⬜ [3] Write tests (pending)
</system_hint>
Design Principles¶
1. Pure Python Implementation¶
Why: Maximum portability and compatibility
- Works on any system with Python
- No Homebrew, apt, or other package managers needed
- Consistent behavior across platforms
2. Modular Tool Architecture¶
Why: Maintainability and extensibility
- Each tool is self-contained
- Easy to add new tools
- Easy to test individually
- Clear separation of concerns
3. No Command-Line Dependencies¶
Why: Reliability and control
- Grep: Pure Python regex search
- Glob: Python's
pathlib.glob() - LS: Python's
osandpathlib - No subprocess calls for core functionality
- Full control over behavior
4. System Hints for Self-Awareness¶
Why: Better agent behavior
- Prevents infinite loops (tool call counting)
- Maintains task focus (TODO tracking)
- Provides environmental context
- Enables self-monitoring
Comparison with Chapter 2¶
| Technique | Status | Implementation |
|---|---|---|
| Standard OpenAI Tool Format | ✅ | Anthropic SDK |
| Streaming Tool Calls | ✅ | Real-time JSON delta parsing |
| Parallel Tool Calls | ✅ | Multiple tools per response |
| Pure Python Tools | ✅ | No command-line dependencies |
| Grep without rg | ✅ | Pure Python regex search |
| Timestamps | ✅ | All messages/tools |
| Tool Call Counting | ✅ | Warns at 3+ |
| TODO List | ✅ | TodoWrite tool |
| System State | ✅ | Working dir, OS, Python |
| Persistent Shell | ✅ | Shell sessions |
| Auto Lint Detection | ✅ | After Write/Edit/MultiEdit |
Configuration (.env)¶
# Required
ANTHROPIC_API_KEY=your_key_here
# Optional
DEFAULT_MODEL=claude-sonnet-5
MAX_ITERATIONS=50
MAX_TOKENS=8192
Adding New Tools¶
- Create tool file in
tools/:
# tools/my_tool.py
from .base import BaseTool
class MyTool(BaseTool):
@property
def name(self) -> str:
return "MyTool"
def _execute_impl(self, params):
# Implementation
return {"result": "success"}
- Register in
tools/__init__.py:
- Add to
tool_registry.py:
- Add definition to
tools.json
Troubleshooting¶
"No module named 'tools'"¶
Make sure you're running from the project directory:
Grep not finding files¶
Check:
- Path is correct
- Pattern is valid regex
- Glob pattern matches files
- Files contain searchable text (not binary)
Shell commands fail¶
Ensure:
- Bash is available on
PATHon macOS/Linux - PowerShell is available on
PATHon Windows (cmd.exeis used as a fallback) - Working directory exists
- Commands use the native shell syntax and are properly quoted
Testing¶
Comprehensive test suite with 130+ tests covering all tool features.
Run Tests¶
# From the repository root, install the Chapter 5 and test environments
uv sync --locked --python 3.12 --extra ch5 --extra dev
# Activate it before changing directories:
# macOS/Linux:
source .venv/bin/activate
# Windows PowerShell: .\.venv\Scripts\Activate.ps1
# Windows cmd: .venv\Scripts\activate.bat
cd chapter5/coding-agent
# Run all tests
pytest
# Run with coverage
pytest --cov=tools --cov-report=html
# Run specific tool tests
pytest tests/test_grep_tool.py
pytest tests/test_bash_tool.py
# Verbose output
pytest -v
Test Coverage¶
- 130+ tests across 14 test files
- 2,200+ lines of test code
- All major features from tools.json tested
- Integration tests for tool chaining and system hints
See tests/README.md for detailed test documentation.
Learning Path¶
- Start with examples: Run
python main.py(interactive CLI) - Run quickstart:
python quickstart.py - Explore system hints:
python example_with_system_hints.py - Study Grep implementation: See
tools/grep_tool.py - Run tests:
pytest -vto see all features in action - Read Chapter 2: Understand the theory
- Add custom tools: Extend the system
References¶
- Chapter 2: Context Engineering (AI Agent Book)
- Tools specification:
tools.json - System prompt:
system-prompt.md - Anthropic Claude API: https://docs.anthropic.com/
Key Advantages¶
- No Dependencies on External Tools
- Pure Python implementation
- Works without rg, grep, find, etc.
-
Perfect for Mac users without Homebrew
-
Modular Architecture
- Each tool is a separate file
- Easy to understand and modify
-
Clear separation of concerns
-
Production Ready
- Comprehensive error handling
- Auto lint detection
- System hints for reliability
-
Streaming support for UX
-
Educational Value
- Learn how tools work internally
- Understand pure Python file operations
- See regex search implementation
- Study agent architecture patterns
License¶
MIT
Contributing¶
This is an educational implementation. Feel free to adapt and extend!
Built with pure Python for maximum portability and learning! 🐍✨
中文¶
概述¶
基于 Claude 的生产级 AI 编码 Agent,落地第 2 章相关技术,全部工具为纯 Python 实现——不依赖任何命令行工具。
核心特性¶
纯 Python 实现¶
全部工具均无命令行依赖:
- ❌ 不需要
grep、rg(ripgrep)、find - ❌ 不依赖系统工具
- ✅ 100% 纯 Python
- ✅ 使用仓库根目录 Python 3.12 环境即可运行
- ✅ 尤其适合未装命令行工具的 Mac 用户
完整工具集¶
tools.json 中的 16 个工具均已实现:
文件操作(纯 Python):
Read- 读文件(含图像/PDF/Notebook)Write- 写文件(自动 lint)Edit- 查找替换编辑MultiEdit- 一次多处编辑
搜索工具(纯 Python,无 rg/grep):
Grep- 纯 Python 正则搜索,功能对齐 ripgrep- 完整正则
- 大小写不敏感
- 上下文行(前/后/环绕)
- 行号
- 多行模式
- Glob 过滤
- 文件类型过滤
- 多种输出模式
Glob- 文件模式匹配LS- 目录列表
Shell:
Bash- 持久 shell 会话BashOutput- 后台任务输出KillBash- 终止 shell
项目管理:
TodoWrite- 任务列表ExitPlanMode- 退出计划模式
进阶:
NotebookEdit- Jupyter 编辑WebFetch- 抓取网页(stub)WebSearch- 网页搜索(stub)Task- 子 Agent 启动(stub)
系统提示(System Hint)技术(第 2 章)¶
- 时间戳:消息与工具结果均打时间戳
- 工具调用计数:重复调用 ≥3 次告警
- TODO 列表:显式任务跟踪
- 详细错误信息:丰富错误上下文
- 系统状态感知:工作目录、OS、Python 版本
- 环境信息:动态写入上下文
终端环境¶
- 持久 Shell 会话:同一 shell 内连续命令
- 工作目录跟踪:
cd等变更可保持 - 后台执行:支持长时命令
自动 Lint¶
Write/Edit/MultiEdit 之后:
- Python 语法检查
- JavaScript/TypeScript 检查
- 错误直接出现在工具结果中
项目结构¶
coding-agent/
├── agent.py # Main agent implementation
├── system_state.py # System state tracking
├── tool_registry.py # Tool name → implementation mapping
├── tools/ # All tool implementations
│ ├── __init__.py
│ ├── base.py # Base tool class
│ ├── bash_tool.py # Shell execution
│ ├── bash_output_tool.py # Background job output
│ ├── kill_bash_tool.py # Shell termination
│ ├── read_tool.py # File reading
│ ├── write_tool.py # File writing
│ ├── edit_tool.py # File editing
│ ├── multi_edit_tool.py # Multiple edits
│ ├── grep_tool.py # Pure Python regex search (no rg!)
│ ├── glob_tool.py # File pattern matching
│ ├── ls_tool.py # Directory listing
│ ├── todo_write_tool.py # TODO management
│ ├── exit_plan_mode_tool.py
│ ├── notebook_edit_tool.py
│ ├── web_fetch_tool.py
│ ├── web_search_tool.py
│ ├── task_tool.py
│ └── shell_session.py # Shell session management
├── tools.json # Tool definitions
├── system-prompt.md # System prompt
├── config.py # Configuration
├── requirements.txt # Dependencies
└── README.md # This file
安装¶
# 在仓库根目录使用统一的第 5 章环境
uv sync --locked --python 3.12 --extra ch5
# 切换目录前先激活环境:
# macOS/Linux:
source .venv/bin/activate
# Windows PowerShell:.\.venv\Scripts\Activate.ps1
# Windows cmd:.venv\Scripts\activate.bat
# 未安装 uv 时可用 pip 兜底:
# python -m pip install -e ".[ch5]"
cd chapter5/coding-agent
# 迁移期间仍支持单项目兼容路径:
# python -m pip install -r requirements.txt
# Set up environment
cp .env.example .env
# Edit .env and configure your provider
配置¶
编辑 .env:
# Choose your provider (anthropic, openai, or openrouter)
PROVIDER=anthropic
# Add API key for your chosen provider
ANTHROPIC_API_KEY=your-anthropic-api-key
# or
OPENROUTER_API_KEY=your-openrouter-api-key
# or
OPENAI_API_KEY=your-openai-api-key
# Select model appropriate for your provider
DEFAULT_MODEL=claude-sonnet-5
详细供应商配置见 PROVIDERS.md。
依赖¶
核心:
- 根目录
ch5安装使用 Python 3.12 anthropic- Anthropic APIopenai- OpenAI/OpenRouter APIpython-dotenv- 配置
可选(增强能力):
PyPDF2- PDF 阅读requests、beautifulsoup4、html2text- WebFetch
无需命令行工具! 无 Homebrew 的 macOS 也可运行。
支持的供应商¶
- Anthropic - 直连 Claude
- OpenRouter - Claude / GPT / Gemini / Llama 等
- OpenAI - 直连 GPT
Agent 自动处理各供应商不同的 API 格式。
OpenRouter 通用兜底¶
不必持有直连 Anthropic/OpenAI key。若所请求直连供应商的 key 缺失,且设置了
OPENROUTER_API_KEY,则经 OpenAI 兼容 SDK 透明回退到 OpenRouter:
PROVIDER=anthropic且有ANTHROPIC_API_KEY→ Anthropic SDK(默认行为)。PROVIDER=anthropic无ANTHROPIC_API_KEY(但有OPENROUTER_API_KEY)→ 走 OpenRouter。PROVIDER=openai且有OPENAI_API_KEY→ OpenAI SDK。PROVIDER=openai无OPENAI_API_KEY(但有OPENROUTER_API_KEY)→ 走 OpenRouter。
回退时原生模型 id 加前缀/映射为 OpenRouter id:
| Requested model | OpenRouter id used |
|---|---|
claude-sonnet-* (e.g. claude-sonnet-5) |
anthropic/claude-sonnet-4.6 |
claude-haiku-* |
anthropic/claude-haiku-4.5 |
claude-opus-* / other claude-* |
anthropic/claude-opus-4.8 |
gpt-* / o1-* (e.g. gpt-5.6-luna) |
openai/<model> |
already prefixed (vendor/model) |
passed through unchanged |
仅持有 OPENROUTER_API_KEY 时例如:
# No ANTHROPIC_API_KEY needed — falls back to OpenRouter automatically
python main.py --provider anthropic --model claude-sonnet-5 -p "..."
# gpt-5.6-luna routed through OpenRouter (no OPENAI_API_KEY needed)
python main.py --provider openai --model gpt-5.6-luna -p "..."
若要指定 OpenRouter 模型且不做映射,显式设 PROVIDER=openrouter 与 vendor/model id。
用法¶
命令行入口(main.py)¶
main.py 是唯一推荐入口,统一 argparse。运行
python main.py --help 查看完整中文帮助:
主要参数:
| 参数 | 说明 |
|---|---|
| (无参数) | 进入交互式对话(默认行为) |
-p, --prompt "任务" |
非交互模式:执行单个任务后退出,适合脚本 / CI |
--list-tools |
离线列出全部已注册工具及简介(无需 API Key,可用于自检) |
--provider {anthropic,openai,openrouter} |
临时覆盖 .env 中的 PROVIDER |
--model 模型名 |
临时覆盖 .env 中的 DEFAULT_MODEL |
--base-url URL |
临时覆盖 API Base URL(自建网关 / 兼容 OpenAI 的服务) |
--max-iterations N |
单个任务的最大 Agent 迭代轮数(默认 50) |
--no-color |
禁用彩色输出(无 TTY 时自动禁用) |
快速自检(离线,无需 API Key)¶
$ python main.py --list-tools
共 16 个工具:
Task Launch a new agent to handle complex, multi-step tasks autonomously.
Bash Executes a given bash command in a persistent shell session ...
Glob - Fast file pattern matching tool that works with any codebase size
Grep A powerful search tool built on ripgrep
...
端到端示例:真实编码任务¶
配置好 .env(见上文 Configuration)后:
成功时的终端输出结构大致如下(示意,实际轮次/调用次数取决于模型):
✓ Agent initialized successfully
You: 创建 hello_world.py ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔧 Calling tool: Write
✓ Completed (call #1)
✓ No lint errors
File: hello_world.py
🔧 Calling tool: Bash
✓ Completed (call #2)
Output:
Hello, World!
Hello, Alice!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Task completed!
Iterations: 2
Tool calls: 2
判定成功的标志:Agent 依次调用
Write写文件、Bash运行脚本, 终端出现脚本的真实输出,并以✅ Task completed!收尾。 (quickstart.py是同一任务的脚本化版本,可作对照。)
交互式对话(默认)¶
功能:
- 🎨 彩色输出
- ⚡ 实时流式响应
- 🔧 现场展示工具执行
- 📊 内置 status 命令
- 💬 对话历史
- 🔄 reset 重新开始
会话内命令:
/help- 帮助/quit或/exit- 退出/reset- 清空对话历史/clear- 清屏/status- Agent 状态(工具调用、TODO 等)
其他示例脚本(均需 API Key)¶
python quickstart.py # 基础快速上手(与上文端到端示例同款任务)
python example_complex_task.py # 复杂多步任务
python example_with_system_hints.py # 系统提示(System Hint)技术演示
编程方式调用¶
from agent import CodingAgent
agent = CodingAgent(api_key="your-key")
for event in agent.run("List all Python files"):
if event["type"] == "text_delta":
print(event["delta"], end="", flush=True)
elif event["type"] == "done":
print("\n✅ Done!")
纯 Python Grep 实现¶
Grep 完全用纯 Python 实现,不依赖 grep/rg 等,功能对齐 ripgrep:
# Example: Search for pattern in files
{
"name": "Grep",
"input": {
"pattern": "def.*test",
"path": "/path/to/search",
"output_mode": "content",
"-i": True, # Case insensitive
"-C": 3, # 3 lines context
"-n": True, # Show line numbers
"glob": "*.py", # Only Python files
"multiline": False # Single line matching
}
}
能力:
- ✅ 完整正则(Python
re) - ✅ 大小写不敏感(
-i) - ✅ 上下文行(
-A、-B、-C) - ✅ 行号(
-n) - ✅ 多行模式
- ✅ Glob(
glob) - ✅ 文件类型(
type) - ✅ 输出模式:
content、files_with_matches、count - ✅ Head limit
- ✅ 递归目录
- ✅ 跳过二进制
- ✅ 跳过隐藏文件/目录
架构¶
模块化工具系统¶
每个工具继承 BaseTool:
class MyTool(BaseTool):
@property
def name(self) -> str:
return "MyTool"
def _execute_impl(self, params: Dict[str, Any]) -> Dict[str, Any]:
# Tool implementation
return {"result": "success"}
工具注册表¶
ToolRegistry 将工具名映射到实现:
registry = ToolRegistry()
tool = registry.get_tool("Grep", system_state)
result = tool.execute(params)
系统状态¶
SystemState 跟踪:
- 当前工作目录
- 工具调用次数
- TODO 列表
- Shell 会话
- 环境信息
系统提示注入¶
每次 LLM 调用前注入:
<system_hint>
# System State
Current Time: 2025-10-12 15:30:45
Working Directory: chapter5/coding-agent
OS: Darwin
Python: Python 3.12.0
# Tool Call Statistics
- Grep: 2 calls
- Write: 1 calls
# Current TODO List
✅ [1] Search for files (completed)
🔄 [2] Implement feature (in_progress)
⬜ [3] Write tests (pending)
</system_hint>
设计原则¶
1. 纯 Python 实现¶
为何: 最大可移植性与兼容性
- 任意有 Python 的系统
- 无需 Homebrew、apt 等
- 跨平台行为一致
2. 模块化工具架构¶
为何: 可维护、可扩展
- 工具自包含
- 易新增、易单测
- 关注点分离清晰
3. 无命令行依赖¶
为何: 可靠与可控
- Grep:纯 Python 正则
- Glob:
pathlib.glob() - LS:
os/pathlib - 核心路径不靠 subprocess
- 行为完全可控
4. System Hint 自我感知¶
为何: 更好的 Agent 行为
- 工具调用计数防死循环
- TODO 保持任务焦点
- 提供环境上下文
- 支持自我监控
与第 2 章对照¶
| Technique | Status | Implementation |
|---|---|---|
| Standard OpenAI Tool Format | ✅ | Anthropic SDK |
| Streaming Tool Calls | ✅ | Real-time JSON delta parsing |
| Parallel Tool Calls | ✅ | Multiple tools per response |
| Pure Python Tools | ✅ | No command-line dependencies |
| Grep without rg | ✅ | Pure Python regex search |
| Timestamps | ✅ | All messages/tools |
| Tool Call Counting | ✅ | Warns at 3+ |
| TODO List | ✅ | TodoWrite tool |
| System State | ✅ | Working dir, OS, Python |
| Persistent Shell | ✅ | Shell sessions |
| Auto Lint Detection | ✅ | After Write/Edit/MultiEdit |
配置(.env)¶
# Required
ANTHROPIC_API_KEY=your_key_here
# Optional
DEFAULT_MODEL=claude-sonnet-5
MAX_ITERATIONS=50
MAX_TOKENS=8192
添加新工具¶
- 在
tools/新建文件:
# tools/my_tool.py
from .base import BaseTool
class MyTool(BaseTool):
@property
def name(self) -> str:
return "MyTool"
def _execute_impl(self, params):
# Implementation
return {"result": "success"}
- 在
tools/__init__.py注册:
- 加入
tool_registry.py:
- 在
tools.json增加定义
故障排查¶
"No module named 'tools'"¶
请在项目目录运行:
Grep 找不到文件¶
检查:
- 路径是否正确
- 模式是否为合法正则
- Glob 是否匹配目标文件
- 文件是否为可搜索文本(非二进制)
Shell 命令失败¶
确认:
/bin/bash可用- 工作目录存在
- 命令引号正确
测试¶
130+ 用例覆盖主要工具能力。
运行测试¶
# 从仓库根目录安装第 5 章环境与测试依赖
uv sync --locked --python 3.12 --extra ch5 --extra dev
# 切换目录前先激活环境:
# macOS/Linux:
source .venv/bin/activate
# Windows PowerShell:.\.venv\Scripts\Activate.ps1
# Windows cmd:.venv\Scripts\activate.bat
cd chapter5/coding-agent
# Run all tests
pytest
# Run with coverage
pytest --cov=tools --cov-report=html
# Run specific tool tests
pytest tests/test_grep_tool.py
pytest tests/test_bash_tool.py
# Verbose output
pytest -v
覆盖情况¶
- 130+ 测试,14 个测试文件
- 2,200+ 行测试代码
- tools.json 主要特性均有覆盖
- 集成测试覆盖工具链与 system hints
详见 tests/README.md。
学习路径¶
- 从示例开始:
python main.py(交互 CLI) - 跑 quickstart:
python quickstart.py - 看 system hints:
python example_with_system_hints.py - 研读 Grep:
tools/grep_tool.py - 跑测试:
pytest -v - 读第 2 章:理解理论
- 加自定义工具:扩展系统
参考¶
- 第 2 章:上下文工程(AI Agent 书)
- 工具规范:
tools.json - 系统提示:
system-prompt.md - Anthropic Claude API:https://docs.anthropic.com/
关键优势¶
- 无外部工具依赖
- 纯 Python
- 无需 rg、grep、find 等
-
适合未装 Homebrew 的 Mac
-
模块化架构
- 每工具一文件
- 易读易改
-
关注点分离
-
可生产使用
- 完善错误处理
- 自动 lint
- system hints 提升可靠性
-
流式输出改善体验
-
教学价值
- 理解工具内部
- 纯 Python 文件操作
- 正则搜索实现
- Agent 架构模式
许可证¶
MIT
贡献¶
教学实现,欢迎改编与扩展!
Built with pure Python for maximum portability and learning! 🐍✨
Notes / 说明¶
- Offline self-check:
python main.py --list-tools(no API key). / 离线自检:python main.py --list-tools(无需 API Key)。 - Commands, code blocks, paths, and env vars are identical in both language sections. / 命令、代码块、路径与环境变量在中英文两侧保持一致。
- Path examples use project-relative paths. / 路径示例使用项目相对路径。