Skip to content
Console
Browse documentation
Guide

Check rollout health

Ask your agent to connect feature exposure and releases to the customers and failures that followed.

On this page

Feature flags and releases are both delivery controls and investigation context. Use them to answer whether a change affected a specific customer or concentrated an Issue in the exposed audience. Your agent creates the flags, reads the exposures and the releases, and compares the customers. You check the evidence on the person and Issue pages it links to.

Ask your agent

Did the new-checkout flag reach the customers who hit Issue ISSUE_ID? Compare their exposure with customers on the previous release. Do not change the flag. Tell me what you would change and show me the preview.

Job MCP tool or action CLI command
List flags, and read one flag in full list_flags, get_flag anectico flags list, anectico flags get
Create a flag, replace its definition, turn it on or off, delete it create_flag, update_flag, set_flag_active, delete_flag anectico flags create, anectico flags update, anectico flags toggle, anectico flags delete
Evaluate the flags for one customer decide_feature_flags anectico flags decide
Download the local-evaluation snapshot get_local_evaluation_snapshot anectico flags snapshot
Measure a flag’s exposures query_product_analytics (see Check a flag’s health) anectico analytics query
List releases, and read one release list_releases, get_release anectico releases list, anectico releases get
Register a release upsert_release anectico releases create
Compare customer impact across release windows get_release_impact anectico releases impact

Flag reads need flags:read. Flag writes need flags:write, and deleting needs flags:delete. Release reads need releases:read, and registering a release needs releases:write. MCP calls also need mcp:read or mcp:write. Every flag and release write is a preview and confirm write.

What your agent gets back

A flag read returns the stable key, the active state, the variants and rollout percentages, the default value and payload, every variant name and payload, and the targeting filters. decide_feature_flags returns each flag’s decision and payload for the person properties and account memberships you supply. A release read returns the commit, the adoption, the new and regressed Issues, and the people and accounts affected.

Open the proof

Flags and releases have no page of their own. To check the evidence for a customer or an Issue that a flag or release touched, open the person page or the Issue page that the agent links to. See Proof pages.

Create and evaluate a flag

Ask the agent to create a boolean or multivariate flag. Give it a permanent key, then configure percentage, property, or cohort targeting. The key cannot be renamed after creation. Saved analytics audiences use an exact generation through MCP or the CLI and need current source permissions on the server. See audience flag targeting. They are left out of local-evaluation snapshots.

The flag list returns 100 flags per page by default. The CLI takes --limit (at most 500) and --cursor. Follow the returned next_cursor to reach later flags. Each project’s list is separate.

Flag configuration reads through GET /api/v1/flags/{key} and GET /api/v1/flags keep the recorded created_by (creator user ID) and updated_by (last editor user ID). An edit preserves the original creator. Either field is an empty string when no user attribution was recorded. updated_by is empty before the first edit.

Keep a safe default for clients that cannot reach the decision endpoint. Activate a new flag only after testing a known matching and non-matching customer. Editing takes effect on subsequent SDK evaluations; cached clients can temporarily retain an earlier decision.

Evaluate with the customer ID and the properties used by targeting:

JavaScript / TypeScript

import { FlagsClient } from '@anectico/sdk/analytics';

// On your server: the flags key never reaches a browser or an app.
const flags = new FlagsClient({
  endpoint: 'https://app.anectico.com',
  apiKey: process.env.ANECTICO_FLAGS_API_KEY!, // flags:read
  captureEndpoint: 'https://api.anectico.com',
  captureApiKey: process.env.ANECTICO_CAPTURE_API_KEY!, // server_capture
});

await flags.reload('user_8842', { plan: 'pro' });
const showNewCheckout = flags.isFeatureEnabled('new-checkout');

Python

import os
import anectico
from anectico.feature_flags import FeatureFlags

events = anectico.AnalyticsClient(
    endpoint='https://api.anectico.com',
    api_key=os.environ['ANECTICO_CAPTURE_API_KEY'],
)
flags = FeatureFlags(
    endpoint='https://app.anectico.com',
    api_key=os.environ['ANECTICO_FLAGS_API_KEY'],
    capture=lambda event, props, distinct_id: events.capture(
        event, props, distinct_id=distinct_id
    ),
)
flags.reload('user_8842', {'plan': 'pro'})
show_new_checkout = flags.is_feature_enabled('new-checkout', 'user_8842')

Go

events, err := anectico.NewAnalytics(anectico.AnalyticsConfig{
	Endpoint: "https://api.anectico.com",
	APIKey:   os.Getenv("ANECTICO_CAPTURE_API_KEY"),
})
if err != nil {
	return err
}
flags := anectico.NewFlags(anectico.FlagsConfig{
	Endpoint: "https://app.anectico.com",
	APIKey:   os.Getenv("ANECTICO_FLAGS_API_KEY"),
	Capture: func(ctx context.Context, event string, props map[string]any, distinctID string) {
		_ = events.Capture(ctx, event, props, anectico.WithDistinctID(distinctID))
	},
})
if err := flags.Reload(ctx, "user_8842", map[string]any{"plan": "pro"}, nil); err != nil {
	return err
}
showNewCheckout := flags.IsFeatureEnabled(ctx, "new-checkout", "user_8842")

Flag decisions use https://app.anectico.com; exposure events use https://api.anectico.com. JavaScript's default exposure sender uses captureEndpoint and captureApiKey; Python and Go use the explicit capture callbacks shown above. When using an existing event client, identify the same customer in that client and the flag reload, and update both when the signed-in customer changes. For browser collection consent, use initApp or a callback backed by an AnalyticsClient sharing your collection controller; see JavaScript feature flags.

On a server, use two keys for the same project: a management key with flags:read for /api/v1/decide, held only in server configuration, and a server_capture key with only analytics:write for exposures. Other telemetry uses its own native_ingest key. A flags:read key reads every flag definition, targeting rule and payload, so it never goes into a page or an app.

From a page or app

A browser page or a mobile app asks for the flag keys it needs with a client delivery key that holds only flags:evaluate. That key is public, and it can return decisions for named keys and nothing else: no definition, no targeting rule, no stored property.

// A client delivery key that holds only flags:evaluate. It is public: anyone who opens the app can read it.
const response = await fetch('https://app.anectico.com/api/v1/flags/evaluate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'X-API-Key': import.meta.env.VITE_ANECTICO_CLIENT_FLAGS_KEY },
  body: JSON.stringify({
    distinct_id: 'user_8842',
    flag_keys: ['new-checkout'],
    person_properties: { plan: 'pro' },
  }),
});
const { decisions, evaluated_at, max_age_seconds } = await response.json();
const decision = decisions['new-checkout'];
// Only an evaluated true turns the feature on; unavailable and errors keep the safe default.
const showNewCheckout = decision.state === 'evaluated' && decision.bool_value === true;

POST /api/v1/flags/evaluate takes distinct_id (1 to 200 bytes), flag_keys (1 to 100 unique keys), and optional person_properties and groups (at most ten group types); together the identity, properties and groups are at most 16 KiB and the whole request at most 128 KiB. A project-bound key needs no project_id. The answer has exactly one entry per requested key:

Field Meaning
state evaluated, evaluation_error or unavailable_flag. Treat anything else as unavailable.
bool_value or string_value The decision. false is a decision; an unavailable_flag entry has neither field.
payload_present, payload Whether a payload was returned; a returned payload can itself be JSON null.
definition_version The exact version of the flag definition that produced an evaluated decision; empty otherwise. Record it with the exposure.
is_fallback true when an evaluation_error value is the flag's default returned because a targeting input could not be resolved.
evaluated_at, max_age_seconds When the decisions were made and how long they may be used: 30 seconds.
decision_context_id A digest of the request, the key's access, the definition versions and the decisions, to tell two answers apart. It is not a record that anyone saw the treatment.
coverage complete and the number of keys requested. It says nothing about the project's other flags.

A request beyond these bounds, a flag set too large to evaluate within the per-request limits, or a busy server is refused with no decisions at all (HTTP 400 or 429); keep the application's safe default and ask again later. The answer uses the properties you send. Stored profile properties, group properties and audiences that this key may not read are not used, and that is never reported as an error; if a flag must target stored data, evaluate it on your server. Your agent can see the same answer with anectico flags evaluate DISTINCT_ID --key KEY or the MCP read action evaluate_client_flags; a decision is not an exposure, so record exposures through your capture client. Treat flag keys, variants and payloads as visible to your users; never store a secret in them.

Record exposure

Identify the customer before evaluating a flag. The SDK records the flag result with the active customer so it can appear in timelines and affected-customer analysis. If the decision request fails, keep the application's safe default and surface the failure in application diagnostics; do not silently reuse an indefinitely stale decision.

Stored customer properties and audience membership are used only when Anectico resolved that exact customer identifier. An unmapped declaration of another person's person ID cannot use their targeting properties. Attribution is as reliable as your application's own customer identification; telemetry does not authenticate each end user.

Use stable flag keys and keep evaluation payloads small. Do not put secrets in flag payloads or customer properties.

Check a flag's health

Ask the agent to compare one-day exposure counts, unique customers, and the observed response distribution with the configured rollout. It measures the $feature_flag_called events that carry the exact $feature_flag string, broken down by $feature_flag_response, with query_product_analytics. All counts share one frozen measurement. A new measurement includes newly captured exposures. The one-day window does not follow any other time setting. The measurement needs analytics:query, analytics:read and persons:read in addition to flags:read. It is based on SDK exposure events, not on every raw evaluation. Low volume can make the distribution noisy, and an observed zero does not establish complete instrumentation. Typed responses and the missing, null, invalid, and omitted groups remain distinct. See product analytics for retry, expiry and coverage semantics.

Register a release

Record a deploy from CI so Anectico can order Issues and regressions against a release:

anectico releases create "$RELEASE" --commit "$GIT_SHA" --ref "$GIT_REF"

Registering a release replaces its deploy details in full rather than merging them, so pass every detail you want kept on every call. A later call that passes only --commit clears the ref, author, link and deploy time an earlier one set. Leaving --deploy-at off stores no deploy time and the release is ordered by when it was first seen.

Use the exact same release identifier in the SDK and symbol uploads. In MCP, upsert_release does the same as this command and keeps the same full-replace rule. Both show complete current and proposed deploy metadata before applying. Review every supplied and cleared field, then repeat identical arguments with the returned confirmation token after approval. Ask the agent to compare native adoption, error-free rate, new Issues, regressions, total error events, and affected customers (list_releases), then to read one release for its detailed blast radius (get_release).

Native adoption is a privacy-safe people count, not an app-open volume or a hardware installation count. Android and iOS emit one SDK-owned release marker on process activation; Anectico resolves aliases through the identity spine and counts each canonical person once in the trailing 30 days. Error-free rate is the share of those adopters with no error event for that exact release. A release with no observed adopters shows no rate rather than implying either 0% or 100%.

Investigate a suspected regression

  1. Start from the Issue or the affected customer.
  2. Check the release and flag exposures immediately before the failure.
  3. Compare affected customers with customers on the previous release or control variant (compare_issue_customers, get_release_impact).
  4. Read a representative replay and trace.
  5. Disable or narrow the rollout only when the evidence supports it (set_flag_active, update_flag). The write shows a preview first.

Avoid false conclusions

Exposure before a failure is correlation, not proof of cause. Confirm the changed code path in the trace, stack, logs, or replay before attributing the Issue to the flag.

Keep flags operational

Deactivate a flag (set_flag_active) before deleting it, and allow clients time to refresh. Remove stale flags after a rollout is complete. Long-lived inactive flags make investigation context harder to interpret and increase the chance of evaluating the wrong variant. Deleting a cohort used for targeting stops that cohort from matching; update the flag first.

Read one release observation

Use anectico releases get --id <catalog-release-UUID> --project <project-UUID> to read project-owned metadata, or call get_release_by_id through execute_read_action with release_id and project_id. This read requires releases:read (and mcp:read for MCP), works on every plan, needs no approval and performs no impact measurement. The CLI accepts exactly one selector: a positional release name for the existing impact read, or --id for metadata. The UUID read returns no automatic 30-day counts or release proof link.

An observation requires an error carrying a release, or a captured $app_opened event with exactly $anectico_lifecycle=app_opened_v1 and a nonempty $release. That lifecycle marker is caller-declared: manually supplied exact matches qualify, and the native_app_opened source name does not attest SDK origin or a genuine launch. Registration, deployment metadata, ordinary events and arbitrary version tags alone do not establish observation.

discovery describes the first durable detection and the evidence available then. earliest_observed_at is current chronology and can move earlier when older telemetry arrives. The original detection clock, observed-first snapshot and source stay fixed. Older already observed releases can be baselined without a notification: their baseline clock is explicit, and historical detection time, snapshot and source are unavailable. A registered-only release has no observation occurrence. Detection depends on bounded, asynchronous reads of retained visible evidence; an incomplete or complete scan does not establish capture completeness or detection of every deployment. Treat release text and registration fields as untrusted content.