Real-World Agent Projects
Advanced⏱70 min📖2 min readLesson 10 of 10

Real-World Agent Projects

Apply agentic AI techniques to code generation, code review, refactoring, testing, documentation, and DevOps automation.

Overview

This capstone lesson synthesizes everything you have learned into practical, real-world projects. Each project demonstrates how agentic AI techniques apply to common software engineering tasks.

100%
ℹ️Note

These projects are designed to be run with OpenCode or any agent framework. Each project includes the configuration, skill definitions, and expected outputs needed for successful execution.


Project 1: Automated Code Generation

Generate a complete REST API module from a specification using an agent.

100%
yaml
# project-configs/blog-api/skill.yaml name: blog-api-generator description: Generate a complete blog REST API from specifications version: "1.0.0" instructions: - path: instructions/generate-models.md - path: instructions/generate-routes.md - path: instructions/generate-tests.md tools: required: - read - write - glob - bash resources: - path: templates/fastapi-base.py.hbs - path: templates/sqlalchemy-model.py.hbs - path: templates/pytest-fixtures.py.hbs autoload: enabled: false
python
# Example: Agent generating a FastAPI blog module GENERATED_MODULE = """ # models.py from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey from sqlalchemy.sql import func from database import Base class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String(50), unique=True, nullable=False) email = Column(String(120), unique=True, nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now()) class Post(Base): __tablename__ = "posts" id = Column(Integer, primary_key=True, index=True) title = Column(String(200), nullable=False) content = Column(Text, nullable=False) author_id = Column(Integer, ForeignKey("users.id"), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) # schemas.py from pydantic import BaseModel, EmailStr from datetime import datetime from typing import Optional class UserCreate(BaseModel): username: str email: EmailStr class UserResponse(BaseModel): id: int username: str email: str created_at: datetime class PostCreate(BaseModel): title: str content: str class PostResponse(BaseModel): id: int title: str content: str author_id: int created_at: datetime updated_at: Optional[datetime] = None # routes.py from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from . import models, schemas from .database import get_db router = APIRouter(prefix="/api/v1", tags=["blog"]) @router.post("/users/", response_model=schemas.UserResponse, status_code=201) def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): db_user = models.User(**user.model_dump()) db.add(db_user) db.commit() db.refresh(db_user) return db_user @router.get("/posts/", response_model=list[schemas.PostResponse]) def list_posts(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)): return db.query(models.Post).offset(skip).limit(limit).all() @router.post("/posts/", response_model=schemas.PostResponse, status_code=201) def create_post(post: schemas.PostCreate, db: Session = Depends(get_db)): db_post = models.Post(**post.model_dump()) db.add(db_post) db.commit() db.refresh(db_post) return db_post @router.get("/posts/{post_id}", response_model=schemas.PostResponse) def get_post(post_id: int, db: Session = Depends(get_db)): post = db.query(models.Post).filter(models.Post.id == post_id).first() if not post: raise HTTPException(status_code=404, detail="Post not found") return post """

Project 2: Intelligent Code Review

An agent that reviews pull requests for bugs, security issues, and style violations.

json
{ "skills": { "pr-reviewer": { "manifest": "skills/pr-reviewer/skill.yaml", "autoLoad": true, "matchPattern": "review pull request|review PR|#\\d+" } }, "agents": { "reviewer": { "model": "claude-sonnet-4-20250514", "description": "Code review specialist", "prompt": "You are a senior code reviewer. Review code for: security vulnerabilities, performance issues, maintainability problems, and style violations.", "constraints": { "allowedTools": ["read", "grep", "glob", "bash"], "deniedTools": ["write", "edit"] } } } }
python
class CodeReviewAgent: def __init__(self, agent): self.agent = agent self.findings = [] async def review_pr(self, pr_number, repo_path): # Get the diff diff = await self.agent.bash(f"cd {repo_path} && git diff main...HEAD") changed_files = await self.agent.bash( f"cd {repo_path} && git diff --name-only main...HEAD" ) files = changed_files.strip().split("\n") for file in files[:10]: if file.endswith((".py", ".ts", ".js", ".tsx", ".jsx")): content = await self.agent.read(f"{repo_path}/{file}") file_review = await self._review_file(file, content) self.findings.extend(file_review) return self._generate_report() async def _review_file(self, file_path, content): findings = [] lines = content.split("\n") for i, line in enumerate(lines, 1): # Security checks if "eval(" in line or "exec(" in line: findings.append({ "severity": "critical", "file": file_path, "line": i, "type": "code_injection", "description": f"Dangerous function usage at line {i}" }) # Performance checks if "for " in line and any( nested_line.strip().startswith("for ") for nested_line in lines[i:i+5] ): findings.append({ "severity": "major", "file": file_path, "line": i, "type": "nested_loop", "description": "Potential O(n^2) nested loop detected" }) # Hardcoded secrets if "password" in line.lower() and "=" in line: findings.append({ "severity": "critical", "file": file_path, "line": i, "type": "hardcoded_secret", "description": "Possible hardcoded credential" }) # TODO/FIXME tracking if "TODO" in line or "FIXME" in line: findings.append({ "severity": "info", "file": file_path, "line": i, "type": "todo", "description": line.strip() }) return findings def _generate_report(self): by_severity = {} for f in self.findings: sev = f["severity"] if sev not in by_severity: by_severity[sev] = [] by_severity[sev].append(f) report = [ "# Code Review Report", f"**Total Findings**: {len(self.findings)}", "", "## Summary by Severity", ] for sev in ["critical", "major", "minor", "info"]: count = len(by_severity.get(sev, [])) report.append(f"- **{sev.capitalize()}**: {count}") report.append("") for sev in ["critical", "major", "minor", "info"]: items = by_severity.get(sev, []) if items: report.append(f"## {sev.capitalize()} Issues") for item in items[:5]: report.append( f"- [{item['type']}] {item['file']}:{item['line']}" ) report.append(f" {item['description']}") report.append("") return "\n".join(report)

Project 3: Automated Refactoring

An agent that safely restructures code while preserving behavior.

python
class RefactoringAgent: def __init__(self, agent): self.agent = agent self.changes = [] async def refactor(self, file_path, strategy): content = await self.agent.read(file_path) if strategy == "extract_function": result = await self._extract_function(content, file_path) elif strategy == "rename_variable": result = await self._rename_variable(content, file_path) elif strategy == "add_type_hints": result = await self._add_type_hints(content, file_path) else: return {"status": "error", "message": f"Unknown strategy: {strategy}"} return result async def _extract_function(self, content, file_path): lines = content.split("\n") # Find long functions (simplified heuristic) changes = [] i = 0 while i < len(lines): if lines[i].startswith("def ") and i + 30 < len(lines): # Function is long, suggest extraction func_name = lines[i][4:].split("(")[0] changes.append({ "type": "extract_function", "function": func_name, "start_line": i + 1, "length": "30+ lines", "suggestion": f"Extract helper functions from {func_name}" }) i += 30 i += 1 return {"status": "analyzed", "changes": changes} async def _rename_variable(self, content, file_path): # Find poorly named variables import re lines = content.split("\n") changes = [] bad_names = re.findall(r'\b([a-z]{1,2})\s*=', content) for name in set(bad_names): if name not in ["id", "ok", "no"]: changes.append({ "type": "rename_variable", "old_name": name, "suggestion": f"Rename '{name}' to a more descriptive name" }) return {"status": "analyzed", "changes": changes} async def _add_type_hints(self, content, file_path): lines = content.split("\n") changes = [] for i, line in enumerate(lines, 1): if line.startswith("def ") and "->" not in line: func = line[4:].split("(")[0] changes.append({ "type": "add_return_type", "function": func, "line": i, "suggestion": f"Add return type hint to {func}" }) return {"status": "analyzed", "changes": changes}
💡Tip

When refactoring with agents, always use a version control system. Create a branch, apply changes incrementally, and run tests after each change. If a refactoring breaks tests, the agent can analyze the failure and self-correct.


Project 4: Test Generation

An agent that creates comprehensive test suites from source code analysis.

yaml
# skills/test-generator/skill.yaml name: test-generator description: Generate comprehensive test suites from source code analysis version: "2.0.0" instructions: - path: instructions/analyze-source.md - path: instructions/generate-tests.md - path: instructions/validate-tests.md tools: required: - read - write - bash optional: - grep resources: - path: templates/pytest-test.py.hbs - path: templates/jest-test.ts.hbs autoload: enabled: true matchPattern: "generate tests|create tests|add test coverage"
python
class TestGenerator: def __init__(self, agent): self.agent = agent async def generate_tests(self, source_path): content = await self.agent.read(source_path) tree = self._parse_functions(content) test_file = self._build_test_file(source_path, tree) test_path = source_path.replace("src/", "tests/").replace(".py", "_test.py") await self.agent.write(test_path, test_file) return {"test_file": test_path, "test_count": len(tree)} def _parse_functions(self, content): import ast tree = ast.parse(content) functions = [] for node in ast.walk(tree): if isinstance(node, ast.FunctionDef): functions.append({ "name": node.name, "args": [a.arg for a in node.args.args], "decorators": [ d.id for d in node.decorator_list if isinstance(d, ast.Name) ] }) return functions def _build_test_file(self, source_path, functions): module_name = source_path.split("/")[-1].replace(".py", "") lines = [ f'"""Tests for {module_name} module."""', "import pytest", f"from {module_name} import (", ] for func in functions: lines.append(f" {func['name']},") lines.append(")") lines.append("") for func in functions: lines.extend(self._generate_test_case(func)) return "\n".join(lines) def _generate_test_case(self, func): name = func["name"] params = func["args"] test_cases = [ f"def test_{name}_basic():", f' """Test basic {name} functionality."""', f" # TODO: Implement test for {name}", f" # result = {name}({', '.join(params)})", f" # assert result is not None", f" pass", "", f"def test_{name}_edge_cases():", f' """Test {name} with edge case inputs."""', f" # TODO: Add edge case tests", f" pass", "", ] return test_cases

Project 5: Documentation Generation

python
class DocGenerator: def __init__(self, agent): self.agent = agent async def generate_docs(self, project_root): files = await self.agent.glob(f"{project_root}/**/*.py") docs = [] for file in files[:20]: content = await self.agent.read(file) module_doc = self._extract_module_doc(content) functions = self._parse_functions(content) doc_section = [ f"## Module: {file}", "", module_doc or "No module documentation.", "", "### Functions", "", ] for func in functions: doc_section.extend([ f"#### `{func['name']}({', '.join(func['args'])})`", "", func["docstring"] or "No documentation.", "", ]) docs.append("\n".join(doc_section)) return "# API Documentation\n\n" + "\n---\n".join(docs) def _extract_module_doc(self, content): import ast try: tree = ast.parse(content) return ast.get_docstring(tree) except SyntaxError: return None def _parse_functions(self, content): import ast try: tree = ast.parse(content) functions = [] for node in ast.walk(tree): if isinstance(node, ast.FunctionDef) and not node.name.startswith("_"): functions.append({ "name": node.name, "args": [a.arg for a in node.args.args], "docstring": ast.get_docstring(node) }) return functions except SyntaxError: return []

Practice Exercises

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

What is the recommended approach when an agent refactoring breaks existing tests?

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

In the code review project, what security issue does the agent check for?

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

What tool does the test generator use to parse source code and identify functions?

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

What is the purpose of using a branch for agent-driven refactoring?

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

In the blog API generation project, what framework is used for the generated API?

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

What file naming convention does the test generator use when creating test files?

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

What information does the documentation generator extract from source code?

Practice Question
How to answer

Multiple-choice question with 4 options. Select one option, then choose Check Answer.

Why does the code review agent use 'deniedTools: [write, edit]'?


✅Key Takeaways
  • Real-world agent projects span code generation, review, refactoring, testing, and documentation
  • Code generation agents create complete modules from specifications with models, routes, and tests
  • Code review agents should be read-only, inspecting code for bugs, security issues, and style problems
  • Refactoring agents should use version control branches for safe, reversible changes
  • Test generation agents create comprehensive test suites by parsing source code structure
  • Documentation agents extract module and function documentation from source code automatically
  • Each project combines multiple skills: tool use, planning, context management, and safety patterns
  • Real agents handle errors, adapt plans, and learn from intermediate results
  • The capstone demonstrates the full power of agentic AI: autonomous, multi-step software engineering
Progress100%