Skip to content

Add fastly-stats skill - #12

Open
zshenker wants to merge 7 commits into
fastly:mainfrom
zshenker:stats/add-fastly-stats-skill
Open

Add fastly-stats skill#12
zshenker wants to merge 7 commits into
fastly:mainfrom
zshenker:stats/add-fastly-stats-skill

Conversation

@zshenker

Copy link
Copy Markdown

Summary

Adds a new fastly-stats skill: a dedicated, self-contained reference for Fastly's stats/metrics APIs so an agent can get to the data without reading Fastly's docs — usable via the fastly CLI or by building raw URLs for curl/direct HTTP.

Stats were previously only lightly covered inside fastly-cli (references/stats.md, CLI-only). This skill goes deep on the full family of stats APIs across two hosts and three response shapes, with endpoints, query parameters, and response schemas documented inline.

What's included

skills/fastly-stats/
  SKILL.md                          # entrypoint: the two-hosts/three-shapes model,
                                    # auth + token safety, "choose the right API" table,
                                    # accurate CLI quick-reference, raw-URL templates,
                                    # workflows, POP-level diagnosis, limits
  references/
    historical-stats-api.md         # /stats* on api.fastly.com — from/to/by, flat envelope,
                                    # usage/billing (SI units, billable_units), regions
    inspector-api.md                # Origin & Domain Inspector, historical + real-time:
                                    # start/end/downsample, dimensions+values, cursor pagination
    realtime-api.md                 # rt.fastly.com /v1/channel polling model, Timestamp chaining
    fields.md                       # measurement/metric catalog (with TOC) + all_/compute_/waf_
    debugging.md                    # symptom-keyed troubleshooting

Also lists the skill in README.md. No manifest changes needed (skills are discovered by directory).

Design notes

  • Two hosts: api.fastly.com (historical) vs rt.fastly.com (real-time).
  • Three response shapes: classic flat {status, meta, msg, data}; Inspector dimensions+values with cursor pagination; real-time Data[].{recorded, aggregated, datacenter}.
  • Fixes an inaccuracy in the existing CLI docs: the inspector subcommands use --downsample/--metric/--group-by/--limit/--cursor (not --by/--field).
  • Complements the existing fastly-cli stats reference rather than replacing it (cross-referenced).
  • Copy-paste CLI + curl templates throughout; no bundled scripts to maintain.
  • Emphasizes the non-obvious pitfalls: NDJSON --json (use jq -s), decimal-SI vs binary units and raw-bandwidth-vs-billable-usage, UTC defaults, Origin/Domain Inspector as a paid add-on, real-time Timestamp chaining, cursor pagination, and preferring per-POP (datacenter) granularity (incl. flagging Shield POPs).

Validation

  • make validate ✓ (markdownlint, yamllint, jsonlint, frontmatter checks, plugin/extension validate)
  • make skillscheck (--strict) ✓ — 0 errors, 0 warnings

How it was tested

Developed and evaluated with the skill-creator workflow: with-skill vs. no-skill agent runs across three realistic tasks (cross-service bandwidth, live RPS/5xx watch, origin 5xx/latency), graded against explicit assertions. The skill scored 100% then 95% (against a stricter assertion set) vs. an 82% no-skill baseline, catching concrete errors the baseline made — mishandling NDJSON, missing cursor pagination, unprefixed Inspector metric names, and binary-GiB units.

🤖 Generated with Claude Code

zshenker and others added 7 commits July 25, 2026 13:32
New dedicated stats/metrics skill covering the Fastly CLI `stats`
commands and the raw Historical Stats, Real-Time analytics, and
Origin/Domain Inspector HTTP APIs. SKILL.md establishes the
two-hosts/three-response-shapes model, auth + token safety, a
"choose the right API" decision table, an accurate CLI quick
reference (inspector uses --downsample/--metric, NDJSON --json),
raw-URL templates, and common workflows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rences

- historical-stats-api.md: /stats* endpoints, from/to/by params, the
  flat {status,meta,msg,data} envelope, usage/billing, regions, legacy summary
- inspector-api.md: Origin/Domain Inspector historical (start/end/downsample/
  metric/group_by, dimensions+values envelope, cursor pagination) and real-time
- realtime-api.md: rt.fastly.com /v1/channel polling model, Timestamp chaining,
  AggregateDelay, response shape, and a correct poll loop

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… README

- fields.md: measurement/metric catalog (traffic, bytes, status, protocol,
  media, compute, security, real-time-only, meta) with a TOC and the
  all_/compute_/waf_ Inspector prefix explanation
- debugging.md: symptom-keyed troubleshooting (401/403, inspector-not-enabled,
  empty data, NDJSON, cursor pagination, real-time Timestamp misuse, casing)
- README: add fastly-stats to the Available skills list

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…trict

Rephrase the frontmatter description away from user-centric trigger
phrasing ("even if the user just says") toward agent-directed wording
so `skillscheck --strict` reports 0 warnings, while keeping it broad
enough to trigger on bare "stats/metrics/analytics/traffic/usage" asks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From the skill-creator eval review:
- Add a "Time and units" section: default to UTC when formatting; report
  bytes in decimal SI GB (1e9), not GiB; raw `bandwidth` != billable usage.
- Historical usage/billing: document SI units, request units of 10,000,
  header+body+origin composition, and billable_units; link the billing doc.
- Real-time: surface the `fastly stats realtime` CLI equivalent and use UTC
  (strftime) in examples.
- Inspector + fields: clarify edge processing time (hits_time/miss_time/
  pass_time in classic stats) vs origin latency histograms (Origin Inspector);
  note both are useful for edge-vs-origin diagnosis.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From iteration-2 eval feedback: default to pulling the per-POP
(datacenter) breakdown when diagnosing, since a healthy-looking
aggregate hides a single erroring/slow POP. New "Pinpoint issues with
POP-level data" section in SKILL.md, reinforced in the real-time and
inspector references. Also call out Shield POPs — in a datacenter
breakdown the shield POP carries edge-to-shield traffic, not client
traffic, and must be identified (fastly pops SHIELD column) and
presented separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements the shield-fields-and-window-traps plan. Every claim below was
verified against the live API on a shielded 3-tier service (DEN edge ->
IAD shield -> BOS shield -> origin) rather than written from docs.

Two of the plan's premises turned out to be wrong:

- Per-POP history DOES exist. `datacenter=` is honored, composes with
  by=minute|hour|day, and reconciles exactly (per-POP sum 392 = unfiltered
  total). Bad codes fail loudly ("invalid datacenter"). So the baseline rule
  is documented as prudence about retention (~1 day at by=minute), not
  impossibility.
- The collapse fields are `request_collapse_usable_count` /
  `_unusable_count`; the plan's suffix-less names return "Unknown field".

Found a worse trap than the plan predicted: sending `region=` alongside
`datacenter=` silently drops the POP filter — HTTP 200, meta.datacenter
null, whole-region numbers. The defense (assert `meta` echoes your filter)
is now documented, since the numbers themselves look fine.

Changes:

- fields.md: new "Shield & tier fields" section. shield_fetches vs
  origin_fetches is the one comparison that reveals tier topology; the
  *_resp_body_bytes direction trap is documented with the adjacency
  invariant that makes it self-checking (DEN.shield_fetch_resp_body_bytes
  == IAD.shield_resp_body_bytes == 339,506).
- fields.md: `Agg` column (counter/gauge/seconds/histogram) so aggregation
  shape travels with the field. Summing gauges is the most silently-wrong
  arithmetic available; origin_offload is confirmed to span header+body
  (documented formula reproduces the API's own value to the digit).
- fields.md: miss_histogram corrected — {millisecond_bucket: count} latency
  buckets, not time buckets.
- realtime-api.md: ts/h on /v1/channel verified working (returns up-to-120
  one-second records). "Never infer a time base from an endpoint name"
  callout; ts/h returns only seconds with traffic, so derive the window
  from `recorded` min/max rather than assuming 120.
- historical-stats-api.md: document GET /datacenters, and the three
  confusable groupings — region != stats_region, and `North-America`
  contains only four Canadian POPs and no US POPs, which is why
  region-level stats cannot isolate Canada.
- debugging.md: silently-wrong-scope entry, baseline-capture rule, and
  before/after attribution (controls, sigma-vs-percent).
- verification-method.md: new methods reference. NB the sigma figures and
  control-POP deltas are transcribed from the plan's session, not measured
  here — the field shapes are first-hand, the operational numbers are not.

Also fixes three bugs found while verifying, all in this skill's own docs:

- The documented auth pattern was broken. Bare `$(fastly auth token)`
  captures 174 bytes / 6 lines when a CLI upgrade is pending (the notice
  goes to stdout, so 2>/dev/null does not help), yielding curl: (43) or a
  spurious 401 while `fastly whoami` succeeds. Now `--quiet` throughout.
- `from=yesterday` resolves to 12:00 UTC, not midnight, silently dropping
  a morning — and it was used in a worked example.
- `fastly stats historical` has no `--datacenter`, so per-POP history is
  API-only; a table row implied a CLI equivalent that does not exist.

make ci passes (0 errors, 0 warnings); SKILL.md kept under the 5k-token
budget by pushing detail into references.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@@ -0,0 +1,135 @@
# Verifying a Change With Stats

@jedisct1 jedisct1 Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the purpose of that file.

It looks like a methodology essay on experimental design, with a thin Fastly costume.

It's a generic undergraduate lab-methods handout, telling the agent nothing about what Fastly actually returns., it seems to just tell the agent how to reason.

Figures seem to be based on some random test/example, and are not going to match a real users' account. None can be checked or reproduced.

I just teaches what the model already knows. There's zero unique Fastly content, so as Fastly documentation, it's not useful.

Can you clarify the intended purpose of that file?

Comment on lines +44 to +50
1. **A zero-to-nonzero transition.** If your change makes a POP start doing something it did not do
before, that metric going `0 → nonzero` needs no baseline model and has no confound. When a new
shield tier came online, its `shield` field went `0 → 209,432` per 120 s — nothing to dispute.
2. **A ratio within one window.** Hit ratio, offload, share-of-service. Immune to window
misjudgement because numerator and denominator come from the same samples.
3. **An absolute rate.** Weakest: needs a correct window *and* a baseline, and is the only form that
broke when a window was misread. If you must report one, print the derived window beside it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an agent skill, for agents, not a markdown document for humans.

There's too much prose (just increasing token usage) and formatting like ** and * is useless to agents.

@jedisct1

jedisct1 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Evaluation https://github.com/fastly/fastly-agent-toolkit-evals/tree/main/additional-experiments/stats-pr12

Quoting the verdict:

  1. Cut the size. 11,743 words to 4,465, 7 files to 4. Delete references/verification-method.md, merge the three API reference files into one, drop the DEN/IAD/BOS war stories and all 189 bold spans, and move the eight rules that actually decide correctness to the top of SKILL.md. Today "use decimal SI, not GiB" is a sub-bullet in the tenth section, and Part 2 shows it decides two of the five tasks.

  2. Give every endpoint one owner. A session loads fastly, fastly-cli and fastly-stats together, so three copies of the /stats* table are three copies in the same context window. fastly-stats has the best version, so let it keep the material and cut the other two down to a pointer: observability.md 1,018 to 407 words, fastly-cli/references/stats.md 1,769 to 463. The routing data says the agent already behaves this way, opening fastly-stats and nothing else; the duplicates are paying rent for text nobody reads.

    This includes the unit, window and gauge rules that f6dc310 put into both neighbours. They are there because main has no fastly-stats to point at, and about 85 words of them are duplicated between observability.md and fastly-cli/references/stats.md. Merging PR Add fastly-stats skill #12 removes the reason: collapse them into fastly-stats, which owns the conventions, and revert both neighbours to pointer-only. skills-trim is already in that shape and scores 24/25 on both models, so nothing is lost by doing it.

  3. Lead with the CLI. 15 curl invocations become 5, and the 5 that survive are the ones fastly stats genuinely cannot reach. Every avoidable curl costs a token substitution, a URL-encoded time string and a hand-written envelope walk, and PR Add fastly-stats skill #12 spends a whole debugging section on a failure that only exists because of the substitution.

  4. Fix the three wrong claims in Part 4.4. An unentitled Inspector returns HTTP 200 with an empty array, not an error, and fastly-cli has said so correctly all along. from=1 day ago&by=day, the skill's own first worked call, returns zero rows. The realtime CLI example filters on .Data[]? and silently prints nothing. All three produce confident wrong answers rather than visible failures, which is the worst failure mode for a reference an agent trusts.

  5. Narrow the description so three skills stop competing for the same question.

Recommendation: merge, but merge the trimmed version. The 82%-overlap number in Part 1 is an argument for consolidating ownership.

@jedisct1

jedisct1 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Token/wall time usage with Deepseek 4-Flash:

       skills mcp    trials   turns   wall s   prompt tok
       base   nomcp      25      15      182      176,173
       stats  nomcp      25      10      106      109,659
       trim   nomcp      25      11       85       93,445
       base   mcp        25      19      221      212,918
       stats  mcp        25      14      160      170,207
       trim   mcp        25      10       93       97,773

Trimming the fastly-stats skill significantly reduces wall time and price.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants