第 14 期 | 代码生成与项目脚手架实战

更新于 2026/4/15

好的,这是为 Hermes Agent 教程撰写的第 14 期文章。


副标题:从 API 设计到全栈代码生成。掌握 AI 辅助架构探索和 TDD 测试驱动工作流。

学习目标

在本期课程中,你将深入学习 Hermes Agent 在软件工程领域的两大核心能力:代码生成 (Code Generation) 与项目脚手架 (Project Scaffolding)。完成本教程后,你将能够:

  1. 理解 Agent-Driven Development (ADD) 模式:学习如何将 AI Agent 集成到你的日常开发流程中,从指令下发者转变为架构指导者。
  2. 熟练运用 project_scaffolding Skill:一键生成标准化的项目结构,如 FastAPI, Express.js, React 等,极大提升项目启动效率。
  3. 精通 code_writer Skill:掌握通过精确的自然语言指令,让 Agent 编写、修改、重构和解释代码的技巧。
  4. 实践 AI 辅助的 TDD 工作流:学习如何结合测试驱动开发 (Test-Driven Development) 与 Agent,编写测试用例,然后指导 Agent 生成通过测试的业务代码,确保代码质量。
  5. 探索快速架构原型验证:利用 Agent 快速生成不同技术栈的原型,以更低的成本进行技术选型和架构设计验证。

核心概念讲解

在深入实战之前,我们必须理解支撑本期教程的几个核心概念。这不仅仅是关于“让 AI 写代码”,而是关于一种全新的、人机协作的软件开发范式。

1. Agent-Driven Development (ADD)

Agent-Driven Development (ADD) 是一种开发方法论,其中开发者(人类)扮演着架构师、产品经理和质量保证(QA)的角色,而 AI Agent 则扮演着一个初级到中级开发者的角色。

  • 人类的职责:定义需求、设计系统架构、拆分任务、编写关键的测试用例、审查和合并 Agent 生成的代码。
  • Agent 的职责:根据明确的指令,执行具体的编码任务,如创建项目结构、编写模块代码、实现 API 端点、生成单元测试模板、修复 Bug 等。

这种模式的优势在于,它将开发者从繁琐的、重复性的“体力”编码中解放出来,使其能更专注于高层次的创造性工作。Agent 如同一个不知疲倦、精通多种语言和框架的结对编程伙伴。

2. project_scaffolding Skill

想象一下启动一个新项目时的场景:创建目录结构、配置 package.jsonpyproject.toml、设置 linter、编写 Dockerfile、创建 .gitignore... 这个过程既耗时又容易出错。

project_scaffolding Skill 正是为了解决这个问题而生。它是一个内置于 Hermes Agent 的高级技能,预置了多种主流技术栈的最佳实践模板。你只需提供项目类型和名称,它就能在数秒内为你构建一个功能完备、结构清晰的初始项目。

工作原理:该 Skill 内部封装了多个项目模板(如 FastAPI, React+Vite, Node.js+Express)。当被调用时,它会根据传入的 project_type 参数,选择对应的模板,复制文件结构,并动态替换项目名称等变量。这远比简单的 mkdirtouch 命令强大得多。

3. code_writer Skill

这是 Hermes Agent 最强大的 Skill 之一。code_writer 不仅仅是简单地将你的 Prompt 传递给 LLM 并将结果写入文件。它是一个具备上下文感知能力的智能写入工具。

核心特性

  • 文件操作:可以创建新文件、覆盖现有文件或在指定位置插入/修改代码(高级用法)。
  • 上下文读取 (Context Reading):在生成代码前,它可以被指令读取一个或多个现有文件的内容。这至关重要,因为它让 Agent 能够理解项目当前的状况,例如已定义的函数、数据模型或测试用例,从而生成与现有代码兼容且一致的新代码。
  • 精准指令:它的效果高度依赖于你 Prompt 的质量。一个好的 Prompt 应该包含:
    • 目标 (Goal):要实现什么功能?(例如:“实现一个创建用户的 API 端点”)
    • 约束 (Constraints):需要遵守哪些规则?(例如:“使用 Pydantic 模型进行数据验证”,“必须返回 201 Created 状态码”)
    • 上下文 (Context):参考哪些已有代码?(例如:“参考 app/models.py 中的 User 模型”)

4. TDD 与 Agent 的协同工作流

测试驱动开发(TDD)的经典循环是“红-绿-重构”:

  1. 红 (Red):编写一个失败的测试用例。
  2. 绿 (Green):编写最少的代码,使测试通过。
  3. 重构 (Refactor):在不改变外部行为的前提下,改进代码结构。

当引入 Hermes Agent 后,这个流程演变为一种人机协作的舞蹈:

  1. 红 (Human):开发者编写一个清晰、具体的失败测试用例。这是定义“完成”标准的关键一步。
  2. 绿 (Agent):开发者向 Agent 发出指令,目标是让刚刚编写的测试通过。例如:“tests/test_api.py 中的 test_create_item 测试失败了。请在 app/main.py 中实现 POST /items 路由,以满足测试用例的要求。”
  3. 验证 (Human):开发者运行测试,确认 Agent 的代码使测试变为“绿色”。
  4. 重构 (Human/Agent):开发者审查代码。如果需要重构,可以自己动手,也可以向 Agent 发出重构指令:“请将 app/main.py 中的数据库逻辑提取到一个新的 app/crud.py 模块中。”

这个工作流的妙处在于,测试用例成为了人类与 Agent 之间最精确、无歧义的沟通语言。它为 Agent 的创造力设定了明确的边界和可验证的目标,确保了生成代码的质量和可靠性。


💻 实战演示

现在,让我们通过一个完整的端到端示例,来构建一个基于 FastAPI 的简单 Todo List API。我们将严格遵循 AI 辅助的 TDD 工作流。

场景:构建一个 Todo API

我们的 API 需要具备以下基本功能:

  • 创建 Todo 项目 (POST /todos)
  • 获取所有 Todo 项目 (GET /todos)

第 1 步:使用 project_scaffolding 初始化项目

首先,我们让 Hermes Agent 为我们创建一个标准的 FastAPI 项目结构。

# 指令 Agent 创建一个名为 todo_api 的 FastAPI 项目
hermes --skill project_scaffolding --args '{"project_type": "fastapi", "project_name": "todo_api"}'

Agent 执行后,你将看到类似以下的输出,并生成 todo_api 目录:

> Executing Skill: project_scaffolding
> Arguments: {'project_type': 'fastapi', 'project_name': 'todo_api'}
> [project_scaffolding] Project 'todo_api' created successfully with 'fastapi' template.

现在,查看生成的项目结构:

cd todo_api
tree .

你会看到一个非常专业的结构:

.
├── app
│   ├── __init__.py
│   ├── main.py       # FastAPI 应用主文件
│   ├── models.py     # 数据模型
│   └── crud.py       # 数据库操作逻辑
├── tests
│   ├── __init__.py
│   └── test_main.py  # 测试文件
├── .gitignore
├── pyproject.toml    # 项目依赖与配置 (使用 Poetry)
└── README.md

第 2 步:定义数据模型

在开始编写业务逻辑之前,我们需要先定义数据模型。我们希望一个 Todo 项包含 id, title, descriptiondone 状态。

我们使用 code_writer Skill 来创建 Pydantic 模型。

# 指令 Agent 在 app/models.py 中定义 Todo 模型
hermes --skill code_writer --args '{
  "file_path": "app/models.py",
  "prompt": "Create a Pydantic model for our Todo application. Create two models: `TodoBase` with `title` (str), `description` (str, optional), and `done` (bool, default=False). Then create a `Todo` model that inherits from `TodoBase` and adds an `id` (int) field."
}'

检查 app/models.py 文件,Agent 应该已经生成了如下内容:

# app/models.py
from typing import Optional
from pydantic import BaseModel

class TodoBase(BaseModel):
    title: str
    description: Optional[str] = None
    done: bool = False

class Todo(TodoBase):
    id: int

    class Config:
        orm_mode = True

注意:Agent 可能会根据其模型的训练数据添加 orm_mode 等配置,这在与数据库 ORM(如 SQLAlchemy)集成时非常有用。

第 3 步:TDD 流程 - 实现 "Create Todo" 端点

现在进入核心的 TDD 循环。

3.1 (红) 编写失败的测试

我们首先在 tests/test_main.py 中编写一个测试用例,用于测试创建 Todo 的功能。此时 app/main.py 中还没有实现任何相关逻辑,所以这个测试注定会失败。

用你喜欢的编辑器打开 tests/test_main.py,写入以下内容:

# tests/test_main.py
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_create_todo():
    response = client.post(
        "/todos/",
        json={"title": "Test Todo", "description": "This is a test description."}
    )
    assert response.status_code == 201, response.text
    data = response.json()
    assert data["title"] == "Test Todo"
    assert data["description"] == "This is a test description."
    assert data["done"] is False
    assert "id" in data

def test_read_todos_initial():
    response = client.get("/todos/")
    assert response.status_code == 200
    assert response.json() == []

我们添加了两个测试:一个用于创建,一个用于确认初始状态下列表为空。

现在,安装依赖并运行测试。我们使用 Poetry (由脚手架配置)。

# 安装项目依赖
poetry install

# 运行 pytest
poetry run pytest

你会看到测试失败的红色输出,特别是 test_create_todo,可能会报 404 Not Found 错误,因为 /todos/ 这个路由还不存在。

=========================== FAILURES ===========================
_________________________ test_create_todo _________________________

    def test_create_todo():
        response = client.post(
            "/todos/",
            json={"title": "Test Todo", "description": "This is a test description."}
        )
>       assert response.status_code == 201, response.text
E       AssertionError: {"detail":"Not Found"}
E       assert 404 == 201

tests/test_main.py:11: AssertionError

3.2 (绿) 指令 Agent 编写代码

现在,我们有了明确的目标:让 test_create_todo 测试通过。我们将这个任务交给 Hermes Agent,并让它读取测试文件作为上下文

# 指令 Agent 实现 /todos/ POST 路由以通过测试
hermes --skill code_writer --args '{
  "file_path": "app/main.py",
  "prompt": "The test `test_create_todo` in `tests/test_main.py` is failing with a 404 error. Please implement the `POST /todos/` endpoint in `app/main.py`. It should: \n1. Accept a Todo item payload (without an ID). \n2. For now, use a simple in-memory list as a database. \n3. Assign a new ID to the created item. \n4. Return the complete Todo item (with ID) with a 201 Created status code. \n5. Also implement the `GET /todos/` endpoint to return the list of all todos.",
  "read_context_files": ["tests/test_main.py", "app/models.py"]
}'

这个 Prompt 的关键点

  • 明确的问题: "The test test_create_todo ... is failing"。
  • 清晰的指令: "implement the POST /todos/ endpoint"。
  • 具体的实现细节: "use a simple in-memory list", "assign a new ID", "Return ... with a 201 status code"。
  • 上下文关联: read_context_files 告诉 Agent 去阅读测试用例和数据模型,这样它就知道需要导入 Todo 模型,并且知道返回的数据结构应该是什么样的。

Agent 执行后,app/main.py 的内容会被更新,可能如下所示:

# app/main.py
from typing import List
from fastapi import FastAPI, HTTPException, status
from .models import Todo, TodoBase

app = FastAPI()

# In-memory database
db: List[Todo] = []
next_id = 1

@app.post("/todos/", response_model=Todo, status_code=status.HTTP_201_CREATED)
def create_todo(todo: TodoBase):
    global next_id
    new_todo = Todo(id=next_id, **todo.dict())
    db.append(new_todo)
    next_id += 1
    return new_todo

@app.get("/todos/", response_model=List[Todo])
def read_todos():
    return db

3.3 (验证) 再次运行测试

现在,我们再次运行测试来验证 Agent 的工作。

poetry run pytest

这一次,你应该会看到所有测试都通过的绿色输出!

========================= 2 passed in 0.05s =========================

我们成功地通过 TDD + Agent 的工作流,零手动编码(除了测试用例)实现了第一个 API 端点。

第 4 步:架构探索与全栈生成

这个模式的强大之处不止于此。

架构探索:假设你现在不确定是用 in-memory 数据库还是 SQLite。你可以快速地向 Agent 发出新指令:

"Refactor the current app/main.py. Instead of an in-memory list, use Python's built-in sqlite3 module to store the todos in a file named todos.db. Create a function to initialize the database table if it doesn't exist."

Agent 可以在几分钟内为你生成一个使用 SQLite 的新版本,让你能够快速评估和比较不同持久化方案的优劣。

前端代码生成:既然后端 API 已经就绪,我们甚至可以要求 Agent 为我们生成一个简单的前端来消费这个 API。

# 首先,创建前端项目结构
hermes --skill project_scaffolding --args '{"project_type": "react", "project_name": "frontend"}'

# 然后,指令 Agent 编写一个 React 组件
hermes --skill code_writer --args '{
  "file_path": "frontend/src/components/TodoList.jsx",
  "prompt": "Create a React functional component named `TodoList`. It should use the `useState` and `useEffect` hooks to fetch data from our backend API at `http://localhost:8000/todos/`. It should then display the list of todos. For each todo, display its title and whether it is done or not. Handle loading and error states."
}'

Agent 会在 frontend/src/components/TodoList.jsx 中生成一个功能完整的 React 组件,为你省去了大量编写数据获取和状态管理模板代码的时间。


涉及命令

  • hermes --skill project_scaffolding --args '{"project_type": "...", "project_name": "..."}'
    • 用于基于预设模板创建新项目。
  • hermes --skill code_writer --args '{"file_path": "...", "prompt": "...", "read_context_files": [...]}'
    • 核心代码生成命令。file_path 指定目标文件,prompt 提供详细指令,read_context_files (可选) 提供上下文。
  • poetry install
    • 安装 pyproject.toml 中定义的 Python 依赖。
  • poetry run pytest
    • 在项目的虚拟环境中运行 pytest 测试框架。
  • tree .
    • 以树状结构显示当前目录的文件和文件夹。

要点回顾

  1. 思维转变:从“代码实现者”转变为“系统设计者和指令下达者”。你的核心工作是分解问题、定义接口和编写高质量的测试。
  2. 结构先行:使用 project_scaffolding 可以确保项目从一开始就拥有一个标准、健壮的结构,避免了“搭架子”的重复劳动。
  3. 测试即文档,测试即契约:在 Agent-Driven Development 中,测试用例是连接人类意图和 AI 执行的最可靠桥梁。一个好的测试就是一个完美的 Prompt。
  4. 上下文是关键code_writerread_context_files 参数是其强大功能的核心。始终记得为你 Agent 的任务提供足够的上下文,以获得更高质量的输出。
  5. 迭代与验证:不要期望 Agent 一次性生成完美的最终代码。采用“指令-生成-验证-迭代”的循环,逐步将项目构建完善。这与敏捷开发的思想不谋而合。

通过本期课程,你已经掌握了利用 Hermes Agent 进行现代化软件开发的强大工作流。这不仅能极大地提高你的开发效率,更能让你将精力聚焦于真正具有挑战性和创造性的架构设计与问题解决上。

参考资料