Agent skill
write-canary-transformations
Write correct transform blocks for Mission Control canary checks including fan-out, inline, and generated canary patterns. Use when adding transformations to canary checks, splitting a single check into multiple results, modifying check output, or generating child canaries from discovered resources.
Install this agent skill to your Project
npx add-skill https://github.com/flanksource/claude-code-plugin/tree/main/skills/write-canary-transformations
SKILL.md
Write Canary Transformations
Goal
Generate correct, production-ready Canary transform blocks from user intent.
Quick Decision Tree
Use this to pick the right transform pattern:
- Need one check result per item in response?
- Use fan-out transform (return JSON array of objects, each with
name).
- Use fan-out transform (return JSON array of objects, each with
- Need to modify only the current check result?
- Use inline transform (return one JSON object without
name).
- Use inline transform (return one JSON object without
- Need to generate new canary/canaries from discovered resources?
- Use canary transform (return object/array with top-level
spec).
- Use canary transform (return object/array with top-level
Golden Rules
- Prefer
transform.expr(CEL) by default overtransform.javascriptandtransform.template.- This is a convention for consistency and easier review, not a strict requirement.
- If JS/template is a better fit for the case, use it.
- End CEL transforms with
.toJSON(). - For fan-out transforms, always set deterministic
name. - Set
passexplicitly in transformed checks (do not rely on defaults). - Use
deletedAtwhen events can resolve/disappear. - Use
markFailOnEmpty: truewhen empty output should fail the check. - Keep check names stable across runs to avoid churn.
Output Contracts
A) Fan-out transformed checks
Return a JSON array (or object) of transformed check entries.
| Field | Required | Description | Example |
|---|---|---|---|
name |
Yes | Check name. Keep deterministic across runs. | db/instance-1 |
pass |
Recommended | Explicit pass/fail status. | true |
message |
No | User-facing summary. | Replication lag within threshold |
description |
No | Longer explanation/context. | Replica is healthy |
labels |
No | Labels for filtering/relationships. | { 'env': 'prod', 'team': 'platform' } |
namespace |
No | Override check namespace. | production |
icon |
No | UI icon override. | alert |
duration |
No | Duration in milliseconds. | 1200 |
start |
No | Start time. | 2026-02-13T12:00:00Z |
detail |
No | Structured detail payload. | { 'raw': r } |
data |
No | Additional arbitrary data. | { 'source': 'prometheus' } |
metrics |
No | Emitted metrics from transform. | [{ 'name': 'lag', 'type': 'gauge', ... }] |
deletedAt |
No | Mark transformed check as resolved/deleted at a time. | r.endsAt |
transformDeleteStrategy |
No | Behavior when transformed check disappears (Mark*,Ignore). |
MarkHealthy |
B) Inline transformed result
Return a single JSON object and omit name.
| Field | Required | Description | Example |
|---|---|---|---|
name |
Must omit | If set, this becomes fan-out behavior. | omit |
pass |
No | Override pass/fail status. | json.status == 'ok' |
message |
No | Override message. | 'status=' + string(json.status) |
description |
No | Override description. | 'Health summary' |
error |
No | Override error text. | 'response missing key' |
detail |
No | Replace detail payload. | { 'status': json.status } |
data |
No | Merge additional data into result data. | { 'apiVersion': json.version } |
duration |
No | Override duration (milliseconds). | 1200 |
metrics |
No | Add metrics emitted from transform. | [{ 'name': 'items', 'type': 'gauge', 'value': 10 }] |
C) Transform into canary/canaries
Return either one canary object or an array of canary objects.
| Field | Required | Description | Example |
|---|---|---|---|
name |
Yes | Child canary name. | generated-http-canary |
namespace |
No | Child canary namespace. | default |
spec |
Yes | Full child canary spec. | { 'schedule': '@every 5m', 'http': [...] } |
Canonical Snippets
1) Fan-out alerts into checks
transform:
expr: |
results.alerts.map(r, {
'name': r.name + r.fingerprint,
'labels': r.labels,
'icon': 'alert',
'pass': false,
'message': r.message,
'description': r.message,
'deletedAt': has(r.endsAt) ? r.endsAt : null
}).toJSON()
2) Prometheus series to checks
transform:
expr: |
dyn(results).map(r, {
'name': r.job,
'namespace': 'namespace' in r ? r.namespace : '',
'labels': r.omit(['value', '__name__']),
'pass': r.value > 0,
'message': 'job=' + r.job
}).toJSON()
3) Inline transform (no new checks)
transform:
expr: |
{
'pass': json.status == 'ok',
'message': 'status=' + string(json.status),
'detail': {
'status': json.status,
'checkedAt': string(time.Now())
}
}.toJSON()
4) Generate child canary from discovery
transform:
expr: |
{
'name': 'generated-http-canary',
'namespace': canary.namespace,
'spec': {
'schedule': '@every 5m',
'http': dyn(results).map(r, {
'name': r.Object.metadata.namespace + '/' + r.Object.metadata.name,
'url': 'https://' + r.Object.spec.rules[0].host
})
}
}.toJSON()
5) Generate multiple child canaries (array output)
transform:
expr: |
dyn(results).map(r, {
'name': 'http-' + r.Object.metadata.name,
'namespace': r.Object.metadata.namespace,
'spec': {
'schedule': '@every 5m',
'http': [{
'name': r.Object.metadata.name,
'url': 'https://' + r.Object.spec.rules[0].host
}]
}
}).toJSON()
6) Empty output should fail
markFailOnEmpty: true
transform:
expr: |
dyn(results.rows).map(r, {
'name': r.id,
'pass': true
}).toJSON()
Deletion / Lifecycle Controls
Use transformDeleteStrategy on the parent check when transformed checks may disappear.
Recommended values:
MarkHealthyMarkUnhealthyIgnore
Example:
transformDeleteStrategy: MarkHealthy
Stateful Transform Patterns
Use prior run state
last_result()gives previous result context.- Useful for cursors/time windows.
Pattern:
transform:
expr: |
{
'detail': {
'max': string(results.?newest.modified.orValue(last_result().results.?max.orValue('now-60d')))
}
}.toJSON()
Use outputs from dependency checks
If checks use dependsOn, you can use outputs.<checkName>... in expressions/tests.
Common Mistakes to Avoid
- Returning multiple transformed entries without
name. - Forgetting
.toJSON()in CEL expressions. - Non-deterministic names (e.g., random UUID every run).
- Forgetting to set
passfor fan-out checks. - Returning empty list unintentionally without
markFailOnEmpty. - Mixing canary-transform output (
spec) with check-transform output in same object.
Authoring Workflow
When user asks for a transformation:
- Identify source payload shape (
results,json, rows, messages). - Pick transform mode (fan-out / inline / canary).
- Build minimal output contract.
- Add
pass,message, stablename. - Add lifecycle fields (
deletedAt,transformDeleteStrategy) if needed. - Return full YAML block ready to paste.
If user provides sample payload, always base transform logic directly on that payload.
References
- Canary spec reference (use this when transform output generates canary
spec): https://flanksource.com/docs/reference/canary-checker/llms.txt
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
troubleshooting-health-checks
Debugs and troubleshoots Mission Control health checks by analyzing check configurations, reviewing failure patterns, and identifying root causes. Use when users ask about failing health checks, mention specific health check names or IDs, inquire why a health check is failing or unhealthy, or need help understanding health check errors and timeouts.
write-canary-tests
Write correct test blocks and assertions for Mission Control canary health checks. Use when creating canaries that need pass/fail conditions, adding test expressions, or writing assertions based on HTTP status, JSON response, exec output, or Kubernetes health.
troubleshooting-notifications
Investigates Mission Control notifications to identify root causes and provide remediation. Use when users mention notification IDs, ask about alerts or notifications, request help understanding "why did I get this notification", want to troubleshoot a specific alert, or ask about notification patterns and history. This skill retrieves notification details, analyzes historical patterns, routes to resource-specific troubleshooting (config items or health checks), correlates findings, and delivers actionable remediation steps with prevention recommendations.
troubleshooting-config-item
Troubleshoots infrastructure and application configuration items in Mission Control by diagnosing health issues, analyzing recent changes, and investigating resource relationships. Use when users ask about unhealthy or failing resources, mention specific config items by name or ID, inquire about Kubernetes pods/deployments/services, AWS EC2 instances/volumes, Azure VMs, or other infrastructure components. Also use when investigating why a resource is down, stopped, degraded, or showing errors, or when analyzing what changed that caused an issue.
promotion-eval-create
Create a promotion evaluation template for any system by gathering requirements through structured questions and generating a reusable evaluation skill. Use when users ask to create a promotion check, release readiness evaluation, environment health template, or want to build a custom evaluation workflow for systems beyond Mission Control.
promotion-eval-mission-control
Evaluates a Mission Control environment's platform health for release or promotion readiness. Checks health check pipelines, config scrapers, background jobs, notifications, event queues, and MC infrastructure. Use for pre-release checks, environment promotion, or environment status. Triggers: "check environment health", "is it ready for release", "pre-release health check", "evaluate environment", "promotion readiness", "environment status"
Didn't find tool you were looking for?