validation

SkillMonitoring & ops

Use after creating or modifying ANY Honeydew object (metric, attribute, entity, domain). Provides type-specific validation logic to ensure objects work correctly and return sensible results.

Use validation in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add validation and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the validation skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

validationStart free

What this skill tells your AI

The instructions your AI receives, as published by hashgraph-online/awesome-codex-plugins in plugins/honeydew-ai/honeydew-ai-coding-agents-plugins/skills/validation/SKILL.md and read by ahel’s review.

Overview

This skill is MANDATORY after creating or modifying any Honeydew object.

Validation ensures:

  • The object compiles and executes without errors
  • Results are returned (not NULL or empty)
  • Values make business sense
  • Related objects are consistent with each other

Validation by Object Type

Metrics

Step 1: Execute the metric

Call get_data_from_fields with:

  • metrics: ["<entity>.<metric_name>"]

If the tool call fails (API error, permission denied, timeout), report the error to the user before proceeding. Do not confuse a tool error with suspicious data.

Step 2: Sanity checks

CheckWhat to Look ForAction if Failed
Returns dataNot NULL, not emptyCheck SQL syntax, entity references
MagnitudeReasonable for business contextVerify calculation logic
SignPositive for revenue/counts (usually)Check for inverted logic
Related metricsParts sum to wholeQuery related metrics together and verify consistency
RatiosBetween 0-100% (usually)Check numerator and denominator metrics independently

Step 3: Cross-validation

If the new metric is a filtered subset of an existing metric, or a ratio of existing metrics, query them together to verify consistency:

  • For filtered metrics: query the filtered metric alongside the unfiltered total — the filtered value should be less than or equal to the total.
  • For ratio/derived metrics: query the numerator and denominator independently to confirm they return sensible values before checking the ratio.

Call get_data_from_fields with both metrics:

  • metrics: ["<entity>.<filtered_metric>", "<entity>.<total_metric>"]

Alert user if:

  • Metric returns $0 or NULL unexpectedly
  • Revenue/count is negative
  • Ratio exceeds 100% or is negative (unless expected)
  • Magnitude seems off by orders of magnitude

Attributes

Step 1: Execute the attribute

If the attribute references a related entity (multi-entity attribute), first verify the relation exists using get_entity on the source entity. If the relation is missing, report that before attempting to query the attribute.

Sample rows — call get_data_from_fields with:

  • attributes: ["<entity>.<attribute_name>"]

For boolean attributes, check distribution — call get_data_from_fields with:

  • attributes: ["<entity>.<boolean_attribute>"]
  • metrics: ["<entity>.count"]

Step 2: Sanity checks by attribute type

Attribute TypeValid RangeRed Flags
Age/Duration0 to reasonable maxNegative values, >150 years
BooleanTRUE/FALSE mixAll TRUE or all FALSE
Percentage0-100 (usually)Negative, >100 (unless growth rate)
DatePast to near futureYear 1900, year 2099, all NULLs
Category/BucketExpected labels95%+ in "Unknown" or NULL
RankStarts at 1, consecutiveStarts at 0, gaps, all same value
Running totalMonotonically increasingDecreases, resets unexpectedly
Any typeMix of values>50% NULLs warrants investigation

Alert user if:

  • All values are NULL or >50% NULLs
  • Boolean is 100% one value
  • Dates are invalid or in wrong century
  • Buckets are mostly "Unknown"

Entities

Step 1: Verify entity was created

Use list_entities and filter results for the new entity name.

Step 2: Verify data flows

Call get_data_from_fields with:

  • metrics: ["<entity>.count"]

Also call with a list of attributes to verify they are accessible:

  • attributes: ["<entity>.<attribute1>", "<entity>.<attribute2>", "<entity>.<attribute3>"]

Step 3: Sanity checks

CheckWhat to Look ForAction if Failed
Entity existsShows in list_entities resultsCheck create_entity call
Has rowsCount > 0Verify source table path
Key is uniqueCount = count distinct of keyFix key or add composite key
Attributes accessibleCan query attributesCheck dataset definition

Alert user if:

  • Entity not found after creation
  • Zero rows returned
  • Key column has duplicates (for non-fact tables)
Validating Relations (part of entity validation)

Relations are not standalone objects — they are defined within an entity's YAML. Validate them as part of the entity that contains them.

Step 1: Verify relation exists

Use get_entity on the source entity and check its relations list for the new relation.

Step 2: Test the join works

Call get_data_from_fields with a cross-entity query:

  • attributes: ["<target_entity>.<attribute>"]
  • metrics: ["<source_entity>.<metric>"]

Step 3: Sanity checks

CheckWhat to Look ForAction if Failed
Relation existsShows in get_entity resultsCheck update_object call
Join worksCross-entity query succeedsVerify join keys match
No fan-outCounts don't explodeCheck cardinality (many-to-one vs many-to-many)
NULLs reasonableSome NULLs OK for left joinToo many NULLs = bad join key

Alert user if:

  • Relation not found on the entity
  • Cross-entity query fails
  • Row count explodes (indicates wrong cardinality)
  • All joined values are NULL (bad join condition)

Domains

Step 1: Verify domain exists

Use search_model (with search_mode: EXACT) to find the new domain by name.

Step 2: Test with a scoped query

Call get_data_from_fields with the domain parameter to verify entities are accessible and filters apply:

  • metrics: ["<entity>.count"]
  • domain: "<domain_name>"

Step 3: Verify filters apply

If the domain has semantic or source filters, compare results with and without the domain to confirm filters reduce the data as expected:

  • Query a metric with the domain set — note the result.
  • Query the same metric without the domain — note the result.
  • The domain-scoped result should be less than or equal to the unscoped result (for filters that restrict rows).

Step 4: Sanity checks

CheckWhat to Look ForAction if Failed
Domain existsFound via search_modelCheck create_object call and YAML syntax
Entities accessibleScoped query returns dataVerify entity names match existing entities
Filters applyScoped count <= unscoped countCheck filter SQL and entity.field references
Field selectors workExcluded fields not returned in queryVerify selector patterns and order
No errorsQuery executes without compilation errorsCheck filter SQL syntax, fully qualified refs

Alert user if:

  • Domain not found after creation
  • Scoped query returns an error (likely bad filter SQL or missing entity)
  • Filters have no effect (scoped count equals unscoped count when a filter is expected to reduce rows)
  • Excluded fields are still accessible (field selector not applied correctly)

Validating Updates (update_object)

When modifying an existing object, compare before and after:

  1. Before altering, query the object and note the current result.
  2. After altering, query again and compare.
  3. Report the difference to the user: "The metric revenue changed from $1,234,567 to $1,198,432 after applying the discount logic."

This confirms the change had the intended effect and helps catch unintended regressions.


Error Handling

If a tool call fails, distinguish between:

SituationMeaningAction
Tool returns an errorAPI error, permission denied, timeout, invalid YAMLReport the error message to the user. Do not treat as a validation failure — the object may not have been created.
Tool returns empty/NULL dataObject was created but returns no resultsProceed with sanity checks — likely a data or SQL issue.
Tool returns unexpected valuesObject works but results look wrongReport findings and ask user before attempting a fix.

Alerting Guidelines

When results seem wrong, report to the user with:

  1. The actual value returned by the query
  2. Why it looks suspicious (e.g., negative revenue, 100% NULL, row count doubled)
  3. A suggested next step (e.g., "Should I check the SQL expression?" or "Should I verify the join keys?")

Do not silently fix issues — always surface findings and ask before making changes.


Quick Reference

ObjectExecute WithKey Checks
Metricget_data_from_fields with metrics listValue, magnitude, sign, consistency
Attributeget_data_from_fields with attributes listRange, distribution, NULLs
Entitylist_entities + get_data_from_fieldsExists, has rows, key unique
Relationget_entity + cross-entity field queryExists, joins work, no fan-out (validated as part of entity)
Domainsearch_model + get_data_from_fields with domainExists, filters apply, fields scoped

Signals

GitHub stars
1k
Forks
316
Last commit
Oct 2026
Advanced
Item type
skill
Key
validation-hashgraph-online
Source
github.com/hashgraph-online/awesome-codex-plugins