Quickstart with Kiro
This guide walks you through creating a complete GenLabZ project from scratch using Kiro. You’ll go through all seven authoring phases in order: intake, scaffolding, objectives and steps, instructions, content files, code generation, and testing. By the end, you’ll have a working project that runs against a real AWS account.
If you haven’t set up the GenLabZ Author power yet, start with the IDE setup for Kiro page first.
Phase 1 — Intake
You start by describing your project idea to Kiro in plain language. Don’t worry about structure yet — just explain what you want to build and who it’s for. Kiro will ask clarifying questions about scope, difficulty, and target audience to help you sharpen the concept.
For this walkthrough, you might say something like: “I want to create a beginner project that teaches authors how to host a static website on S3. It should cover creating a bucket, enabling static website hosting, and adding a public read bucket policy.”
Kiro will ask follow-up questions — expected duration, prerequisite knowledge, which AWS services are involved. Your answers shape the project metadata that goes into spec.yaml. By the end of intake, you have a clear project concept and a shared understanding of what you’re building.
Phase 2 — Scaffolding
Once you’re happy with the project concept, Kiro calls init_project to create the directory structure. You don’t write any files manually — the server scaffolds everything for you.
For the s3-static-website project, the result looks like this:
s3-static-website/├── spec.yaml├── content/├── images/├── solution/│ └── boto3/├── evaluation/│ └── boto3/└── cleanup/ └── boto3/Each directory has a specific role. solution/boto3/ holds your reference implementation — one Python file per step. evaluation/boto3/ holds the code that verifies a student’s work. cleanup/boto3/ holds the teardown code — one file per objective. The content/ and images/ directories are for rich markdown content and diagrams that supplement the spec fields.
At this point, spec.yaml exists with the project metadata you defined during intake. The objectives and steps sections are empty — that’s what you fill in next.
Phase 3 — Objectives and steps
Now you break the project into objectives and steps. Kiro helps you think through the structure, but you make the decisions. An objective is a purpose-oriented grouping — it describes why a set of steps belongs together. A step is a discrete, testable action.
For the S3 static website project, the spec ends up looking like this:
objectives: - id: "01" title: "Create and configure the S3 bucket" description: | Set up an S3 bucket with static website hosting enabled. This objective covers bucket creation with a unique name and configuring the **index document** for website hosting. steps: - id: "01" title: "Create the S3 bucket" instructions: [] inputs: [] outputs: - name: "01_01_bucket" type: "AWS::S3::Bucket" description: "The S3 bucket for hosting" - id: "02" title: "Enable static website hosting" instructions: [] inputs: - name: "01_01_bucket" outputs: - name: "01_02_website_url" type: "string" description: "The website endpoint URL"
- id: "02" title: "Configure public access" description: | Add a bucket policy to allow public read access to the website. You'll write an IAM policy document that grants `s3:GetObject` to all principals on the bucket's objects. steps: - id: "01" title: "Apply a public read bucket policy" instructions: [] inputs: - name: "01_01_bucket" outputs: - name: "02_01_policy" type: "AWS::S3::BucketPolicy" description: "Public read policy on the bucket"Notice the inputs and outputs on each step. The outputs declare what a step produces — each output gets a handle name like 01_01_bucket. The inputs on a later step reference those handles by name, telling the platform that this step depends on that resource. This is called handle wiring, and it’s how the test runner knows what to pass to each step’s code at runtime. Handle wiring is covered in depth in Handle wiring.
After you review and approve the objectives and steps, Kiro runs validate_project to catch any structural errors before you move on.
Phase 4 — Instructions
Now that your spec structure is in place, let’s write the instructions. Instructions are the student-facing guidance for each step — they describe what the student needs to accomplish, not how to do it. The platform supports multiple interfaces and runtimes, so you leave the implementation details to the student.
Here’s what the instructions look like for the S3 static website steps:
steps: - id: "01" title: "Create the S3 bucket" instructions: - "Create a new S3 bucket with a unique name" - "The bucket name must be globally unique — use a random suffix" outputs: - name: "01_01_bucket" type: "AWS::S3::Bucket" description: "The S3 bucket for hosting"
- id: "02" title: "Enable static website hosting" instructions: - "Configure the bucket for static website hosting" - "Set index.html as the index document" inputs: - name: "01_01_bucket" outputs: - name: "01_02_website_url" type: "string" description: "The website endpoint URL"Each instruction is a short, action-oriented sentence. You’re telling the student what to create and what configuration matters — not which console to click through or which CLI command to run. A good instruction says “Create a bucket policy that allows s3:GetObject for all principals.” A bad one says “In the AWS Console, navigate to S3, click your bucket, go to Permissions, and paste this JSON.”
Once you’re happy with the instructions, Kiro validates the project again before moving to code generation.
Phase 5 — Content files
With instructions in place, you can optionally enrich the student experience with content files. Content files are Markdown files in the content/ directory that provide narrative context — the why behind each step, not the how. They’re optional, but they make a real difference to how students experience the project.
Here’s a simple content file for step 01.01 — creating the S3 bucket:
Amazon S3 bucket names are globally unique across all AWS accounts and regions.This means you can't just pick any name — you need to ensure yours doesn'tconflict with a bucket someone else has already created.
:::TIPA common pattern is to append a short random suffix to a descriptive base name,like `my-project-a3f9c2b1`. The exact suffix doesn't matter — what matters isthat it's unique and follows S3 naming rules.:::
The content file overrides the step’s instructions field when it exists — the file wins. This means you can start with short inline instructions in spec.yaml and promote to a richer content file when you’re ready, without changing the spec structure.
After writing content files, run validate_project to check for broken image references or orphaned files. You can also launch the preview server to see how the content renders before moving on.
For the full guide on content file types, callout usage, and the code example rules, see Content files.
Phase 6 — Code generation
With instructions approved, Kiro generates three types of code for each objective: solution code, evaluation code, and cleanup code. You work through one objective at a time — solution first, then evaluation, then cleanup — before moving to the next objective.
Solution code is your reference implementation. It creates the AWS resources a student is expected to create. Here’s the solution for step 01.01 — creating the S3 bucket:
import uuidfrom botocore.exceptions import ClientError
async def run(session, context, logger): s3 = session.client("s3") bucket_name = f"01-01-bucket-{uuid.uuid4().hex[:8]}" try: s3.create_bucket(Bucket=bucket_name) logger.info(f"Created bucket: {bucket_name}") return { "success": True, "resources": [ {"name": "01_01_bucket", "type": "AWS::S3::Bucket", "id": bucket_name} ], } except ClientError as e: logger.error(f"Failed to create bucket: {e}") return {"error": str(e), "code": e.response["Error"]["Code"]}Every solution file defines async def run(session, context, logger). The session is a boto3 Session scoped to the sandbox account. The context dict contains resolved — the validated handles from prior steps — and spec, the step’s expected inputs and outputs. The function returns a resources list on success, or an error dict on failure. It never raises exceptions.
Evaluation code verifies that the student created the right resources with the right configuration. Cleanup code tears everything down after testing. Both follow the same function signature. The code contracts for all three types are covered in depth in the Solution code, Evaluation code, and Cleanup code pages.
Phase 7 — Testing
Once all code is generated and review_project passes, you’re ready to test against a real AWS account. Testing runs your solution, evaluation, and cleanup code in your own AWS account — it creates and deletes real resources.
You can test at different levels of granularity. To test a single step’s solution:
test solution 01.01To run solution and evaluation for a full objective:
test objective 01To test an objective, clean it up, and test it again (a cycle test — useful for verifying cleanup works):
cycle test objective 01Behind the scenes, the test runner executes your solution code, collects the returned resource handles, passes them to your evaluation code as events, and promotes validated handles to resolved so subsequent steps can use them. If anything fails, Kiro stops immediately and shows you the error, logs, and handle state. You decide whether to investigate, fix and re-run, or roll back the objective.
The testing reference covers session state, the full resource flow, and all available test scopes in depth.
What’s next
You’ve seen the full authoring workflow from intake to testing. The next step is to try it with your own project idea. Load the GenLabZ Author power in Kiro and start with intake — describe what you want to build and let Kiro guide you through the phases.
When you’re ready to go deeper on any part of the workflow, the authoring guide covers project structure, objectives and steps, writing instructions, and handle wiring. The code contracts section covers the exact function signatures, return formats, and patterns for solution, evaluation, and cleanup code.