Coding Agents
Agents specialized for software development: code generation, refactoring, testing, and repository understanding.
Coding Agent Capabilities
| Capability | Description | Tools |
|---|---|---|
| Code Generation | Write new code from specs | LSP, templates, snippets |
| Refactoring | Restructure without behavior change | AST, codemods, LSP |
| Code Review | Find bugs, style, security issues | Linters, SAST, LLMs |
| Testing | Generate, run, debug tests | pytest, jest, coverage |
| Debugging | Trace, breakpoint, inspect | Debugger, logs, REPL |
| Repository Understanding | Navigate, search, analyze | Git, grep, LSP, embeddings |
| Documentation | Generate, update docs | Docstrings, markdown |
| Dependency Management | Update, audit, resolve | Package managers, lockfiles |
| CI/CD Integration | Pipeline, deploy, rollback | GitHub Actions, GitLab CI |
| Architecture | Design, diagram, decision records | ADR, C4, Mermaid |
Agent Architectures for Coding
1. Repository-Aware Agent
class RepoAwareCodingAgent:
def __init__(self, repo_path: str):
self.repo_path = Path(repo_path)
self.index = self._build_index()
def _build_index(self) -> RepoIndex:
return RepoIndex(
files=self._discover_files(),
symbols=self._extract_symbols(),
dependencies=self._analyze_dependencies(),
git_history=self._analyze_git_history()
)
async def answer_question(self, question: str) -> Answer:
# Retrieve relevant context
context = self.index.retrieve(question, k=10)
# Generate answer with citations
return await self.llm.generate(
prompt=f"Question: {question}\n\nContext:\n{context}\n\nAnswer with file references:",
tools=[self.index.get_file, self.index.get_symbol]
)
2. Test-Driven Agent
class TDDAgent:
def __init__(self, project_root: Path):
self.project_root = project_root
self.test_runner = TestRunner(project_root)
async def implement_feature(self, spec: FeatureSpec) -> Implementation:
# 1. Generate failing tests from spec
tests = await self.generate_tests(spec)
await self.write_tests(tests)
# 2. Run tests (should fail)
result = await self.test_runner.run(tests)
assert not result.passed
# 3. Implement code to pass tests
code = await self.generate_code(tests, spec)
# 4. Iterate until passing
for attempt in range(5):
await self.write_code(code)
result = await self.test_runner.run(tests)
if result.passed:
break
code = await self.fix_code(code, result.failures)
# 5. Refactor
code = await self.refactor(code, tests)
return Implementation(code=code, tests=tests)
3. Code Review Agent
class CodeReviewAgent:
def __init__(self, repo: GitRepo):
self.repo = repo
self.linters = self._setup_linters()
self.security_scanner = SecurityScanner()
async def review_pr(self, pr_number: int) -> ReviewResult:
pr = self.repo.get_pr(pr_number)
diff = pr.get_diff()
# Parallel analysis
results = await asyncio.gather(
self.check_style(diff),
self.check_types(diff),
self.check_security(diff),
self.check_performance(diff),
self.check_tests(diff),
self.check_docs(diff),
self.suggest_improvements(diff)
)
return ReviewResult(
style_issues=results[0],
type_issues=results[1],
security_issues=results[2],
performance_issues=results[3],
test_gaps=results[4],
doc_gaps=results[5],
suggestions=results[6]
)
Core Tools for Coding Agents
Language Server Protocol (LSP)
class LSPClient:
def __init__(self, language: str, project_root: Path):
self.language = language
self.project_root = project_root
self.server = self._start_server()
def _start_server(self) -> LSPServer:
servers = {
"python": ["pyright-langserver", "--stdio"],
"typescript": ["typescript-language-server", "--stdio"],
"go": ["gopls"],
"rust": ["rust-analyzer"],
"java": ["jdtls"],
"cpp": ["clangd"]
}
return LSPServer(servers[self.language])
async def goto_definition(self, file: str, line: int, col: int) -> Location:
return await self.server.request("textDocument/definition", {
"textDocument": {"uri": f"file://{file}"},
"position": {"line": line, "character": col}
})
async def find_references(self, file: str, line: int, col: int) -> list[Location]:
return await self.server.request("textDocument/references", {...})
async def get_hover(self, file: str, line: int, col: int) -> Hover:
return await self.server.request("textDocument/hover", {...})
async def get_diagnostics(self, file: str) -> list[Diagnostic]:
return await self.server.request("textDocument/publishDiagnostics", {...})
Code Search & Navigation
class CodeNavigator:
def __init__(self, project_root: Path):
self.project_root = project_root
self.embeddings = CodeEmbeddings(project_root)
async def search(self, query: str, k: int = 10) -> list[CodeSnippet]:
# Semantic search
semantic_results = await self.embeddings.search(query, k)
# Keyword search (grep)
keyword_results = await self.grep_search(query, k)
# Merge & rerank
return self.rerank(semantic_results + keyword_results, query)
async def grep_search(self, pattern: str, k: int) -> list[CodeSnippet]:
# Use ripgrep for fast keyword search
result = subprocess.run(
["rg", "--json", pattern, str(self.project_root)],
capture_output=True, text=True
)
return self._parse_rg_output(result.stdout)[:k]
Code Execution & Testing
class CodeExecutor:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
async def run_tests(self, test_files: list[Path]) -> TestResult:
return await self.sandbox.run(
f"pytest {' '.join(str(f) for f in test_files)} -v --json-report"
)
async def run_linter(self, files: list[Path]) -> LintResult:
return await self.sandbox.run(f"ruff check {' '.join(str(f) for f in files)}")
async def run_type_check(self, files: list[Path]) -> TypeCheckResult:
return await self.sandbox.run(f"mypy {' '.join(str(f) for f in files)}")
async def run_code(self, code: str, language: str = "python") -> ExecutionResult:
return await self.sandbox.run_code(code, language)
Git Operations
class GitOperator:
def __init__(self, repo_path: Path):
self.repo = git.Repo(repo_path)
def get_diff(self, base: str = "HEAD", target: str = None) -> str:
if target:
return self.repo.git.diff(base, target)
return self.repo.git.diff(base)
def get_changed_files(self, base: str = "HEAD") -> list[str]:
return [item.a_path for item in self.repo.index.diff(base)]
def create_branch(self, name: str, base: str = "HEAD"):
self.repo.git.checkout("-b", name, base)
def commit(self, message: str, files: list[str] = None):
if files:
self.repo.index.add(files)
self.repo.index.commit(message)
def create_pr(self, title: str, body: str, base: str = "main") -> PR:
return self.github.create_pr(title, body, self.repo.active_branch.name, base)
Specialized Coding Agents
1. Frontend Agent
class FrontendAgent:
def __init__(self, project_root: Path):
self.project_root = project_root
self.framework = self._detect_framework()
def _detect_framework(self) -> str:
package_json = self.project_root / "package.json"
if package_json.exists():
deps = json.loads(package_json.read_text()).get("dependencies", {})
if "react" in deps: return "react"
if "vue" in deps: return "vue"
if "svelte" in deps: return "svelte"
if "next" in deps: return "nextjs"
return "vanilla"
async def create_component(self, spec: ComponentSpec) -> Component:
# Generate component with framework conventions
template = self.get_template(self.framework, spec.type)
code = template.render(spec.props)
# Add styles
if spec.styling == "css-modules":
styles = self.generate_css_modules(spec)
elif spec.styling == "tailwind":
styles = self.generate_tailwind(spec)
# Add tests
test_code = self.generate_component_test(spec)
return Component(
code=code,
styles=styles,
test=test_code,
storybook=spec.include_storybook
)
2. Backend Agent
class BackendAgent:
def __init__(self, project_root: Path):
self.project_root = project_root
self.framework = self._detect_framework()
self.orm = self._detect_orm()
async def create_api_endpoint(self, spec: APISpec) -> Endpoint:
# Generate route
route_code = self.generate_route(spec)
# Generate schema (Pydantic/Zod)
schema_code = self.generate_schema(spec.request, spec.response)
# Generate service layer
service_code = self.generate_service(spec)
# Generate tests
test_code = self.generate_tests(spec)
# Generate OpenAPI docs
openapi_code = self.generate_openapi(spec)
return Endpoint(
route=route_code,
schema=schema_code,
service=service_code,
tests=test_code,
docs=openapi_code
)
3. Database Agent
class DatabaseAgent:
def __init__(self, connection_string: str):
self.engine = create_engine(connection_string)
self.inspector = inspect(self.engine)
async def generate_migrations(self, schema_changes: list[SchemaChange]) -> Migration:
# Generate Alembic migration
ops = []
for change in schema_changes:
if change.type == "create_table":
ops.append(CreateTableOp(change.table))
elif change.type == "add_column":
ops.append(AddColumnOp(change.table, change.column))
elif change.type == "create_index":
ops.append(CreateIndexOp(change.table, change.columns))
return Migration(operations=ops)
async def optimize_query(self, query: str) -> OptimizationResult:
# Analyze query plan
plan = await self.explain_query(query)
# Suggest optimizations
suggestions = []
if plan.has_seq_scan:
suggestions.append("Add index for sequential scan")
if plan.has_nested_loop:
suggestions.append("Consider hash join or materialized view")
return OptimizationResult(plan=plan, suggestions=suggestions)
4. DevOps Agent
class DevOpsAgent:
def __init__(self, repo: GitRepo, kubeconfig: str = None):
self.repo = repo
self.k8s = KubernetesClient(kubeconfig) if kubeconfig else None
async def setup_ci_cd(self, spec: CICDSpec) -> Pipeline:
# Generate pipeline config
if spec.platform == "github":
config = self.generate_github_actions(spec)
elif spec.platform == "gitlab":
config = self.generate_gitlab_ci(spec)
elif spec.platform == "jenkins":
config = self.generate_jenkinsfile(spec)
# Add security scanning
config = self.add_security_scanning(config)
# Add deployment
if spec.deploy_target:
config = self.add_deployment(config, spec.deploy_target)
return Pipeline(config=config)
async def deploy(self, environment: str, version: str) -> DeploymentResult:
if self.k8s:
return await self.k8s.deploy(environment, version)
# ... other deployment targets
Coding Benchmarks
SWE-bench
# Real GitHub issues from popular repos
# Task: Fix issue given repo + issue description
# Metrics: Pass rate, patch quality
class SWEBenchEvaluator:
def __init__(self, dataset_path: str):
self.dataset = load_dataset(dataset_path)
async def evaluate(self, agent: CodingAgent) -> EvaluationResult:
results = []
for instance in self.dataset:
# Setup repo at commit before fix
repo = self.setup_repo(instance)
# Agent attempts fix
patch = await agent.generate_fix(
repo=repo,
issue=instance.issue_text
)
# Apply patch & test
result = self.apply_and_test(repo, patch, instance.tests)
results.append(result)
return EvaluationResult(
pass_rate=sum(r.passed for r in results) / len(results),
avg_patch_size=statistics.mean(len(r.patch) for r in results)
)
HumanEval / MBPP
class CodeGenerationEvaluator:
def __init__(self, dataset: str = "humaneval"):
self.dataset = load_dataset(dataset)
async def evaluate(self, agent: CodingAgent) -> EvaluationResult:
results = []
for problem in self.dataset:
# Generate solution
solution = await agent.generate_code(
prompt=problem.prompt,
signature=problem.signature
)
# Execute tests
result = await self.execute_tests(solution, problem.tests)
results.append(result)
return EvaluationResult(
pass_at_1=pass_at_k(results, k=1),
pass_at_10=pass_at_k(results, k=10),
pass_at_100=pass_at_k(results, k=100)
)
Best Practices
Code Quality
- Always run linters/type checkers before committing
- Generate tests first (TDD)
- Small, focused changes - easier to review
- Self-consistency - generate multiple solutions, pick best
- Verify in sandbox - never trust generated code blindly
Repository Navigation
- Use LSP for accurate navigation
- Embeddings + grep for semantic + keyword search
- Git history for context on why code exists
- Dependency graphs for impact analysis
Testing
- Test in sandbox - never run untrusted code on host
- Run full test suite before declaring done
- Property-based testing for edge cases
- Mutation testing for test quality
Security
- Never commit secrets - use env vars, secret managers
- Scan dependencies - SCA tools in CI
- Validate inputs - never trust generated code
- Least privilege - sandbox all execution
Related Notes
- Code Execution — Sandbox execution
- Function Calling — Code as tool
- MCP Protocol — Code tools via MCP
- Code Execution — Execution environments
- API Integration — API integration
- CI CD Best Practices — CI/CD for code
- Observability — Code observability
- Secure Coding — Secure coding
- Supply Chain Security — Dependency security
- Test Pyramid — Testing strategy
- Test Driven Development — TDD
- Design Patterns — Patterns in code
- Domain Driven Design — DDD in code
- Architecture Decision Records — ADRs for code
Sources: SWE-bench, HumanEval, MBPP, OpenAI Codex, GitHub Copilot, Cursor, Devin, Cody, Tabnine, Codeium, SWE-agent, OpenDevin, Aider, language server protocol, Tree-sitter, ripgrep, pytest, ruff, mypy, E2B, Modal, Daytona, GitHub Actions, GitLab CI, ArgoCD, Argo Workflows, Tekton, Dagger, Earthly.