This project is NOT about code generation. It's about validation, parsing, and analysis that saves agent tokens.
Core Principle: Build what agents waste tokens on, avoid what they do well.
✅ Validators - Catch errors before execution
- Syntax validation (shell, Python, YAML, JSON, TOML)
- Type hint validation
- Security validation (injection, secrets, misconfigurations)
- Schema validation (CI/CD configs, API specs)
✅ Parsers - Convert unstructured → structured
- AST parsing (Python, shell)
- Tool output parsing (ruff, mypy, pytest, git)
- Log parsing and extraction
- Configuration file parsing
✅ Extractors - Pull specific data
- Function signatures
- Docstring information
- Import statements
- Complexity metrics
- Schema information
✅ Formatters - Apply deterministic rules
- Argument escaping (shell, SQL)
- Import sorting
- Docstring formatting (Google, NumPy, Sphinx styles)
- Type hint normalization
✅ Scanners - Rule-based detection
- Secret detection (API keys, tokens, passwords)
- Security anti-patterns (SQL injection, XSS, eval usage)
- Performance anti-patterns (N+1 queries, unbounded loops)
- Compliance checking (GDPR, accessibility)
❌ Code Generators - Agents excel at creative logic
- Don't build full function/class generators
- Don't build template systems
- Don't build project scaffolding
- Don't build documentation generators
❌ Architecture Tools - Requires judgment
- Don't build design pattern generators
- Don't build architecture decision tools
- Don't make opinionated structural choices
❌ Refactoring Tools - Agents reason through this
- Don't build code transformation tools
- Don't build migration generators
- Don't build optimization engines
src/coding_open_agent_tools/
├── _decorators.py # Centralized decorator imports
├── confirmation.py # Smart confirmation system (3 modes)
├── exceptions.py # Custom exceptions
├── types.py # Type definitions
├── helpers.py # Tool loading and management (11 functions)
│
├── navigation/ # Shared navigation utilities
│ └── shared.py # Common validation/extraction logic
│
├── analysis/ # AST parsing, complexity, imports (14 functions)
│ ├── ast_parsing.py # Python AST operations
│ ├── complexity.py # Cyclomatic complexity
│ ├── imports.py # Import analysis
│ ├── patterns.py # Code pattern detection
│ └── secrets.py # Secret detection
│
├── git/ # Git repository operations (14 submodules, 79 functions)
│ ├── branches.py # Branch management
│ ├── commits.py # Commit analysis
│ ├── config.py # Repository configuration
│ ├── conflicts.py # Merge conflict detection
│ ├── diffs.py # Diff operations
│ ├── health.py # Repository health checks
│ ├── history.py # Git history analysis
│ ├── hooks.py # Git hooks management
│ ├── remotes.py # Remote repository operations
│ ├── security.py # Security scanning
│ ├── status.py # Working tree status
│ ├── submodules.py # Submodule management
│ ├── tags.py # Tag operations
│ └── workflows.py # CI/CD workflows
│
├── python/ # Python-specific tools (5 submodules, 32 functions)
│ ├── navigation.py # Code navigation (17 functions, 70-95% token savings)
│ ├── validators.py # Syntax validation
│ ├── analyzers.py # Code analysis
│ ├── extractors.py # Data extraction
│ └── formatters.py # Code formatting
│
├── shell/ # Shell script tools (5 submodules, 13 functions)
│ ├── validators.py # Syntax validation
│ ├── security.py # Security scanning
│ ├── analyzers.py # Script analysis
│ ├── formatters.py # Argument escaping
│ └── extractors.py # Command extraction
│
├── config/ # Configuration file tools (6 submodules, 28 functions)
│ ├── env_parser.py # .env file operations
│ ├── extractors.py # Value extraction (YAML/TOML/JSON)
│ ├── parsers.py # INI/properties/XML parsing
│ ├── security.py # Gitignore security
│ ├── validators.py # Format validation
│ └── utils.py # Helper utilities
│
├── database/ # SQLite operations (5 submodules, 18 functions)
│ ├── operations.py # Database operations
│ ├── query_builder.py # Safe query building
│ ├── schema.py # Schema inspection
│ └── utils.py # Helper utilities
│
├── profiling/ # Performance profiling (8 functions)
│ ├── memory.py # Memory profiling
│ ├── performance.py # Performance analysis
│ └── timing.py # Execution timing
│
├── quality/ # Code quality analysis (7 functions)
│ ├── parsers.py # Tool output parsing
│ └── analysis.py # Quality metrics
│
└── [language]/navigation.py # Per-language navigation (8 languages)
├── cpp/ # C++ (17 functions)
├── csharp/ # C# (17 functions)
├── go/ # Go (17 functions)
├── java/ # Java (17 functions)
├── javascript/ # JavaScript/TypeScript (17 functions)
├── python/ # Python (included in python/ above)
├── ruby/ # Ruby (17 functions)
└── rust/ # Rust (17 functions)
Total: 286 functions across 8 core modules + 7 language-specific modules
All agent tools use centralized decorator imports with conditional fallback:
# In _decorators.py
try:
from strands import tool as strands_tool
except ImportError:
# No-op decorator if strands not installed
def strands_tool(func: Callable[..., Any]) -> Callable[..., Any]: # type: ignore[no-redef]
return func
# In any module
from coding_open_agent_tools._decorators import strands_tool
@strands_tool
def your_function(param1: str, param2: str) -> dict[str, str]:
"""Function description."""
# Implementation
return {"result": "value"}Why: Zero required dependencies - package works without strands installed. Graceful degradation.
Common functionality extracted to shared modules to reduce code duplication:
# In navigation/shared.py
def validate_source_code(source_code: str, param_name: str = "source_code") -> None:
"""Validate source code parameter."""
if not isinstance(source_code, str):
raise TypeError(f"{param_name} must be a string")
if not source_code.strip():
raise ValueError(f"{param_name} cannot be empty")
def validate_identifier(identifier: str, param_name: str) -> None:
"""Validate identifier parameter."""
if not isinstance(identifier, str):
raise TypeError(f"{param_name} must be a string")
if not identifier.strip():
raise ValueError(f"{param_name} cannot be empty")
if not identifier.replace("_", "").isalnum():
raise ValueError(f"{param_name} must be a valid identifier")
# In any navigation module
from coding_open_agent_tools.navigation.shared import validate_source_code, validate_identifier
@strands_tool
def get_function_signature(source_code: str, function_name: str) -> dict[str, str]:
validate_source_code(source_code)
validate_identifier(function_name, "function_name")
# Implementation
passWhy: Consistent validation, reduced duplication, easier maintenance.
All functions return dict[str, str] for Google ADK compatibility:
@strands_tool
def validate_python_syntax(source_code: str) -> dict[str, str]:
"""Validate Python source code syntax."""
try:
ast.parse(source_code)
return {
"is_valid": "true", # Note: string, not boolean
"error_message": "",
"line_number": "0", # Note: string, not int
"column_offset": "0",
"error_type": "",
}
except SyntaxError as e:
return {
"is_valid": "false",
"error_message": str(e.msg) if e.msg else "Syntax error",
"line_number": str(e.lineno) if e.lineno else "0",
"column_offset": str(e.offset) if e.offset else "0",
"error_type": "SyntaxError",
}Why: Google ADK requires JSON-serializable types only. Agents can easily parse string values.
All functions validate inputs and raise appropriate exceptions:
@strands_tool
def analyze_code(file_path: str, threshold: str) -> dict[str, str]:
"""Analyze code complexity."""
# Type validation
if not isinstance(file_path, str):
raise TypeError("file_path must be a string")
if not isinstance(threshold, str):
raise TypeError("threshold must be a string")
# Value validation
if not file_path.strip():
raise ValueError("file_path cannot be empty")
# Numeric validation (when string represents number)
try:
threshold_int = int(threshold)
if threshold_int < 0:
raise ValueError("threshold must be non-negative")
except ValueError as e:
raise ValueError(f"threshold must be a valid integer: {e}")
# File existence validation
if not os.path.exists(file_path):
raise FileNotFoundError(f"File not found: {file_path}")
# Implementation
passWhy: Fail fast with clear error messages. Prevents cryptic failures downstream.
Three-mode confirmation handling for write/delete operations:
from coding_open_agent_tools.confirmation import check_user_confirmation
def write_file(file_path: str, content: str, skip_confirm: str) -> dict[str, str]:
"""Write file with smart confirmation."""
# Convert string to boolean (ADK compliance)
skip = skip_confirm.lower() == "true"
# Check confirmation
confirmed = check_user_confirmation(
operation="write file",
target=file_path,
skip_confirm=skip,
preview_info=f"{len(content)} bytes"
)
if not confirmed:
return {
"success": "false",
"error": "Operation cancelled by user",
"path": file_path,
}
# Proceed with write
with open(file_path, 'w') as f:
f.write(content)
return {
"success": "true",
"error": "",
"path": file_path,
}Modes:
-
Bypass Mode -
skip_confirm=TrueorBYPASS_TOOL_CONSENT=trueenv var- Proceeds immediately without prompts
- Perfect for CI/CD and automation
-
Interactive Mode - Terminal with
skip_confirm=False- Prompts user with
y/nconfirmation - Shows preview info (file sizes, etc.)
- Prompts user with
-
Agent Mode - Non-TTY with
skip_confirm=False- Raises
CONFIRMATION_REQUIREDerror with instructions - LLM agents can ask user and retry with
skip_confirm=True
- Raises
Why: Safe by default, adapts to context (interactive vs automation).
- All tools decorated with
@strands_tool - Optional dependency (graceful fallback)
- Import pattern:
from strands import tool as strands_tool - Conditional import with no-op fallback
- Works with
@strands_tooldecorated functions - Requires JSON-serializable returns (
dict[str, str]) - No default parameters allowed
- Comprehensive docstrings for LLM understanding
- Works with standard Python callables
- No decorator needed
- Can use any function directly
- Standard Python functions work with any framework
- Decorator is transparent to non-Strands frameworks
- Type hints provide IDE autocomplete
- ✅ 100% ruff compliance - No exceptions
- ✅ 100% mypy compliance - Full type coverage
- ✅ 80%+ test coverage - Every function tested
- ✅ Google ADK compliance - JSON-serializable only
- ✅ Zero external dependencies (core) - Prefer stdlib
tests/
├── analysis/
│ ├── test_ast_parsing.py
│ ├── test_complexity.py
│ └── ...
├── git/
│ ├── test_health.py
│ ├── test_security.py
│ └── ...
├── python/
│ ├── test_navigation.py
│ ├── test_validators.py
│ └── ...
└── [module]/
└── test_*.py
Type Validation Tests:
def test_invalid_param_type(self) -> None:
"""Test TypeError when param is not a string."""
with pytest.raises(TypeError, match="param must be a string"):
function_name(123, "valid") # type: ignoreValue Validation Tests:
def test_empty_param(self) -> None:
"""Test ValueError when param is empty."""
with pytest.raises(ValueError, match="param cannot be empty"):
function_name("", "valid")Path Validation Tests:
def test_file_not_found(self, tmp_path: Path) -> None:
"""Test FileNotFoundError for missing file."""
nonexistent = tmp_path / "missing.py"
with pytest.raises(FileNotFoundError):
function_name(str(nonexistent))Happy Path Tests:
def test_success_case(self, tmp_path: Path) -> None:
"""Test successful operation."""
result = function_name("valid_input", "valid_param")
assert result["success"] == "true"
assert result["error"] == ""
assert "expected_key" in resultEdge Case Tests:
def test_edge_case_empty_result(self) -> None:
"""Test handling of empty result."""
result = function_name("input_with_no_matches")
assert result["count"] == "0"
assert result["items"] == "[]"Mocked Subprocess Tests:
@patch("subprocess.run")
def test_git_command(self, mock_run: MagicMock) -> None:
"""Test git command execution."""
mock_run.return_value = MagicMock(
returncode=0,
stdout="mocked output",
stderr=""
)
result = git_function("/path/to/repo")
assert result["success"] == "true"
mock_run.assert_called_once()- Overall: 83% coverage (571 tests passing)
- Critical modules: 90%+ coverage
- Git modules: 80-93% coverage
- Navigation modules: 68-88% coverage
- Python module: 93% coverage
- Config module: 86% coverage
Core functionality uses stdlib only. Optional dependencies enhance capabilities.
✅ ADD optional dependency if:
- It provides substantial value (10x better than stdlib approach)
- It's pip-installable Python library (not external binary)
- There's graceful fallback to stdlib
- It's actively maintained (1000+ stars, recent commits)
- It's Python-native (can import, not subprocess-only)
❌ DON'T add optional dependency if:
- Stdlib solution is "good enough" (80% as good)
- It's a Go/Rust binary requiring subprocess
- No graceful fallback possible
- Maintenance concerns (unmaintained, <500 stars)
- Only marginal improvement over stdlib
Why detect-secrets: Production-grade secret detection as optional enhancement
# In pyproject.toml
[project.optional-dependencies]
enhanced-security = ["detect-secrets>=1.5.0"]Install with: pip install coding-open-agent-tools[enhanced-security]
Implementation Pattern:
def scan_for_secrets_enhanced(
content: str,
use_detect_secrets: str # "true" or "false" (ADK compliance)
) -> dict[str, str]:
"""Scan content for secrets with optional detect-secrets integration.
Falls back to stdlib regex if detect-secrets not installed.
"""
if use_detect_secrets == "true":
try:
from detect_secrets import SecretsCollection
from detect_secrets.settings import default_settings
# Use detect-secrets for comprehensive scanning
return _scan_with_detect_secrets(content)
except ImportError:
# Graceful fallback to stdlib
return _scan_with_stdlib_regex(content)
else:
return _scan_with_stdlib_regex(content)Why This Works:
- ✅ Default behavior uses stdlib (no dependencies)
- ✅ Users opt-in for enhanced detection
- ✅ Graceful degradation if not installed
- ✅ Clear benefit: 1000+ patterns vs ~30 stdlib patterns
- ✅ Python-native library, not external binary
For enhanced code navigation across multiple languages:
[project.optional-dependencies]
enhanced-navigation = [
"tree-sitter>=0.20.0",
"tree-sitter-language-pack>=0.1.0"
]Benefits:
- Accurate parsing for 8 languages (C++, C#, Go, Java, JavaScript, Python, Ruby, Rust)
- Better handling of complex syntax
- More robust navigation
Fallback: Basic regex-based navigation when not installed
- 70-95% reduction in common workflows
- Navigation tools: 70-95% token savings vs reading full files
- Validation: Prevents retry loops, saves 30-50% tokens
- Parsing: Structured data extraction, 60-80% token savings
- <100ms for most operations
- AST parsing: Near-instant for typical files
- Git operations: 50-500ms depending on repo size
- Navigation: <50ms for function lookup
- Validation catches 95%+ of errors before execution
- Syntax validation: Prevents Python/shell syntax errors
- Security scanning: Catches injection patterns, secrets
- Type validation: Prevents type-related failures
Track token savings, not feature count:
- Retry loop prevention: Validation catches X% of errors
- Parsing efficiency: Convert unstructured → structured in <100ms
- Token savings: Document 30-50% reduction in specific workflows
- Error prevention: 95%+ syntax/security error detection
- Parse, don't generate
- Validate early, save tokens
- Deterministic operations only
- If agents do it well, skip it
- Prevent errors > Generate code
When in doubt, ask: "Does this save agent tokens or prevent retry loops?"
If no, it probably doesn't belong here.