Repository navigation
Add fastly-stats skill - #12
Conversation
| @@ -0,0 +1,135 @@ | |||
| # Verifying a Change With Stats | |||
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Purpose question answered by deleting it — you were right. It was a methodology essay in a Fastly costume, its figures came from one past investigation and can't be reproduced on anyone else's account, and it taught the model things it already knows. Its actionable residue (baseline first, control POPs, sigma not percent, replicate, sanity-check ranges) is six bullets, which is what survives at the end of references/debugging.md; debugging.md already carried a shorter version of the same list, so nothing unique was lost.
| 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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Agreed and applied across the whole skill, not just this file: all 189 **bold** spans are gone, prose is cut to ~5.0k words from ~10.7k, and the rules that decide correctness are a numbered list on the first screen of SKILL.md rather than emphasis buried in prose.
|
Evaluation https://github.com/fastly/fastly-agent-toolkit-evals/tree/main/additional-experiments/stats-pr12 Quoting the verdict:
Recommendation: merge, but merge the trimmed version. The 82%-overlap number in Part 1 is an argument for consolidating ownership. |
|
Token/wall time usage with Deepseek 4-Flash: Trimming the |
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>
…nership Addresses the PR fastly#12 review. The eval campaign showed the skill's content is right but its packaging is not: the same pass rate holds on 62% less text, at 17% fewer prompt tokens and 27% less wall clock. Cut the size. 7 files to 4, ~10.7k words to ~5k. Delete verification-method.md (its actionable residue is six bullets in debugging.md), merge the three API reference files into references/api.md, drop the war stories, and remove every bold span. The eight rules that decide correctness are now a numbered list at the top of SKILL.md instead of sub-bullets in the tenth section. Give every endpoint one owner. A session loads fastly, fastly-cli and fastly-stats together, so three copies of the /stats* material is three copies in one context window. fastly-stats keeps the endpoints and the unit, window and gauge conventions; observability.md drops to 407 words and stats.md to 530, both pointer-only for the material fastly-stats owns. stats.md keeps the flag matrix, which is the CLI skill's job. Lead with the CLI. Six curl invocations against eight fastly ones, and the raw API section is scoped to the five things the CLI genuinely cannot reach. Fix the three wrong claims, all verified against a live account: - An unentitled Inspector returns HTTP 200 with "status":"success" and an empty data array, not an error. Confirmed on a service with both products off. fastly-cli had this right all along; that version is now the only one. - from=1 day ago&by=day returns zero rows. A bucket is emitted only for a period wholly inside the window, so a relative from drops the ragged ends: measured live, "8 days ago" loses a day that explicit UTC boundaries return. - The realtime CLI example filtered on .Data[]? and silently printed nothing. fastly stats realtime --json emits flat {recorded, aggregated, datacenter} per line with no Data wrapper; the corrected filter reports 17 requests over a 15 s span where the old one reported nothing. Every code block in the skill was executed against a live account before commit. Two findings from that verification beyond the review: - On a Compute service the traffic lands in compute_requests and requests stays 0, so summing requests alone reports an idle service that is serving fine. Now rule 9, with the worked examples summing both. - Sending region and datacenter together drops the POP filter and returns a meta that omits the datacenter key entirely rather than setting it to null. Kept two details the trimmed proposal dropped: the publication-lag timings and the reason datacenter= is unreachable from the CLI (missing from the SDK input type, not just the flags). Rejected its claim that repeatable flags reject comma-separated values; the CLI joins them with commas before the request, so both forms are equivalent, as fastly-cli already documented. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
e830716 to
5377d16
Compare
|
Thanks for the campaign — the 1. Size. 7 files to 4, ~10.7k words to ~5.0k. 2. One owner. 3. CLI first. Six curl invocations against eight 4. The three wrong claims. All three reproduced against a live account before fixing:
5. Description narrowed to your wording. Every code block in the skill was executed against a live account before commit, and that turned up two things worth adding:
Two places I did not follow
|
| | `downsample` | `minute`, `hour` or `day`. This is the Inspector's `by`. | | ||
| | `metric` | Comma-separated metric names. This is the Inspector's `field`. | |
There was a problem hiding this comment.
Fixed — Inspector param table, normalized by prettier along with the rest.
…payload Run prettier over the fastly-stats files so table pipes align. The ragged tables were hand-padded by eye and survived CI because .markdownlint.json checks table structure (MD055/MD056) but not pipe alignment. Rewrap rule 2 in SKILL.md so its inline code span no longer straddles a newline; prettier dedents the numbered-list continuation in that case, which breaks the list rendering. Re-running the code blocks afterward turned up a real bug: the ts/h block in api.md aborted with "null (null) cannot be subtracted" on a quiet service, because max/min over an empty Data array both return null. That is the exact HTTP 200 + empty-Data payload documented two paragraphs above it. Guard the empty case and add the missing compute_requests term. Verified live against a real account: hit ratio, 5xx share, bandwidth ranking (reconciles exactly with account-wide usage), usage totals, realtime rps, and ts/h on both a trafficked and a quiet service. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Pushed Formatting. Ran These slipped through CI because One prettier gotcha worth knowing for this file format: it dedents a numbered-list continuation line when an inline code span wraps across the newline, which breaks list rendering. That hit rule 2 in Re-verification found a real bug, not just cosmetics. Re-running every code block after reformatting, the Verified live against a real account: hit ratio, 5xx share, bandwidth ranking (its total reconciles exactly with account-wide |
| Guard the empty case first: on a quiet service `max` and `min` over an empty array both return | ||
| `null` and the subtraction aborts the filter with `null (null) cannot be subtracted`. |
There was a problem hiding this comment.
This is a code comment, not useful here.
|
Re-reviewed at I also ran a sixth eval task, since none of the five existing ones can see the case rule 9 introduces:
All five trials on the PR branch ran the SKILL.md 5xx recipe as their first data call. Four noticed that zero errors was implausible, dumped the row's key list and recovered; the fifth wrote Five things to fix. The first four are one family: rule 9 is right, and the worked examples did not follow it. 1. The 5xx example reports zero errors on a Compute service. The denominator got The true count is 168,981, a 0.0742% share. 2. Classic 3. The account-usage example under-reports by 8x, with no tell. It sums 4. The live-rate example never got the guard its A service with no traffic emits no lines at all — 5. For July on my account, Two worth adding, since they are the same class of trap the skill already documents:
Packaging, two small ones:
Nits: "Five things the CLI cannot do" is followed by a paragraph naming two more, so it is seven. |
|
Let's merge this. Leaving Claude on its own doesn't work. The remaining issues will be fixed separately. |
Summary
Adds a new
fastly-statsskill: 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 thefastlyCLI or by building raw URLs forcurl/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
Also lists the skill in
README.md. No manifest changes needed (skills are discovered by directory).Design notes
api.fastly.com(historical) vsrt.fastly.com(real-time).{status, meta, msg, data}; Inspectordimensions+valueswith cursor pagination; real-timeData[].{recorded, aggregated, datacenter}.--downsample/--metric/--group-by/--limit/--cursor(not--by/--field).fastly-clistats reference rather than replacing it (cross-referenced).--json(usejq -s), decimal-SI vs binary units and raw-bandwidth-vs-billable-usage, UTC defaults, Origin/Domain Inspector as a paid add-on, real-timeTimestampchaining, 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 warningsHow it was tested
Developed and evaluated with the
skill-creatorworkflow: 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