Skip to content

Objectives and steps

A GenLabZ project is broken down into objectives and steps. Getting this structure right is the most important part of authoring — everything else (instructions, code, evaluation) flows from it.

Objectives

An objective is a purpose-oriented grouping of steps. It describes what the student is working toward in that phase of the project, not what they physically do.

Good objective titlesWhy
”Provision the DynamoDB table for persistent storage”Describes the purpose
”Implement the business logic in a Lambda function”Describes the purpose
Bad objective titlesWhy
”Students will learn to create S3 buckets”That’s a learning outcome, not an objective
”Navigate to the Lambda console and create a function”Those are instructions

The objective’s description field is student-facing — write it in markdown and make it engaging. It should explain what this objective achieves and why it matters in the context of the project. If you need more space or richer formatting, you can override it with a content/{objective_id}.md file.

Steps

A step is a discrete, testable action within an objective. Each step should produce something concrete that can be verified — a resource created, a configuration applied, a connection established.

Aim for 2–4 steps per objective. A step that does too much is hard to evaluate precisely; a step that does too little creates unnecessary overhead.

Good step titlesWhy
”Create a Lambda function with Python 3.12 runtime”Discrete, testable
”Define security groups for application layers”Discrete, testable
Bad step titlesWhy
”Navigate to the Lambda console and create a Lambda function”That’s an instruction, not a step title

Handle wiring

Steps communicate through handles — named references to resources produced by one step and consumed by another. You declare handles as outputs on the producing step and reference them as inputs on the consuming step.

Handle names follow the format {OO}_{SS}_{resource_name}:

  • OO — zero-padded objective ID (e.g. 01)
  • SS — zero-padded step ID within that objective (e.g. 02)
  • resource_name — lowercase alphanumeric segments joined by underscores, starting with a letter

Examples: 01_01_vpc_id, 01_02_igw_id, 02_01_function_arn

A step in objective 2 can reference handles from objective 1. Forward dependencies (referencing a handle from a later step) are not allowed.

Worked example

Here’s a two-objective project showing handle flow across objectives:

objectives:
- id: "01"
title: Create VPC Infrastructure
description: |
Establish the network foundation by creating a **VPC** with public and
private subnets across two availability zones, providing isolation and
high availability for your resources.
steps:
- id: "01"
title: Create VPC
instructions: []
outputs:
- name: 01_01_vpc_id
type: AWS::EC2::VPC
description: The VPC that will contain all project resources
- id: "02"
title: Create and attach Internet Gateway
instructions: []
inputs:
- 01_01_vpc_id
outputs:
- name: 01_02_igw_id
type: AWS::EC2::InternetGateway
description: Internet Gateway for public subnet internet access
- id: "03"
title: Configure public routing
instructions: []
inputs:
- 01_01_vpc_id
- 01_02_igw_id
outputs:
- name: 01_03_public_rt
type: AWS::EC2::RouteTable
description: Route table for public subnets
- id: "02"
title: Deploy the Application
description: |
Deploy the application into the VPC, using the network infrastructure
created in the previous objective.
steps:
- id: "01"
title: Create the EC2 instance
instructions: []
inputs:
- 01_01_vpc_id # from objective 01
- 01_03_public_rt # from objective 01
outputs:
- name: 02_01_instance_id
type: AWS::EC2::Instance
description: The application server

Notice that objective 2 references handles from objective 1 directly by name. The test runner resolves these at runtime — your evaluation code receives the actual resource IDs.

What to leave out at this stage

When writing objectives and steps, leave the instructions list empty (instructions: []). Instructions are written in the next phase, after the structure is reviewed and approved. Filling in instructions before the structure is stable means rewriting them every time a step changes.

For more on handle naming rules and how handles flow through the test runner, see Handle wiring.