Starphix
Agentic Engineering / Sources
The Lab / Sources / Agentic Engineering / Domains/Coding-Agents.md

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

  1. Always run linters/type checkers before committing
  2. Generate tests first (TDD)
  3. Small, focused changes - easier to review
  4. Self-consistency - generate multiple solutions, pick best
  5. Verify in sandbox - never trust generated code blindly

Repository Navigation

  1. Use LSP for accurate navigation
  2. Embeddings + grep for semantic + keyword search
  3. Git history for context on why code exists
  4. Dependency graphs for impact analysis

Testing

  1. Test in sandbox - never run untrusted code on host
  2. Run full test suite before declaring done
  3. Property-based testing for edge cases
  4. Mutation testing for test quality

Security

  1. Never commit secrets - use env vars, secret managers
  2. Scan dependencies - SCA tools in CI
  3. Validate inputs - never trust generated code
  4. Least privilege - sandbox all execution

  • 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.

From the Agentic Engineering research vault · CC BY 4.0 · all notes · raw markdown