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 这么重要
注意几个关键点:
- "不做什么"比"做什么"更重要 —— 不写这部分,AI 可能给你加一堆你不需要的功能
- 数据模型先定义 —— DynamoDB 的 PK/SK 设计决定了后面所有查询方式
- 具体数字 —— "< 500ms" 比 "快" 有用得多
- 统一约定 —— 错误格式、分页方式写清楚,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
- 加一行配置
- 简单的重命名/格式化
上手建议
- 从小 Spec 开始 —— 别一上来写 500 行的规格,先写一个 50 行的、覆盖一个模块
- "不做什么"必须写 —— 这是防止 AI 发散的关键
- 数据结构先定 —— 数据模型决定了 80% 的实现逻辑
- 持续迭代 Spec —— 项目演进时同步更新 Spec,它就是活文档
下载 Kiro:https://aws.amazon.com/cn/campaigns/kiro/
Kiro Specs 文档:https://kiro.dev/docs/specs/

浙公网安备 33010602011771号