Handle wiring
Handles are the mechanism that connects steps together. A step declares the resources it produces as outputs, and later steps reference those resources as inputs. The test runner resolves handles at runtime, passing actual resource IDs to your evaluation code.
Handle naming
Handle names follow a strict format: {OO}_{SS}_{resource_name}
| Part | Format | Example |
|---|---|---|
OO | Two-digit zero-padded objective ID | 01, 02 |
SS | Two-digit zero-padded step ID within the objective | 01, 03 |
resource_name | Lowercase alphanumeric segments joined by underscores, starting with a letter | vpc_id, function_arn, bucket_name |
Full examples: 01_01_vpc_id, 01_02_igw_id, 02_01_function_arn, 03_01_public_subnet_1_id
Rules
- Fully qualified names — output names always include the objective and step prefix.
01_02_bucket, notbucket. - Prefix must match the step — a step with objective
01, step02can only declare outputs starting with01_02_. - Inputs reference prior outputs — a step can only reference handles from earlier steps. Forward dependencies (referencing a handle from a later step) are not allowed.
- Cross-objective references are fine — a step in objective
02can reference handles from objective01.
Output declarations
Each output needs three fields:
outputs: - name: 01_01_vpc_id # handle name — must match {OO}_{SS}_{resource_name} type: AWS::EC2::VPC # CloudFormation resource type, or "string" description: The VPC that will contain all project resourcesThe type field must be either a valid CloudFormation resource type (AWS::S3::Bucket, AWS::Lambda::Function, etc.) or the literal "string" for non-resource outputs like ARNs, URLs, and names.
Input declarations
Inputs reference prior outputs by handle name:
inputs: - 01_01_vpc_id - 01_02_igw_idA step with no dependencies omits the inputs field entirely (or uses an empty list).
Worked example — handles flowing across objectives
objectives: - id: "01" title: Create VPC Infrastructure steps: - id: "01" title: Create VPC instructions: - Create a VPC with CIDR block 10.0.0.0/16 outputs: - name: 01_01_vpc_id type: AWS::EC2::VPC description: The VPC for all project resources
- id: "02" title: Create public subnets instructions: - Create two public subnets in different availability zones inputs: - 01_01_vpc_id outputs: - name: 01_02_subnet_a_id type: AWS::EC2::Subnet description: Public subnet in AZ-a - name: 01_02_subnet_b_id type: AWS::EC2::Subnet description: Public subnet in AZ-b
- id: "02" title: Deploy the Application steps: - id: "01" title: Create the load balancer instructions: - Create an Application Load Balancer in the public subnets inputs: - 01_01_vpc_id # from objective 01, step 01 - 01_02_subnet_a_id # from objective 01, step 02 - 01_02_subnet_b_id # from objective 01, step 02 outputs: - name: 02_01_alb_arn type: AWS::ElasticLoadBalancingV2::LoadBalancer description: The application load balancer - name: 02_01_alb_dns type: string description: The DNS name of the load balancerHow handles flow through the test runner
When the test runner executes a step, it:
- Runs the solution code, which creates the AWS resources and returns a dict of handle names to resource IDs
- Creates generated handles from the solution’s return value — these are unvalidated at this point
- Runs the evaluation code, which receives the generated handles alongside any events the resources emitted
- Promotes handles to resolved status for each handle the evaluation code includes in its
validatedlist
Evaluation code receives two categories of handles:
- Qualified handles — the full set of all resolved handles from prior steps, keyed by handle name
- Unqualified handles — the handles from the current step’s solution output, keyed by just the resource name (without the
{OO}_{SS}_prefix)
This means your evaluation code can reference context["resolved"]["01_01_vpc_id"] for a prior step’s VPC, or context["unqualified"]["vpc_id"] for the current step’s VPC.
Only handles that appear in the evaluation’s validated list are promoted to resolved and made available to subsequent steps. If a handle isn’t validated, downstream steps won’t receive it.
For the full evaluation code contract, see Evaluation code.