# Verify agent tracking

> Check public site conformance and safely verify synthetic tracking receipts through the Developer API or OAuth MCP.


Developers and coding agents can check a site without database access. Use two separate checks: public conformance for what the site serves, and authenticated receipt verification for what Kismet stored.

## Release status

The receipt API, SDK method and OAuth tool below are **preview source contracts**. They require the matching backend and OAuth relay deployments and a compatible SDK release exporting `client.telemetry.verifyAgentTracking`. The published `0.2.0-beta.1-poppy02.20261018.2` does not contain that method. Check deployment and `tools/list` before use; installation does not activate access or grant permissions.

## Check public pages

```sh
npx kismet check https://your-staging-site.example --env staging --json
```

Use the actual served environment. For a static production export, use `npx kismet check ./out --env production --json`. Do not pass a `.next` directory. `kismet verify` additionally runs the configured recipe checks. Blocking findings fail the command; warnings remain visible but do not make its exit code nonzero. These checks do not inspect persisted receipts or authenticate a personal agent.

## Send synthetic probes

Use only public discovery or document URLs, never guest data, login links, tokens or cookies. Generate a fresh UUID `probeId` for each run and add `kismet_probe=<probeId>` to every URL. Give each distinct request a unique URL, including separate GET and HEAD probes. Record the exact URL and full original User-Agent; use `null` only when no User-Agent header was sent.

Test installed `llms.txt`, `llms-full.txt` when present, public Markdown, and Poppy/MCP discovery. Include known, unknown and missing UAs. To test a warm cache, deliberately repeat one exact URL and UA, then set its `expectedReceipts` to the number of requests sent. HTTP method, status, empty HEAD bodies, cache HITs, and absence of Set-Cookie must be checked at the HTTP client: receipt storage does not prove them.

Wait for asynchronous ingestion before verifying. Set `since` just before probing and `until` just after it. The window is half-open (`since <= timestamp < until`), at most 30 minutes, and within the last day. There are at most 32 distinct URL/UA pairs, each expecting zero to five receipts. A zero expectation is useful for a deliberately unconfigured ownership-proof route. It proves only no matching receipt in this collection/environment/window, not global absence of sessions or traffic.

## Verify through manager OAuth MCP

Connect the Kismet Developer MCP and sign in with an ADMIN or DEVELOPER account for the collection. Call `verify_agent_tracking` with `installation_id` and `input` matching the SDK example below. Infrastructure rechecks current collection authority, application/installation state and a collection-wide `telemetry.read` grant. No server key needs to be issued or pasted into chat.

URLs must use exact HTTPS origins already registered on that installation. TEST installations can inspect only non-production environments; LIVE can inspect only production. Domain verification or a manifest does not grant telemetry access. Anonymous, guest and machine-key MCP callers cannot use this manager tool; server integrations use REST/SDK instead. Missing grants must follow the separately approved access setup, not automatic escalation.

## Verify through a server SDK

```ts
import { createKismetClient, KISMET_LIVE_API_BASE_URL } from '@kismet-tech/sdk/server';

const client = createKismetClient({ baseUrl: KISMET_LIVE_API_BASE_URL }); // KISMET_SECRET_KEY in the server secret store
const result = await client.telemetry.verifyAgentTracking({
  probeId: '11111111-1111-4111-8111-111111111111',
  environment: 'staging',
  since: '2026-10-19T11:50:00Z', // replace with this run's timestamps
  until: '2026-10-19T12:00:00Z',
  probes: [{
    id: 'llms-unknown-warm',
    pageUrl: 'https://your-staging-site.example/llms.txt?kismet_probe=11111111-1111-4111-8111-111111111111&request=1',
    userAgent: 'YourSyntheticAgent/1.0',
    expectedReceipts: 2,
  }],
});
if (!result.ok) throw new Error(JSON.stringify(result));
```

Use the server entry point and a restricted server credential with collection-wide `telemetry.read`. The key carries its collection; a `collection` override is only a locator, never authority. Browser and publishable clients do not expose this method.

REST uses `POST /v1/developer/collections/{collection}/telemetry/agent-verification` with the same JSON input and Bearer server credential. It is read-only; POST keeps full probe URLs and UAs out of query strings. Responses and SDK requests use `no-store`. Do not log request bodies in your own proxy.

## Interpret results

The response returns each supplied probe ID, expected/matched counts, server/fetch/view counts, human-session contamination counts and diagnostic codes. It never returns raw URLs, UAs, events, IPs, guest identifiers or session values.

| Diagnostic | Action |
| --- | --- |
| `MISSING_RECEIPT` | Allow ingestion to settle, then retry the same bounded window. Check middleware runs before static/CDN returns. |
| `DUPLICATE_RECEIPT` | Check for overlapping middleware, route and edge capture. |
| `UNEXPECTED_RECEIPT` | An expected-zero control was captured; inspect its route boundary. |
| `NOT_SERVER_FETCH` | A receipt was not a server-side `fetch`. Check the adapter integration. |
| `HUMAN_SESSION_PRESENT` | Synthetic document traffic acquired a human-session reference. Do not claim clean acceptance. |
| `INCOMPLETE_EVIDENCE` | The 256-row safety bound was exceeded. Narrow the probe set/window; truncated evidence never passes. |

`ok` requires complete evidence and every probe passing. A missing receipt is not success merely because the request returned HTTP 200. `400` means invalid input/window; `401` inactive or missing credential; `403` missing grant, wrong environment or origin; `404` unavailable collection; `429` quota; `503` unavailable authority or storage. Fail closed and retry transient failures with bounded backoff.

This check does not prove consent, returning-visitor recovery, booking attribution, provider delivery, global cross-collection absence, or Poppy session acceptance. [Poppy discovery](https://developers.kismet.travel/sdk/poppy-discovery.md) and authenticated agent issuance/renewal remain separate acceptance steps.
