Commit 59b5232
feat(cli): add AgenticCheck construct (#1268)
* feat(cli): add AgenticCheck construct for AI-powered monitoring
Adds the AgenticCheck construct that lets users define agentic checks
in their Checkly project via checkly.config.ts. Agentic checks use a
prompt string (no scripts/bundling) to define what the AI agent should
verify.
- Add AGENTIC to CheckTypes enum
- Create AgenticCheck extending Check (not RuntimeCheck)
- Validate prompt (required, max 10000 chars) and frequency (min 30)
- Add construct export and analytics mapping
- Add 6 tests covering synthesis, defaults, groups, and validation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(cli): force runParallel for agentic checks
Agentic checks always run in parallel for better reporting UX.
The construct omits runParallel from props (users can't override it)
and hardcodes it to true in synthesize().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Revert "feat(cli): force runParallel for agentic checks"
This reverts commit a77f117.
* feat(cli): restrict AgenticCheck props to platform-supported fields
Lock down AgenticCheckProps to only the subset of CheckProps the
Checkly platform currently honors for agentic checks. Omits locations,
privateLocations, runParallel, retryStrategy, shouldFail, doubleCheck,
triggerIncident and groupId at the type level, and restricts frequency
to the discrete set exposed in the webapp builder.
Defensive overrides in the constructor ensure project-level config
defaults for any of these fields are also ignored, so the construct
never claims to support what the platform won't honor.
These restrictions can be relaxed additively (without breaking changes)
once the platform supports the corresponding capabilities for agentic
checks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(cli): add agentRuntime to AgenticCheck for skills and env var access
Adds an `agentRuntime` prop to AgenticCheck that declares the runtime
context the agent has access to during execution: which skills it can
use and which environment variables it is permitted to read.
agentRuntime is the explicit security boundary for the agent. Anything
not declared here is unavailable at runtime, which keeps the blast
radius of any prompt injection as small as possible. Environment
variables accept either bare names or `{ name, description }` objects;
descriptions are passed to the agent so it can decide when to read each
variable, and are validated to stay within the runner's 200-char limit.
The construct always synthesizes a complete agentRuntime payload (with
empty arrays when unset), so the backend has unambiguous source-of-truth
semantics: omitted skills/env vars mean "the agent should not have
them", not "preserve whatever was there before". The backend translates
this clean shape into the existing agenticCheckData storage blob.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(cli): add code generation support for AgenticCheck
Wires AgenticCheck into the \`checkly import\` code generation flow so
users can import an existing agentic check from the backend and get a
construct file that matches the locked-down props type added earlier on
this branch.
Implementation:
- New \`AgenticCheckCodegen\` in \`agentic-check-codegen.ts\` mirroring the
Heartbeat/Browser codegen pattern. Places generated files under
\`resources/agentic-checks/{name}\`, imports \`AgenticCheck\` from
\`checkly/constructs\`, and emits a \`new AgenticCheck(...)\` expression.
- The resource shape (\`AgenticCheckResource\`) carries \`prompt\` and the
backend's \`agenticCheckData\` storage blob. A small helper reverse-
translates that blob into the CLI construct's public shape:
* \`agenticCheckData.skills\` → \`agentRuntime.skills\`
* \`agenticCheckData.selectedEnvironmentVariables\` → \`agentRuntime.environmentVariables\`
— mapping \`key\` back to \`name\` for object-form entries
* \`agenticCheckData.assertionRules\` → deliberately not emitted
(agent-generated, preserved server-side via the backend's merge
logic, the construct intentionally does not expose them)
An imported check with no skills and no selected env vars produces no
\`agentRuntime\` block at all, to avoid noise in the generated code.
- Registers the new codegen in \`CheckCodegen.constructor\` and wires
\`AGENTIC\` into the dispatch switches in \`describe()\` and \`gencode()\`
alongside the existing check types.
\`buildCheckProps\` gains a narrow \`BuildCheckPropsOptions\` parameter —
currently a single \`skipRetryStrategy\` flag — because \`retryStrategy\`
is the only field that \`buildCheckProps\` emits unconditionally (null is
rendered as \`RetryStrategyBuilder.noRetries()\`). The AgenticCheck
construct's props type omits \`retryStrategy\` entirely, so emitting it
would produce a generated file that does not type-check. The
AgenticCheckCodegen passes \`skipRetryStrategy: true\` and clears
\`locations\` from a resource copy before calling \`buildCheckProps\` — the
two fixes together make the generated output round-trip cleanly through
the construct's props type.
Verified end-to-end by extending \`ai-context/context.fixtures.json\` with
an example agentic check (prompt, skills, mixed-form env vars, sample
assertionRules) and running \`npm run prepare:ai-context\`. The generated
\`gen/resources/agentic-checks/example-agentic-check.check.ts\` contains
only fields the construct accepts, reverse-translates env vars from
\`key\` to \`name\`, omits \`assertionRules\`, and type-checks against the
construct. Full CLI suite remains green (829 passing / 2 skipped /
60 files). No regressions in any other check type's codegen from the
new optional options parameter.
Covers item #3 on Simo's new-construct checklist. Items #5 (examples),
#6 (E2E tests), and #8 (AI context reference doc) still pending on this
branch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(cli): add unit tests for AgenticCheckCodegen
Cover the codegen edge cases that the `prepare:ai-context` happy-path
fixture doesn't exercise: missing/null/empty `agenticCheckData`,
skills-only, env vars-only, mixed bare-string and object-form env var
entries, the `key` -> `name` reverse translation, and the explicit
suppression of `locations`, `retryStrategy`, and `assertionRules`
from the generated source.
Also drop a few defensive runtime checks in the codegen that the
typed `StoredAgenticCheckData` interface already guarantees, and
trim a comment block in `gencode()`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(cli): add AgenticCheck examples for AI context and boilerplate
- Add an `AGENTIC_CHECK` entry to `EXAMPLE_CONFIGS` so the
`prepare:ai-context` pipeline can interpolate the generated example
into reference docs.
- Simplify the `example-agentic-check` fixture to a single self-contained
pricing-page check (no skills, no env vars). The unit tests added in
the previous commit cover the more complex agentRuntime cases.
- Add an `agentic.check.ts` (and the JS twin) to the boilerplate
project so first-time CLI users see what an agentic check looks like
alongside the existing API/URL/heartbeat examples.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(cli): add e2e deploy round-trip for AgenticCheck
Adds a `deploy-agentic-project` fixture that exercises both the
plain-prompt form and the `agentRuntime` form, plus a corresponding
`describe('deploy-agentic-project', ...)` block in `deploy.spec.ts`.
The tests cover two scenarios:
1. `--preview` produces an import plan that lists both agentic
checks under the `Create:` heading, exercising the codegen +
deploy planner path without leaving any state behind.
2. `--force` actually creates the checks on the target account and
reads them back via the public REST API to confirm that
`checkType`, the hardcoded `us-east-1` location, and round-tripped
tags all land correctly.
Both tests require the e2e CI account to be entitled to agentic
checks. If the account is not entitled, the tests will fail with a
402 — that's the signal to enable the entitlement, not to weaken
the test.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(cli): add Agentic Check reference for the AI skill
- Add `configure-agentic-checks` to the `REFERENCES` array so the
`npx checkly skills` command and the generated `checkly.rules.md`
expose the new construct alongside the other check types.
- Add `configure-agentic-checks.md` covering the locked-down props,
the restricted frequency set, the `agentRuntime` security boundary,
the prompt-writing guidance, and the assertion-rules round-trip
rules. The example is interpolated from `EXAMPLE_CONFIGS.AGENTIC_CHECK`.
- Mention agentic checks in the `skill.md` frontmatter description so
agents discover the construct from the skill summary alone.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: regen ai context and fix NO_RETRIES
* docs(cli): correct AgenticCheck skill installation guidance
Skills declared on `agentRuntime.skills` are installed on the runner
via `npx skills add <entry>` (https://skills.sh), not via the
`npx checkly skills install` meta-skill installer that ships the
SKILL.md file into a project. The previous JSDoc, reference doc, and
example fixtures conflated the two.
Updates:
- `agentic-check.ts`: rewrite the `AgentRuntime.skills` JSDoc to
describe the real installation path, list the three identifier forms
skills.sh accepts (full URL, owner/repo, plain name), and note that
the runner preloads the `playwright-cli` skill so users only need to
declare extras.
- `configure-agentic-checks.md`: same correction in the AI reference
doc, with the example block expanded to show all three forms.
- Test/example fixtures: switch the placeholder skill from the
non-existent `'checkly/playwright-skill'` to
`'addyosmani/web-quality-skills'` to make it visible that
third-party skills published to skills.sh work — not just Checkly's
own.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ci: temporary debug step to fingerprint the e2e Checkly account
Adds a debug step before `npm run test:e2e` (ubuntu only) that prints
SHA-256 hashes of the secret account ID/name plus a few non-secret
fields from `/next/accounts/<id>` and `/v1/accounts/me/entitlements`.
The hashes let us verify which account the secrets resolve to without
leaking the actual values in this public repo's CI logs. The
entitlement block shows whether `maxAgenticChecks` bumps are landing
on the account the e2e tests actually use, and the existing-AGENTIC
count surfaces stale orphans that may be eating the budget.
Compare locally with:
node -e "console.log(require('crypto').createHash('sha256') \\
.update('<candidate-id-or-name>').digest('hex'))"
To remove once the right account is confirmed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ci: remove temporary e2e account fingerprint debug step
The fingerprint did its job — it surfaced that the secrets pointed
at an account different from the one being bumped, and that the
target account's `maxAgenticChecks` column was unset (the
`add_agentic_check_quota_columns` migration only seeded HOBBY,
STARTER, TEAM and TRIAL plan accounts, leaving CONTRACT plan rows
with NULL).
The right account has been bumped and the e2e tests should pass on
the next run. Reverting the workflow back to its previous shape.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(cli): rename agentRuntime.environmentVariables to exposeEnvironmentVariables
Makes the allowlist semantics explicit — these are the env vars the agent
is permitted to read, not the variables themselves.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 53bbce0 commit 59b5232
39 files changed
Lines changed: 1532 additions & 3 deletions
File tree
- examples
- boilerplate-project-js/__checks__
- boilerplate-project/__checks__
- packages/cli
- e2e/__tests__
- fixtures/deploy-agentic-project
- src
- ai-context
- references
- constructs
- __tests__
- fixtures/agentic-check
- test-cases
- test-agent-runtime
- test-basic
- test-check-defaults
- test-group-mapping
- test-locations-override
- test-validation-description-too-long
- test-validation-empty-env-var-name
- test-validation-frequency-too-low
- test-validation-missing-prompt
- test-validation-prompt-too-long
- rest
- skills/checkly
Lines changed: 15 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
261 | 261 | | |
262 | 262 | | |
263 | 263 | | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
264 | 327 | | |
265 | 328 | | |
266 | 329 | | |
| |||
Lines changed: 28 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
Lines changed: 7 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
824 | 824 | | |
825 | 825 | | |
826 | 826 | | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
827 | 884 | | |
828 | 885 | | |
829 | 886 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
2 | 6 | | |
3 | 7 | | |
4 | 8 | | |
| |||
147 | 151 | | |
148 | 152 | | |
149 | 153 | | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
150 | 159 | | |
151 | 160 | | |
152 | 161 | | |
| |||
Lines changed: 52 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
0 commit comments