编辑此页 / 查看本页的源代码
Comprehensive Coding Agent - Pure Python Implementation¶
A production-ready AI coding agent built with Claude, implementing all techniques from Chapter 2 with pure Python tools - no command-line dependencies required!
🌟 Key Features¶
✅ Pure Python Implementation¶
All tools implemented without command-line dependencies:
- ❌ No grep, rg (ripgrep), find commands needed
- ❌ No dependency on system utilities
- ✅ 100% pure Python implementations
- ✅ Works on any system with Python 3.8+
- ✅ 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 support
- Write - File writing with auto lint checking
- Edit - Search and replace editing
- MultiEdit - 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 matching
- LS - Directory listing
Shell Operations:
- Bash - Persistent shell sessions
- BashOutput - Background job output
- KillBash - Terminate shells
Project Management:
- TodoWrite - Task list management
- ExitPlanMode - Plan mode exit
Advanced:
- NotebookEdit - Jupyter notebook editing
- WebFetch - 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¶
# Navigate to project directory
cd /Users/boj/ai-agent-book/projects/week5/coding-agent
# Install dependencies
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=sk-ant-api03-...
# or
OPENROUTER_API_KEY=sk-or-v1-...
# or
OPENAI_API_KEY=sk-...
# Select model appropriate for your provider
DEFAULT_MODEL=claude-sonnet-5
See PROVIDERS.md for detailed provider configuration guide.
Requirements¶
Core dependencies:
- Python 3.8+
- anthropic - For Anthropic API
- openai - For OpenAI/OpenRouter API
- python-dotenv - For configuration
Optional (for enhanced features):
- PyPDF2 - For PDF reading
- requests, 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¶
命令行入口(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
...
端到端示例:让 Agent 完成一个真实编码任务¶
配置好 .env(见上文 Configuration)后,用一条命令让 Agent 创建并运行一个脚本:
成功时的终端输出结构大致如下(示意,实际轮次/调用次数取决于模型):
✓ 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是同一任务的脚本化版本,可作对照。)
交互式对话(默认)¶
不带 -p 直接运行即进入交互式会话:
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
会话内命令(在对话中输入):
- /help - Show help message
- /quit or /exit - Exit the CLI
- /reset - Reset conversation history
- /clear - Clear the screen
- /status - Show agent status (tool calls, TODOs, etc.)
其他示例脚本(均需 API Key)¶
python quickstart.py # 基础快速上手(与上文端到端示例同款任务)
python example_complex_task.py # 复杂多步任务
python example_with_system_hints.py # 系统提示(System Hint)技术演示
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 re module)
- ✅ Case insensitive search (-i)
- ✅ Context lines (-A, -B, -C)
- ✅ Line numbers (-n)
- ✅ Multiline mode
- ✅ Glob filtering (glob parameter)
- ✅ File type filtering (type parameter)
- ✅ 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: /Users/boj/coding-agent
OS: Darwin
Python: Python 3.11.5
# 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 os and pathlib
- 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 file:
# 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 at /bin/bash
- Working directory exists
- Commands are properly quoted
🧪 Testing¶
Comprehensive test suite with 130+ tests covering all tool features.
Run Tests¶
# Install test dependencies
pip install -r requirements.txt
# 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! 🐍✨