Kiro Specs 实战:先写规格再生代码,一个 CRUD API 的完整开发流程

Kiro 最大的差异点不是"代码写得多快",而是它的开发流程和其他 AI 编程工具不一样。

大多数 AI 编程工具的思路是:你给指令 → AI 写代码 → 你 review。问题来了——你给的指令越模糊,AI 的产出越离谱,来回修改的时间反而比自己写还长。

Kiro 的思路是:先写 Spec(规格文件),再让 Agent 执行。Spec 就是你和 AI 之间的"合同"——写清楚了要什么,AI 才能一次做对。

今天用一个实际例子走一遍:用 Kiro 从零搭一个用户管理 API(CRUD + DynamoDB + Lambda)。

第一步:写 Spec

在项目根目录创建 .kiro/specs/user-api.md

# User Management API

## 目标
构建一个用户管理 RESTful API,支持增删改查操作。

## 技术栈
- Runtime: Python 3.12 on AWS Lambda
- Database: DynamoDB (single-table design)
- API: API Gateway HTTP API
- IaC: AWS CDK (Python)
- 测试: pytest + moto

## 数据模型

### User Table
- PK: `USER#<user_id>`
- SK: `PROFILE`
- Attributes:
  - user_id (string, UUID)
  - email (string, unique)
  - name (string)
  - created_at (ISO8601)
  - updated_at (ISO8601)
  - status (enum: active/inactive/suspended)

## API 端点

| Method | Path | 描述 | 返回 |
|--------|------|------|------|
| POST | /users | 创建用户 | 201 + user object |
| GET | /users/{id} | 获取用户 | 200 + user object |
| PUT | /users/{id} | 更新用户 | 200 + user object |
| DELETE | /users/{id} | 删除用户 | 204 |
| GET | /users | 列出用户(分页) | 200 + users[] + nextToken |

## 约束
- email 必须唯一(用 GSI 做唯一性检查)
- 分页用 DynamoDB 的 LastEvaluatedKey(不用 offset)
- 所有响应包含 request_id(从 Lambda context 取)
- 错误返回统一格式:{ "error": "message", "request_id": "xxx" }

## 非功能需求
- Lambda 冷启动 < 500ms
- 单个 API 响应 < 200ms(排除冷启动)
- DynamoDB 用 on-demand 模式

## 不做什么
- 不做认证/鉴权(后续接 Cognito)
- 不做文件上传
- 不做批量操作
- 不做 WebSocket

为什么 Spec 这么重要

注意几个关键点:

  1. "不做什么"比"做什么"更重要 —— 不写这部分,AI 可能给你加一堆你不需要的功能
  2. 数据模型先定义 —— DynamoDB 的 PK/SK 设计决定了后面所有查询方式
  3. 具体数字 —— "< 500ms" 比 "快" 有用得多
  4. 统一约定 —— 错误格式、分页方式写清楚,AI 不会每个接口实现不一样

第二步:项目配置

.kiro/settings.toml

[agent]
model = "claude-sonnet-4.6"

[project]
language = "python"
framework = "aws-cdk"

[conventions]
test_framework = "pytest"
linter = "ruff"
type_checker = "mypy"

第三步:让 Kiro 跑

打开 Kiro,输入:

按照 specs/user-api.md 的规格,生成完整项目结构并实现所有 API 端点。
先生成项目脚手架,再逐个实现端点,每实现一个跑一遍测试。

Kiro 会按 Spec 里定义的约束来执行。如果 Spec 写得好,产出是这样的:

project/
├── .kiro/
│   ├── specs/user-api.md
│   └── settings.toml
├── infrastructure/
│   ├── app.py
│   └── stacks/
│       └── user_api_stack.py
├── src/
│   ├── handlers/
│   │   ├── create_user.py
│   │   ├── get_user.py
│   │   ├── update_user.py
│   │   ├── delete_user.py
│   │   └── list_users.py
│   ├── models/
│   │   └── user.py
│   └── repository/
│       └── user_repository.py
├── tests/
│   ├── unit/
│   │   ├── test_create_user.py
│   │   ├── test_get_user.py
│   │   └── ...
│   └── integration/
│       └── test_api.py
├── pyproject.toml
└── README.md

第四步:Review 重点

AI 生成完代码后,重点看这几个地方:

1. DynamoDB 操作是否正确

# 检查 email 唯一性约束的实现
# 好的实现:用 ConditionExpression
def create_user(self, user: User) -> User:
    try:
        self.table.put_item(
            Item=user.to_dynamodb_item(),
            ConditionExpression="attribute_not_exists(PK)"
        )
    except ClientError as e:
        if e.response['Error']['Code'] == 'ConditionalCheckFailedException':
            raise EmailAlreadyExistsError(user.email)
        raise

2. 分页是否用了 LastEvaluatedKey

# 正确的分页实现
def list_users(self, limit: int = 20, next_token: str = None) -> tuple:
    params = {
        "Limit": limit,
        "FilterExpression": Attr("SK").eq("PROFILE")
    }
    if next_token:
        params["ExclusiveStartKey"] = json.loads(
            base64.b64decode(next_token)
        )

    response = self.table.scan(**params)
    items = response.get("Items", [])
    last_key = response.get("LastEvaluatedKey")

    encoded_token = None
    if last_key:
        encoded_token = base64.b64encode(
            json.dumps(last_key).encode()
        ).decode()

    return items, encoded_token

3. 错误处理是否统一

# 统一的错误响应格式
def error_response(status_code: int, message: str, request_id: str) -> dict:
    return {
        "statusCode": status_code,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({
            "error": message,
            "request_id": request_id
        })
    }

Spec 驱动 vs Prompt 驱动的区别

维度 Prompt 驱动(普通 AI 编程) Spec 驱动(Kiro)
输入 自然语言描述 结构化规格文件
一致性 每次可能不同 同一 Spec 产出稳定
可审计 对话历史散落 Spec 文件可 git track
团队协作 每人提示词不同 共享 Spec 约束
变更管理 重新描述 修改 Spec + 重新执行

实际效果

用 Spec 驱动开发的实际体验:

  • 首次生成质量明显更高 —— 因为约束定义清楚了,减少了来回修改
  • Review 更有依据 —— 对照 Spec 检查,不是凭感觉看代码
  • 需求变更可追溯 —— Spec 改了哪里,git diff 一目了然
  • 新人上手快 —— 看 Spec 就知道项目做什么、怎么做

什么场景值得写 Spec

不是所有任务都需要 Spec。我的经验:

值得写 Spec 的:

  • 新项目初始化(定义整体架构和约束)
  • 复杂 feature(涉及多个组件联动)
  • 团队协作的共享约定
  • 需要反复生成/重构的模块

不值得的:

  • 改一个 bug
  • 加一行配置
  • 简单的重命名/格式化

上手建议

  1. 从小 Spec 开始 —— 别一上来写 500 行的规格,先写一个 50 行的、覆盖一个模块
  2. "不做什么"必须写 —— 这是防止 AI 发散的关键
  3. 数据结构先定 —— 数据模型决定了 80% 的实现逻辑
  4. 持续迭代 Spec —— 项目演进时同步更新 Spec,它就是活文档

下载 Kiro:https://aws.amazon.com/cn/campaigns/kiro/
Kiro Specs 文档:https://kiro.dev/docs/specs/

posted @ 2026-06-17 20:06  亚马逊云开发者  阅读(8)  评论(0)    收藏  举报