| name | k6-builder |
| description | Build runnable k6 artifacts from a plan or direct requirements. Use when users ask to generate k6 scripts, choose/apply executors in runnable options, or create single/multi-environment configs. Prefer this skill for any implementation output request, even if the user also mentions "executor" or "config". |
| user-invocable | true |
| disable-model-invocation | false |
| license | MIT |
| metadata | {"version":"0.1.0","category":"performance-testing","protocols":["http","grpc","browser","websocket"]} |
- User says: "generate runnable k6 script for this endpoint"
- User says: "build dev/staging/prod config with thresholds"
- User says: "which executor should I use and give me final options"
Mission
Generate runnable k6 artifacts safely and deterministically:
- script code
- scenario/options configuration
- single and multi-environment setup
Do not switch to planning-only discussion when user asked for implementation output.
Tool Discovery Protocol
At the beginning of the workflow, detect and use interaction tools in this order:
- If
AskUserQuestion exists, use it for required inputs.
- Else if
mcp:sampling or create_message exists, use native IDE modal interaction.
- Else if
confirm_action exists, use it for critical confirmations.
- Else emit the exact fallback and end the turn:
> [?] MISSING REQUIREMENT: Missing build input for runnable artifacts
missing: target, scenario type, SLA requirements, protocol
why: deterministic generation cannot proceed safely without minimum build inputs
next_question: What target URL or endpoint should this build use?
Do not continue generation after fallback.
Interoperability Fallback Contract
When fallback is required, always use this portable payload shape:
> [?] MISSING REQUIREMENT: <short missing requirement summary>
missing: <comma-separated missing fields>
why: <why generation cannot continue deterministically>
next_question: <single, specific question that unblocks the next step>
Do not emit final artifact content after this fallback.
Core Rules
1. **Adaptive Question System**: When critical parameters are missing, start with baseline planning questions and continue in the same question flow with any additional required questions:
- What is the target URL/endpoint? (if `target` missing)
- What scenario type do you need? Options: load, stress, spike, soak, smoke (if `scenario` missing)
- What are your SLA requirements? Example: p95<500ms,error<1% (if `sla` missing)
- What protocol should this test use? Options: http, grpc, browser (if `protocol` missing)
Round contract:
- Round 1: one consolidated baseline question block with all minimum required questions.
- Round 2: one optional tie-break block only when a critical ambiguity remains after Round 1.
- If required inputs are still unresolved after Round 2, emit the interoperability fallback and end the turn.
Partial template override for multi-environment requests:
- If
target or protocol is missing but the request clearly specifies multiple environments and a scenario, generate a partial script template with __ENV placeholders for all missing values.
- Mark each assumption with
[assumption-based] in a pending_questions block appended at the end of the artifact.
- The partial template must still satisfy all other invariants (named function, thresholds, load profile via defaults).
Partial template override for auth-only edge cases:
- If the user explicitly asks for an auth pattern/template and the scenario/protocol is clear but
target is missing, generate an auth-focused partial template.
- Use
__ENV.BASE_URL (or protocol-equivalent env var) placeholder and mark all unresolved values as [assumption-based].
- Append a
pending_questions block with one direct question for the unresolved target.
Additional questions must be integrated into the same question system, not handled as a separate side flow:
- Add an HTTP method question when
protocol=http and the method cannot be inferred safely.
- Add one or more authentication questions when auth is required or unknown and executable output depends on it.
- Add more questions only inside Round 1 or the single Round 2 tie-break block when other critical ambiguities or missing requirements are detected.
- Do not finalize artifact generation until all required questions from this same system are resolved.
-
Load Profile Defaults (when profile is not specified):
minimal: 5 VUs, 1m duration, smoke testing
standard: 25 VUs, 9m duration, realistic load
aggressive: 120 VUs, 14m duration, stress testing
-
Output Format: Primary output is runnable artifacts with:
- Recommended executor type
- VU count and stages/options
- Duration estimate
- SLA-derived thresholds
- Protocol-specific implementation notes
- Data integration suggestions (CSV/JSON)
- Exactly one deterministic
Next recommended step
-
Determinism: Same inputs produce identical outputs every time.
Terminology Contract
- Scenario type means the test objective shape (
load, stress, spike, soak, smoke).
- Profile means default intensity presets (
minimal, standard, aggressive) used when explicit vus/duration are missing.
- Round means one consolidated question block in the adaptive question system; baseline questions are Round 1 and the optional tie-break is Round 2.
- Scenario type selects the executor strategy; profile sets default intensity values.
HTTP Method Question
Before producing final HTTP artifacts, add the method question to the same active question system:
- Confirm primary method (
GET, POST, PUT, PATCH, DELETE) when endpoint behavior depends on method.
- If method is missing and cannot be inferred, ask it as an additional required question before finalizing.
- Reflect confirmed method in scenario steps, checks, and threshold rationale.
Auth Discovery Questions
Before finalizing artifact output, add auth questions to the same active question system:
- Detect whether authentication is required (Bearer token, API key, basic auth, mTLS, session cookie, or none).
- If auth is required or still unknown for executable output, ask for auth mechanism and required variable names as additional required questions.
- Never hard-code credentials in examples or generated scripts.
- Prefer environment variables (
__ENV) for auth inputs and list required variables.
Direct Invocation Behavior
If invoked without prior plan, the same Adaptive Question System above still applies.
Then:
- Build a minimal internal plan
- Expose assumptions
- Generate runnable artifacts
- Include a mandatory
k6-validate handoff block with one suggested validation command
Language Policy
- If user language is explicit, answer in that language.
- If language is not explicit, default to English.
- Keep command names, k6 metric keys, and code identifiers in English.
Dynamic Capacity Protocol
Run this protocol before emitting any runnable artifact.
Cross-skill required fields:
execution_context
machine_profile
projected_load
capacity_estimate
risk_status
safe_limit_recommendation
scale_out_recommendation
High-risk gate rule (mandatory):
- Before generating or orchestrating any script that projects more than
500 VUs, run host audit silently with node skills/k6-builder/scripts/audit-host.js.
- If Node.js is unavailable, use the Python fallback:
python3 skills/k6-builder/scripts/audit-host.py.
- Parse stdout JSON and use that as the authoritative
machine_profile for this generation pass.
Contextual deterministic formulas:
vus_max = (logical_cpu * cpu_factor) + (free_ram_gb * ram_factor)
arrival_rate_max = floor(vus_max / max(projected_load.expected_iteration_duration_seconds, 1))
Default context factors:
local: cpu_factor=50, ram_factor=10
ci: cpu_factor=30, ram_factor=6
container: cpu_factor=25, ram_factor=5
cloud: cpu_factor=60, ram_factor=12
distributed: compute per node, then aggregate
Evaluation order:
- Build
execution_context from the declared environment (local, ci, container, cloud, or distributed) plus user constraints.
- Derive
machine_profile from current evidence: logical_cpu, free_ram_gb, fd_limit, ephemeral_port_budget, environment type, and declared user restrictions.
- If projected load is expected to exceed
500 VUs, run host audit (node skills/k6-builder/scripts/audit-host.js, fallback python3 skills/k6-builder/scripts/audit-host.py) and overwrite missing or stale machine evidence with audit output.
- Add optional telemetry when available: prior k6 saturation, observed memory per VU, prior stable arrival rate, or prior port exhaustion signals.
- Derive
projected_load from the runnable executor shape: target VUs, arrival rate, duration, stages, and expected_iteration_duration_seconds for arrival-rate executors.
projected_load.expected_iteration_duration_seconds must come from explicit user input, prior measured telemetry, or a conservative [assumption-based] estimate called out in the output.
- If that field is unavailable, do not present
arrival_rate_max as fully deterministic.
- Calculate
capacity_estimate.vus_max and capacity_estimate.arrival_rate_max from the current machine_profile using contextual deterministic formulas. Never use a universal fixed VU ceiling.
- Classify
risk_status as SAFE, AT_RISK, or HIGH_RISK.
- Derive
safe_limit_recommendation and scale_out_recommendation, including additional_cpu_percent, additional_ram_gb, and additional_nodes.
Incomplete-data rules:
- If critical machine inputs are missing, ask one clarification question when that is the cheapest unblocker.
- If the scenario is otherwise clear, continue with a conservative
[assumption-based] estimate instead of inventing a global default capacity.
- Mark every derived field that depends on missing telemetry as
[assumption-based] and state the missing evidence explicitly.
Builder-stage gate behavior:
SAFE: emit runnable artifacts normally.
AT_RISK: runnable artifacts are allowed only if the output includes the canonical capacity alert, the reduced safe limit, and the distributed mitigation guidance.
HIGH_RISK: block runnable single-node artifact emission. Replace the runnable artifact section with a blocked-output explanation plus a reduced-load or distributed execution path.
When HIGH_RISK, the blocked-output explanation must use this exact format:
Your machine only has [X]GB of available/free RAM. Attempting to run [Y] VUs locally will collapse the load generator. Limit the local test to [Z] VUs or export this design to k6-operator (distributed execution).
Canonical alert format:
LOAD GENERATOR CAPACITY ALERT
Risk Detected: The requested scenario ([X] VUs) exceeds the load generator operating limit ([Y] VUs).
Impact: Possible metric skew, TCP port exhaustion, or k6 process collapse.
Recommendation: Reduce the scenario to [Z] VUs or use distributed infrastructure with at least [N] additional nodes.
Determinism rules:
Y must come from the current capacity_estimate.
Z must come from the current safe_limit_recommendation.
N must come from the current scale_out_recommendation.additional_nodes.
- The same request and machine evidence must produce the same capacity classification.
Required k6 Invariants
Always enforce these validations before returning output:
- Thresholds are required
- Parse from SLA when provided.
- If SLA missing, derive deterministic defaults and state them.
- Load profile is required
- Include explicit
vus and duration, or explicit staged/scenario equivalent.
- Parameter coherence is required
- Arrival-rate executors must satisfy
preAllocatedVUs <= maxVUs.
- Time-based executors require explicit duration.
- Iteration-based executors require explicit
vus and iterations.
- Secrets and runnable safety are required
- Never hard-code credentials/tokens.
- Require environment variables (
__ENV) for auth and base URL.
- Multi-environment coherence is required
- For
dev/staging/prod, validate dev <= staging <= prod for VU progression.
- Emit
WARNING if user override violates VU progression without explicit justification.
- SLA thresholds are invariants: the stated SLA must be identical across dev, staging, and prod. If any environment has relaxed thresholds (e.g.,
p99<2s in dev when the SLA states p99<1s), reject the artifact and report under Guardrail Validation.
- Named default function is required
- The
export default function must always have a name derived from the active scenario and protocol.
- Naming convention:
run<Protocol><ScenarioType> — example: runHttpLoad, runGrpcStress, runBrowserSmoke.
- If scenario or protocol is not resolved yet, use a generic but named function:
runPerfTest.
SLA Consistency Across Multi-Environment
When building for multiple environments (dev/staging/prod):
- Threshold values MUST BE IDENTICAL across all environments.
- VU counts MAY VARY per environment.
- Duration MAY VARY per environment.
- Performance SLA targets (p95, p99, error bounds) MUST NOT VARY per environment.
Rationale: SLA is a commitment and must remain coherent across environments. Relaxing SLA by environment creates non-comparable results and hides production risk.
Canonical cross-skill warning (must match k6-plan exactly):
WARNING: SLA must be identical across environments to maintain testing coherence.
Canonical enforcement flow (builder stage):
- Detect single declared SLA plus per-environment threshold divergence request.
- Emit the canonical warning string above.
- Ask one confirmation question:
Do you want to normalize all environment thresholds to the same SLA now?
- If user confirms normalization:
- Continue generation with identical thresholds across dev/staging/prod.
- If user rejects normalization:
- Reject runnable artifact emission and report violation under Guardrail Validation.
- Do not emit per-environment relaxed thresholds.
Builder Decision Rules
Scenario to Executor Mapping
load: ramping-vus
stress: ramping-vus (aggressive progression)
spike: ramping-vus (rapid surge)
soak: constant-vus or ramping-vus sustained
smoke: constant-vus
Request-Rate Intent
If user explicitly requires rate control, prioritize:
constant-arrival-rate for fixed RPS
ramping-arrival-rate for changing RPS
Iteration Intent
If user asks for exact iteration accounting:
per-vu-iterations or shared-iterations
Multi-Environment Differentiation Rules
When building multi-environment outputs (dev/staging/prod), apply mandatory differentiation:
- VU counts must differ explicitly across environments — never use identical values. Baseline pattern: dev ≤ staging ≤ prod.
- SLA-derived thresholds are invariants across all environments — never relax or adjust threshold values per environment. The stated SLA (e.g.,
p99<1s) must be applied identically to dev, staging, and prod. Only VU counts, durations, ramp-up stages, and load profiles may differ per environment. Any threshold relaxation (e.g., p99<2s in dev when SLA states p99<1s) is a hard invariant violation — reject and report under Guardrail Validation.
- Target URL must be distinct per environment — use
__ENV.DEV_BASE_URL, __ENV.STAGING_BASE_URL, __ENV.PROD_BASE_URL as named environmental variables.
- SLA-derived thresholds must be applied even when the target URL is missing — use defaults from the stated SLA (e.g.,
p99<1s) with __ENV placeholder for the URL.
- Structure: use three distinct scenario blocks or a clearly labeled
profiles object with per-env overrides — never collapse to a single block relabeled with comments.
Multi-Environment Architecture Options
When user requests multi-env outputs, offer two architecture options and make the default explicit:
Option 1: Separate Scripts
- Files:
dev.js, staging.js, prod.js
- Pros: Strong isolation per environment
- Cons: Duplication and cross-env maintenance overhead
Option 2: Single Script with Environment Switcher (recommended default)
- File:
load-test.js
- Pattern:
__ENV.ENVIRONMENT selects environment-specific VUs/duration
- Pros: DRY, single source of truth for shared logic and thresholds
- Cons: Slightly more control-flow branching
Default behavior:
- Recommend Option 2 unless user explicitly asks for separate files.
- Still mention Option 1 as an available alternative.
- Keep SLA thresholds identical regardless of selected architecture.
SLA Parsing Rules
Parse SLA string to extract threshold conditions. Supported syntax:
Simple Conditions (single metric)
p95<Xms -> 95th percentile latency threshold
p99<Xms -> 99th percentile latency threshold
error<X% or rate<X% -> Error rate threshold
Comma-Separated Lists (implicit AND)
p95<500ms,p99<900ms,error<1% -> All conditions must be met
- Commas separate independent thresholds
- All listed thresholds are combined in final configuration
Explicit AND Conditions (multiple conditions on same metric)
p95<500ms AND p95>100ms -> p95 must be between 100ms and 500ms
- Multiple constraints on the same metric (range validation)
- Translates to multiple threshold entries for the same k6 metric
Note: OR logic is not supported in this skill behavior. All conditions are treated as mandatory (AND).
Parsing Examples
- Input:
p95<400ms,error<1% -> p95 AND error rate thresholds
- Input:
p95<500ms AND p99<900ms -> Both percentiles required
- Input:
p95<2s -> Single threshold with p99 inferred (see sla-defaults.md)
Defaults per profile when SLA is not provided:
minimal: p95<800ms, error<2%
standard: p95<500ms, error<1%
aggressive: p95<300ms, p99<700ms, error<0.5%, checks>99%
Protocol-to-Threshold Mapping
When generating thresholds, apply the correct metric per protocol. Using http_req_duration for non-HTTP protocols is a hard invariant violation.
| Protocol | Required threshold metric |
|---|
| HTTP | http_req_duration: ['p(95)<Nms'] |
| WebSocket | ws_session_duration: ['p(95)<Nms'] (built-in session duration metric) |
| gRPC | grpc_req_duration: ['p(99)<Nms'] |
| Browser | browser_http_req_duration: ['p(95)<Nms'] |
If the inferred protocol does not match http, ensure the threshold uses the correct metric above — never substitute http_req_duration as a fallback.
Base URL Template Rule
When generating artifacts (single or multi-environment):
For HTTP/gRPC/Browser protocols:
For multi-environment outputs:
- Always use pattern:
__ENV[${env.toUpperCase()}_BASE_URL]
- Append a
.env.example stub with all required variables.
Validation: After artifact generation, scan for violations:
- If protocol in [http, grpc, browser] and artifact contains
= 'https:// or = "https:// without __ENV, REJECT.
- Add to guardrail validation checklist:
[ ] Base URL uses __ENV, not hardcoded literals
Protocol-Specific Generation
### HTTP
- Use `http.get()`, `http.post()`, `http.batch()` for parallel requests
- Metrics: `http_req_duration`, `http_req_failed`
- Include explicit timeout guidance (baseline `timeout: '30s'`) for executable HTTP examples; missing timeout should be validated as `WARNING`.
- Tag requests: `tags: { name: 'api-call' }`
gRPC
- Use
grpc.Client(), client.load(), client.connect(), client.invoke()
- Metrics:
grpc_req_duration, grpc_req_failed
- Always close connections in teardown
- Handle metadata for authentication
Browser
- Use
browser.newContext(), context.newPage(), page.goto(), page.waitForSelector()
- Always close page/context at iteration end
- Prefer
data-testid selectors
- Collect Web Vitals when relevant
- For requested multi-step user journeys, model the full sequence explicitly in order (do not collapse or skip steps).
- For checkout/browser journeys, include an end-to-end threshold aligned to the requested KPI/SLA (for example
p(95)<4000 when the request states p95<4s).
WebSocket
Dashboard Policy
Apply deterministic recommendation:
- CI/headless:
K6_WEB_DASHBOARD=false
- Local browser troubleshooting:
K6_WEB_DASHBOARD=true
- Local non-browser: default
K6_WEB_DASHBOARD=false unless explicit opt-in
- Otherwise default
false
Output Contract
Every response must include these sections in order:
- Build Inputs Summary
- Internal Minimal Plan
- Executor and Scenario Configuration
- Runnable Artifacts
- Thresholds
- Environment Configuration (single or multi-env as requested)
- Guardrail Validation — include this checklist at minimum:
- Assumptions & Defaults — compact format required:
- Keep this section to 3 lines maximum.
- Line 1:
Provided: <comma-separated provided inputs>
- Line 2:
Defaults Applied: <comma-separated key=value defaults>
- Line 3 (only when provisional/partial):
Pending Questions: <single unblocker question>
- Preserve explicit
[provided] and [assumed] tags inline per key-value token.
- Validation Handoff (required) — include one runnable command for
k6-validate
/k6-validate
- **For other scenarios** (load, stress, soak, spike): Include validation recommendation that references k6-validate.
- Execution Hints (required)
- Include at least one concrete run command that can be copied as-is.
- Include required environment variables used by that command.
- Use deterministic command shape (
k6 run <script> plus -e flags when needed).
- Keep hints runnable and aligned with the emitted artifact names.
- Treat
Execution Hints as a hard companion of Runnable Artifacts: if artifact code exists, hints must include the exact script filename and matching env var flags.
- Never emit conceptual guidance only; include at least one concrete copy-paste command.
- Next recommended step
Dynamic capacity reporting requirements:
-
Build Inputs Summary must include execution_context.
-
Internal Minimal Plan must include machine_profile and projected_load.
-
Guardrail Validation must also include these checklist items:
-
When risk_status is HIGH_RISK, Runnable Artifacts must not include a single-node runnable artifact.
Runnable Artifact Rules
- Always prefer
__ENV.BASE_URL for runnable scripts.
- Include timeout guidance for HTTP (
timeout: '30s' baseline).
- Include checks and request tags for segmentation.
- For auth, list required env vars and never place secret literals.
- For multi-env requests, include
.env.example placeholders only.
- Any output containing URLs, auth headers, or any configurable external value must include an explicit
## Required Environment Variables block listing each __ENV.VAR_NAME with a one-line description of its purpose.
- The
## Required Environment Variables block must be concrete and non-empty; include every required runtime variable and avoid generic placeholders like "add your vars here".
- For multi-env outputs, always include a
.env.example stub section with three labeled groups (# dev, # staging, # prod) showing the expected variable names as empty placeholders.
- This block is mandatory and must appear even when the target URL is a placeholder — document the placeholder variable name.
- For browser or transaction flows with multiple business steps, emit the full ordered step list in code/comments so the generated artifact preserves the requested journey sequence.
Code Quality Rules
Generated code must not introduce static-analysis violations. Before emitting any artifact:
-
Named exports — export default function must be named (see Required k6 Invariants #6).
- Generate using naming convention:
run<Protocol><ScenarioType> (e.g., runHttpLoad(), runGrpcSmoke()).
- VALIDATION (MANDATORY): After code generation, scan the artifact for
export default function followed by (.
- If the pattern matches
export default function\s*\( (anonymous), REJECT the artifact immediately.
- Add to guardrail violations: "Default export function must be named (e.g.,
runHttpLoad)". Do not emit unless function is named.
-
No var declarations — use const or let only.
-
No console.log in hot paths — inside export default function or any function called per iteration.
-
No hardcoded literals for URLs or credentials — all configurable values must use __ENV.
-
No silent catch blocks — errors must be logged or re-thrown with context.
-
No unsafe JSON.parse — wrap in try-catch with descriptive error message.
If any generated line would violate a rule above, block the artifact and report the specific violation under Guardrail Validation instead of emitting broken code.
Progressive Disclosure
Keep this file focused on generation workflow. Place deep guidance in:
skills/k6-builder/references/README.md
Workflow
- Parse parameters (
target, scenario, sla, protocol, profile, duration, vus, environments, goal).
- Run Tool Discovery Protocol when minimum inputs are missing.
- Start the Adaptive Question System with baseline questions when
target, scenario, sla, or protocol are missing.
- Add an HTTP method question to the same question system when protocol is HTTP and method is still ambiguous.
- Add auth questions to the same question system when auth is required, unknown, or otherwise blocks executable output.
- Add more questions in the same system if other critical ambiguities or missing requirements are detected.
- Build internal minimal plan from inputs.
- Select executor and derive coherent scenario config.
- Enforce executor coherence: if scenario type is
load and the user did not explicitly request rate-based control, recommend and emit ramping-vus.
- Parse SLA thresholds or apply deterministic defaults.
- Run the Dynamic Capacity Protocol using current machine evidence and projected workload (mandatory host audit first when projected load exceeds 500 VUs).
- For multi-environment requests, choose architecture using Multi-Environment Architecture Options (default single-script unless explicitly overridden).
- Generate runnable script/options/config outputs only when the capacity gate allows them.
- Apply dashboard and secrets safety policies.
- Validate all required invariants, including: (a) the generated default export function is named — reject anonymous
export default function () {}; (b) SLA thresholds are identical across all environments — reject any per-environment threshold relaxation. Both are hard invariant violations that block output emission.
- Return output in Output Contract order.
Local Evaluation Workspace Policy
For official skill evaluation runs in this repository:
- Store artifacts under
skills/k6-builder/k6-builder-workspace/iteration-N/.
- Keep each run isolated inside its own
iteration-N directory.
- Treat benchmark outputs, grading files, timing files, and generated responses as non-versioned execution artifacts.