# Collectors Metadata YAML

> Content rules for collector metadata.yaml, field by field, for every collector family (go.d, C plugins, scripts.d, Rust plugins, ibm.d via its docgen sources). Use when writing or reviewing a collector's metadata.yaml; when asked what goes on the integration page, in the overview, metrics description, method description, auto-detection, limits, performance impact, permissions, prerequisites, the config options table, examples, troubleshooting, metrics scopes, or alerts; when a generated integration page reads as a wall of text or says something false about defaults or discovery. Not for the generator pipeline, JSON schemas, or generated outputs (integrations-lifecycle), and not for config_schema.json (collectors-go-design/config-schema.md).

- Skill: `netdata/collectors-metadata-yaml` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add netdata/collectors-metadata-yaml`
- Raw SKILL.md: https://api.skillmd.com/api/skills/netdata/collectors-metadata-yaml/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: netdata (https://skillmd.com/u/netdata)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/netdata/collectors-metadata-yaml

---


# Collector metadata.yaml: The Page The User Reads

`metadata.yaml` is the source of the integration page on Learn and of the catalog row that leads to it. Users open that
page to decide whether to run the collector, what they will get, what it needs, and what it costs. Every field in it is
product copy for an operator, not developer documentation. This skill owns what each field says and how it reads.

## Ownership

- This skill: the content of every collector `metadata.yaml` field: what it answers, in what order, in what shape,
  for whom. Rules are cross-plugin. ibm.d metadata is generated by `docgen` and never edited: `module.yaml` holds the
  identity and the overview `description`, `contexts.yaml` the metric rows; every other field (method, permissions,
  default behavior, keywords, option rows, prerequisites, examples, troubleshooting) is a constant in docgen's
  metadata template (`src/go/plugin/ibm.d/docgen/main.go`, see `integrations-lifecycle/ibm-d.md`), so applying these
  rules there means changing the template. `config.go` feeds the schema and README, not the options table.
- `.agents/skills/integrations-lifecycle/`: mechanics. JSON schemas, generators, validation commands, artifacts and
  banners, the ibm.d generation chain, and the cross-type page meta-description derivation contract
  (`description-authoring.md`).
- `.agents/skills/collectors-go-design/config-schema.md`: the DynCfg form. Option wording shared between the
  form and the options table has one owner there (sections 7 and 8); this skill points to it.
- `.agents/skills/collectors-go-design/operator-surface.md`: which options exist and what an operator decides.
  Decided before this skill applies.

## How The Page Is Rendered

Facts every rule below relies on (`integrations/templates/overview/collector.md` and siblings):

- The template owns the heading hierarchy (h1 title; h2 Overview, Setup, Troubleshooting, Alerts, Metrics, and Live
  Data when the collector has Functions; h3 to h6
  inside them, down to one h5 per option depth block and one h6 per example). Field text is inserted under those
  headings as-is.
- Field text is Markdown rendered by Docusaurus on Learn. Paragraphs, lists, tables, inline code, fenced code, links,
  and `:::` admonitions (`note`, `tip`, `caution`) pass through the generator untouched.
- Some empty fields are not empty on the page. `auto_detection`, `limits`, and `performance_impact` render a template
  placeholder sentence that asserts something about the collector (see `overview.md`). An empty field is a claim.
- The first sentence of `metrics_description` is the catalog row and the page meta description; its mechanics and
  length contract are in `integrations-lifecycle/description-authoring.md`.
- Generated pages under `integrations/` and the `README.md` symlink are outputs. Fix the source; never edit them.

## The Reading Model

- The reader is an operator scanning a page, deciding in this order: what is this, what do I get, what do I need,
  what does it cost, how do I set it up, what went wrong. Fields are ordered that way by the template; write each
  field for the question it sits under.
- Readers stop when they have enough. The first paragraph of every field MUST stand alone; detail follows in
  decreasing importance.
- Readers skip walls of text ("I ain't reading all that"). Long content is fine when it is structured: one idea per
  paragraph, lists for enumerations, tables for items that share attributes, an admonition for what must not be
  missed. Length is a symptom to check, not the rule; an unstructured 120-word paragraph fails, a 400-word field made
  of a table and three short paragraphs may pass.
- Operator voice. The page describes what the collector does as the operator sees it: connections, requests,
  commands, files, permissions, what it creates and deletes, what it never touches. Engine vocabulary (journal,
  state machine, reconciliation, plan compiler, snapshot) MUST NOT appear; define any unavoidable term at first use.

## Routing By Field Family

| Family | Fields | Rules |
|---|---|---|
| Overview | `metrics_description`, `method_description`, `supported_platforms`, `multi_instance`, `additional_permissions`, `default_behavior.*` | `overview.md` |
| Setup | `prerequisites`, `configuration.file`, `configuration.options` (rows, `detailed_description`, groups), `configuration.examples` | `setup.md` |
| Troubleshooting | `troubleshooting.errors` (the known-errors catalog), legacy `troubleshooting.problems` | `troubleshooting.md` |
| Metrics | `metrics.scopes`, labels, metric `description` and `unit`, `dynamic_context_prefixes`, `availability` | `metrics.md` |
| Alerts, meta, Functions | `alerts`, `meta.monitored_instance`, categories, keywords, icon, `related_resources`, `info_provided_to_referring_integrations`, `functions` (the Live Data section) | `alerts-and-meta.md` |

## Depth Boundary

Content that does not answer its field's question does not stay in the field. Route it:

- Another field on the page owns it (a permission belongs in `additional_permissions`, a knob in its option row's
  `detailed_description`, a failure in `troubleshooting`, a chart in its metric `description`).
- The collector's profile format documentation (`profile-format.md`) owns it, for profile-driven collectors.
- A `docs/guides` page owns it when it is an operator procedure spanning several products.
- It is developer content (internal stages, caches, bounds nobody configures, ownership resolution). It belongs in the
  collector's `ARCHITECTURE.md` or in code, is never linked from the page, and leaves the page.
- Nothing owns it: cut it.

## Safety Of The Markdown

Field text travels through the generator into MDX. These break the Learn build or the page silently:

- Placeholders in angle brackets (`<service-name>`, `<region>`) parse as JSX. Put them in backticks, like every other
  code-shaped expression (option names, paths, values).
- Generics and any other angle-bracket syntax in prose (`Vec<u32>`, `HashMap<K,V>`) parse the same way. Backticks.
- A bare `<` before a digit (`<100 ms`) fails the build. Write "under 100 ms" (or `&lt;` when the symbol must stay).
- Smart quotes from editors and an unbalanced backtick break code detection. Use ASCII quotes; balance backticks.
- Tables need a header separator row and the same number of cells on every row; an admonition needs its closing
  `:::` on its own line.
- Learn's ingest escapes only bare `{`, `<=`, `%<`, `<->`, and `<details><summary>`. `test_collector_metadata` checks
  the rest here; anything it misses appears on the next Learn deploy preview, not in this repo's CI.

## Review Checklist

Before committing a collector `metadata.yaml` (or an ibm.d `module.yaml`) change:

1. Regenerate and read the page: `python3 integrations/gen_integrations.py`, then
   `python3 integrations/gen_docs_integrations.py -c <plugin>/<module>` (for example `go.d.plugin/cloudwatch`), open
   the collector's file under `integrations/`, read it as the operator top to bottom once, then `git restore` the
   regenerated page. The first script writes only gitignored outputs (`integrations.js`, `integrations.json`); the
   second writes the page.
2. Every field answers its own question (the family file's contract), leads with what matters, and would survive the
   reader stopping after its first paragraph.
3. No field is over-scoped: no headings, at most two or three bold captions, at most one admonition, no glossary
   before the reader knows what the collector does.
4. Empty `auto_detection`, `limits`, or `performance_impact` only where the placeholder sentence is true. A collector
   covered by a service-discovery rule, or with a cardinality cap or a metered API, fills them.
5. No engine vocabulary; every term defined at first use; no developer links (`ARCHITECTURE.md`, source files).
6. Statements verified against the code, not against the previous prose: permissions, defaults, what is created or
   deleted, limits, addresses probed.
7. Markdown safety items above; then `python3 -m unittest integrations.tests.test_collector_metadata` (the mechanical
   checks of this skill) and the pipeline validation in `integrations-lifecycle/description-authoring.md`
   (`gen_docs_integrations.py --check`, `test_descriptions`).
8. Generated hunks under `integrations/` are not part of the commit; the post-merge regeneration owns them.

