Skip to content
Console
Browse documentation
Reference

What integration verification proves and what it does not

The stages between your code and stored evidence, what a verified sample establishes, the exact limits and known gaps of the verification reads, how long to wait, and what has been run.

On this page

After your agent integrates feature flags or product events, three reads ask Anectico whether the exact samples of a controlled test arrived. This page is the one place that says what their answers establish, which limits bound them, how long to wait before trusting a negative answer, and what has and has not been run. The request and answer fields are on the pages for each read.

Read REST MCP action CLI Fields and states
One job, one verdict POST /api/v1/instrumentation/verify verify_integration anectico doctor integration Integration job verification
Exact product events POST /api/v1/instrumentation/events/verify verify_integration_events anectico doctor events Integration event verification
Exact flag exposures POST /api/v1/instrumentation/flags/verify verify_flag_integration anectico doctor flags Feature-flag exposure verification

All three are reads. They send nothing, change nothing, store no report, run no model and open no proof page: links is always empty. Their states (observed_match, mismatch, not_observed, withheld, unavailable, ambiguous) mean the same thing on every surface, and a REST, MCP or CLI call with the same request returns the same answer.

Six stages, and which one a read can establish

A test passes through six stages. Each one is evidence of itself and of nothing after it.

Stage What it is Who reports it Does a verification establish it?
Configuration The flag, keys, project and tracking-plan revision you approved through a preview and a confirmation The confirmation receipt No. A receipt shows a setting exists, never that your application uses it.
Application execution and local outcome Your application ran, served a branch, and its SDK or code reported success or failure Your application's own record No. Anectico does not see your run. Keep the clocks, message IDs and served branch from your application's record.
Queue acceptance Capture answered CAPTURE_DELIVERY_QUEUED for the item The capture acknowledgement No. It does not mean the event is stored, readable, or that an identity update has finished.
Retained evidence A stored event with that name, message ID and admitting source matches your selection The verification read Yes, for the selected samples only.
Identity The distinct_id your application declared resolves to a person The identity check, with persons:read Yes, with persons:read. The declared ID is your application's own assertion; Anectico does not authenticate your end users.
Verification Every required check of every selected sample is observed_match The verdict It is the sum of the checks above and no more.

What a verified sample proves

verified_sample means: for the up to 20 samples you selected, inside the window and before the read_cutoff the answer states, every required check was observed_match. For product events that is the event name, message ID and admitting source, the declared identity, the session if you asked, the person the declared identity resolves to, and, with a pinned tracking-plan revision, that the revision declares the event and the property types match. For flags it is the value, definition version, evaluation status, fallback flag, evaluation mode and input context that your application recorded.

It does not prove:

  • that any other event, flag, person or code path is instrumented;
  • that everything your application sent arrived. upstream_completeness is always unknown: SDK configuration, sampling, consent, client-side loss and an accepted intake request are not observed;
  • that errors, traces, logs or replay work. They are neither required nor checked;
  • that a person saw a treatment. A flag exposure is application-reported use;
  • that your application authenticated its inputs. An input_binding is a declaration by the sender, never recomputed or authenticated, and a remote decision that used stored person, group, cohort or audience context is context_not_established;
  • that the people in the test are real people;
  • that the project's measurements are healthy. Verification checks your selected samples and nothing else, so another person's correct events neither help nor hide a wrong one.

Bounds on every request

Bound Value
Event-time window At most 1 hour, [start, end), millisecond precision
Samples or exposures 1 to 20, answered in the order sent
Property checks per sample At most 20
Whole job call Stops after 20 seconds
Concurrent verifications per project 2; a third is refused with HTTP 429

The product-event read behind both jobs also stops at these limits, returned in every answer under limits:

Read limit Value
Rows scanned 10,000,000
Bytes scanned 1 GiB
Memory 512 MiB
Candidate events returned 200
Returned bytes 4 MiB
Execution time 8 seconds

A reached limit makes every sample unavailable with a reason that begins limit_, and limits.limit_reached is true. It never produces not_observed. Normal rate limits and agent budgets apply to these reads; there is no separate fee.

Two known gaps in the event read

Both are open and both are stated in every answer's limitations.

The read is not narrowed by date. It reads every retained event of the selected event names in the project, not only those of the window's day, and keeps the ones inside the window. The cost therefore grows with the project's history of those names, not with your test. On a local deployment holding 100,000 retained events of the 20 selected names across 30 days, one 20-sample verification read about 100,000 rows, 27 MB, in about 50 ms. At that row width the 1 GiB byte limit binds near 3.9 million retained events of the selected names, before the row limit. A busy project can therefore answer unavailable for an event that exists. Select fewer distinct event names per request, and treat unavailable with a limit_ reason as unknown, never as absent.

The stored event has no source in its key. Two sources in one project that send the same event name, timestamp, distinct ID and message ID keep one stored event. Verifying one source can then report not_observed because the other source's copy was kept. Ordinary traffic rarely collides, because SDK message IDs are random, but a replayed fixture, a copied payload, or two servers forwarding one upstream event can. Use a message ID that is unique to the source in every test, and never reuse a fixture across sources. Nothing in the answer tells you a collision happened.

How long to wait, and when to stop

Queue acceptance is not readability. In the local runs described below, stored events became readable about 20 to 35 seconds after the application sent them; the slowest run needed its fourth read, about 65 seconds after the exercise. How long a hosted deployment takes has not been measured, so do not hard-code a delay.

  • The first one or two reads after a test can answer failed because every check is not_observed. That is delay, not a defect. A mismatch is different: the event was read and it differs from what you asked for. Read the checks, not only the verdict.
  • Read again with the same request. The runnable examples read at most four times, after waiting 5, 10, 20 and 30 seconds in turn, and re-read only while a required check is not_observed or unavailable. Then they report what is unresolved. Your agent decides the schedule; Anectico does not poll for you.
  • Do not resend an acknowledged event to make it appear, do not widen the window or change the selectors to get a better verdict, and do not create another resource after an ambiguous answer.
  • A call that fails with 409, 429 or 503 released no answer. Retry the same request shortly.
  • If a scope, the project's content policy or the selected events change while a read runs, no answer is released. Start a fresh read.

Scopes decide how much of the answer you see

Scope Needed for Without it
mcp:read Calling a read over MCP The MCP call is refused.
query:read The one-verdict job read The job read is refused (403) before anything is read.
analytics:read Every product-event and flag-exposure read The read is refused (403).
flags:read The flags job and the exposure read The read is refused (403).
persons:read The identity check The check is withheld; a stored identity that differs from the declared one is reported only as a mismatch.
tracking_plans:read The plan and its declarations They are withheld.
agents:content:read Property checks and recorded flag fields Every such check is withheld.

A withheld check never lets a sample verify. It is not a sign that the application is wrong or the event is absent: ask for the scope, or report that part as not checked.

Time, history and population

  • Windows are event time as your application stamped it. read_cutoff is the receipt time after which nothing was read; it is not a snapshot or a delivery watermark. effective_start_time and effective_end_time are the part of the window the read covered after the project's readable history, and are empty when nothing was read.
  • population.basis is always explicitly_selected_application_samples: only the samples you selected were checked.
  • Anectico does not yet reserve a population for verification traffic. Test events are ordinary events in the project: they count in its measurements and in its event allocation, and they are retained, exported and erased like any other event. Use clearly synthetic identities such as anectico-verification-user-a, tell the person who owns the project, and never erase a person merely to tidy up.
  • Identify and group-identify calls store no event row, so no read can select them. Their outcome is the acknowledgement. Verify the events that follow them.

Jobs not covered yet

errors, traces_logs, replay, surveys and experiments are refused by name. For an error or trace story use the setup check in verify your setup.

What has been run

On 15 October 2026 the runnable examples were driven against a local test deployment on one macOS machine, each by a script that exercised the application like a visitor's browser and then asked Anectico to verify the samples:

Example Runtime Result
Node checkout, remote flag decisions Node 22.22.0, SDK built from the repository; and from a packed tarball Product events and flags verified_sample; the people behind the events resolved as expected
Node checkout, remote flag decisions Node 24.21.0, packed tarball The same
Node checkout, local flag evaluation Node 22.22.0, SDK built from the repository The same
Ruby checkout over HTTP, no SDK Ruby 2.6.10, standard library The same, with session checks

Against the verified Ruby run's own requests, a wrong selection failed as it should: another source, identity, session, expected value or definition version each produced failed, and another project was refused.

On 16 October 2026 an independent coding agent was asked, on the same local test deployment, to integrate product events or a server-side flag into the uninstrumented Node 24 and Ruby 2.6 checkouts from scratch, four times in all. In every run, its changed application, exercised again by the test harness as two visitors the agent had never seen, produced exactly the events and exposures that the verification reads then confirmed: the events, the anonymous-to-identified joins, a numeric property, the served branch and the versioned exposures, and on Node an established, agreeing local-versus-remote comparison. None of the four counts as a qualification: each final report left out a fact the check requires (an event name, the test people, the message IDs or the flag key). The agents' own check of $groups as an event property came back missing, so account attribution was not confirmed through event verification.

Not run: a passed qualification of the workflow by an independent agent; a hosted or shared deployment; Ruby 3; Linux or Windows hosts; a browser; and any other language. Nothing on this page is a promise for those. See Ask your agent to integrate Anectico for what is covered and Runnable integration examples for the code that was run.