Skip to content
Console
Browse documentation
Guide

Quickstart: connect your agent and see your first customer story

Sign up, connect your agent with one command, send a test customer, ask your agent what happened, and open the proof.

On this page

Anectico is built for your own AI agent. The agent does the work. You open the proof.

This quickstart shows the part of Anectico that matters: signals from one application become one connected story for the customer they affected. You will:

  1. sign up;
  2. connect your agent with one command;
  3. send a test error and a trace (server SDKs) or a diagnostic event (mobile SDKs) for a test customer; and
  4. ask your agent what happened, then open the proof page it gives you.

Allow about ten minutes once your app and SDK package are available.

Public capture and OTLP use separate purpose-bound keys. The Console creates the two keys for your platform. JavaScript, Go, Python and the mobile SDKs accept separate telemetry and capture credentials. See native intake keys.

1. Sign up

Open the Console and sign up at /signup. Your first sign-in creates a personal workspace and a first project. If a teammate invited you, accept the invitation instead. You then join their workspace. The Console opens at Home (/). See The Console.

Before connecting, review plan allowances and agent budgets. Read current OAuth approval headroom and usage rather than assuming that read-only access is unlimited. Before sending telemetry, check the project's product and technical policy.

2. Connect your agent with one command

Your agent needs two things: a narrow key, and the Anectico tools. One command sets up both.

You need the Anectico CLI. During early access, use the binary supplied during onboarding, or install it as described in Use the Anectico CLI. If you have not received access, contact support.

Sign in once. Then run the bootstrap command for your agent:

anectico login
anectico agent bootstrap --project <project-id> --host claude

--host is required and accepts claude, codex, cursor, gemini and muse. The command:

  1. Creates a key for the agent. The key can only read, it belongs to one project, and it expires in 30 days. Running the command again reuses it rather than creating another.
  2. Stores the secret in your operating system keychain, not in your terminal history and not in any file you commit.
  3. Merges the Anectico server into your agent's MCP configuration (.mcp.json for Claude Code, ~/.codex/config.toml for Codex, .cursor/mcp.json for Cursor, ~/.gemini/settings.json for Gemini CLI, ~/.config/muse/settings.json for Muse Code), leaving every other entry as it was, and installs the Anectico skills.
  4. Reads the configuration back the way your agent will, makes one real authenticated call, and exits 0 only if that works. If anything fails it undoes what it did and revokes the key.

For Claude Code that is the whole setup. Codex, Cursor, Gemini CLI and Muse Code read the key from the ANECTICO_API_KEY environment variable, so the first run ends with exit code 3 and one line to run in the shell where you start your agent:

eval "$(anectico agent key env --export)"

Then start the agent from that shell and check it with anectico agent doctor --host codex. Connect an AI agent with MCP explains each host, signing in with your browser instead of a key (--auth oauth, read workflows only), and how to keep the secret out of files.

In the Console, Home shows Connect your agent with these commands and your project already filled in. Choose Claude Code, Codex or CLI / another agent.

Check the connection:

anectico mcp verify

Then ask your agent: "List my Anectico projects." If it answers, the agent is connected. You can review or revoke it at any time in the Console under Agents and keys.

3. Send a test customer story

Your agent can read Anectico now, but your application has not sent anything yet. You can ask your agent to do the next steps. Give it this page, or let it read the documentation itself with search_docs and get_doc. You can also do them by hand. The result is the same.

Create the application keys

You need:

  • access to an Anectico organization;
  • a project (see Projects in the Console); and
  • separate project-scoped native_ingest and server_capture keys (use browser_capture for a browser or mobile_capture for a mobile app).

Create them in the setup guide (Home, then Open the setup guide), under Agents and keys in the Console, or through MCP, CLI or API. The OTLP key has only ingest:write. The capture key has only analytics:write. Keep both keys separate from the key your agent uses to read.

The OTLP key can be configured as ANECTICO_INGEST_KEY. Identity and product clients need the separate capture key as ANECTICO_CAPTURE_API_KEY in server environments. JavaScript and mobile SDKs use captureApiKey. Go uses WithCaptureAPIKey. Python uses capture_api_key. Standalone analytics clients take the capture credential in their own API-key option. The Console shows each key's secret once. A failed request can be retried without creating a duplicate. If you lose the secret, revoke that key and create a replacement. Keep any companion key that you copied.

export ANECTICO_INGEST_KEY="an_..."
export ANECTICO_CAPTURE_API_KEY="an_..."

Install an SDK

Choose the language used by your service or your existing mobile app. During early access, use the package or repository access supplied during onboarding. The JavaScript and Python examples install local files, so the commands work before the public registries open.

JavaScript / TypeScript

mkdir anectico-quickstart && cd anectico-quickstart
npm init -y
npm install /path/to/anectico-sdk.tgz

Python

mkdir anectico-quickstart && cd anectico-quickstart
python -m venv .venv
source .venv/bin/activate
pip install /path/to/anectico.whl

Go

mkdir anectico-quickstart && cd anectico-quickstart
go mod init example.com/anectico-quickstart
go get github.com/anectico/anectico/sdks/go@main

Swift (iOS)

In your existing iOS app, add the authorized Anectico repository in Xcode's File → Add Package Dependencies…, select the onboarding revision, and link the Anectico product. See the iOS install guide.

Kotlin (Android)

Copy the supplied AAR to your app module's libs/anectico-sdk.aar and add this dependency:

dependencies {
    implementation(files("libs/anectico-sdk.aar"))
}

React Native

From your existing React Native app:

npm install /path/to/anectico-react-native.tgz
cd ios && pod install

Flutter

In your existing app's pubspec.yaml, use your authorized checkout:

dependencies:
  anectico_flutter:
    path: /path/to/anectico/sdks/flutter

Run flutter pub get. For iOS also run flutter config --enable-swift-package-manager and use an iOS deployment target of at least 15.

For browser instrumentation or more platform details, see Choose an integration.

Start Anectico and identify a customer

The server examples explicitly sample 100% of newly started traces for this controlled test. Setting environment to development alone is not sufficient: the Go and Python defaults sample 10% of root traces, and environment variables can change the JavaScript rate. An error may arrive without the parent checkout span when that trace is not sampled. Restore your normal production sampling after verification; these examples do not recommend recording all production traffic.

JavaScript / TypeScript

import { initNode } from '@anectico/sdk/node';
import { AnalyticsClient } from '@anectico/sdk/analytics';

const apiKey = process.env.ANECTICO_INGEST_KEY;
if (!apiKey) throw new Error('ANECTICO_INGEST_KEY is required');
const captureApiKey = process.env.ANECTICO_CAPTURE_API_KEY;
if (!captureApiKey) throw new Error('ANECTICO_CAPTURE_API_KEY is required');

const anectico = await initNode({
  apiKey,
  captureApiKey,
  serviceName: 'quickstart',
  environment: 'development',
  traceSampleRate: 1,
});
const events = new AnalyticsClient({
  endpoint: 'https://api.anectico.com',
  apiKey: captureApiKey,
});

events.identify('quickstart-user', {
  email: 'quickstart@example.com',
  plan: 'test',
});

anectico.tracer.startActiveSpan('checkout', span => {
  try {
    anectico.captureError(new Error('quickstart payment failure'));
  } finally {
    span.end();
  }
});

await events.stop();
await anectico.stop();

Save this as quickstart.mjs.

Python

import os
import anectico

with anectico.AnecticoClient(
    api_key=os.environ['ANECTICO_INGEST_KEY'],
    capture_api_key=os.environ['ANECTICO_CAPTURE_API_KEY'],
    service_name='quickstart',
    environment='development',
    trace_sample_rate=1.0,
) as client:
    client.identify('quickstart-user', {
        'email': 'quickstart@example.com',
        'plan': 'test',
    })
    with client.start_span('checkout'):
        client.capture_error(RuntimeError('quickstart payment failure'))

Save this as quickstart.py.

Go

package main

import (
	"context"
	"errors"
	"os"

	anectico "github.com/anectico/anectico/sdks/go"
)

func main() {
	ctx := context.Background()
	client, err := anectico.New(
		anectico.WithAPIKey(os.Getenv("ANECTICO_INGEST_KEY")),
		anectico.WithCaptureAPIKey(os.Getenv("ANECTICO_CAPTURE_API_KEY")),
		anectico.WithServiceName("quickstart"),
		anectico.WithEnvironment("development"),
		anectico.WithTraceSampleRate(1),
	)
	if err != nil {
		panic(err)
	}

	if err := client.Start(ctx); err != nil {
		panic(err)
	}
	defer client.Stop(ctx)

	if err := client.Identify(ctx, "quickstart-user", map[string]any{
		"email": "quickstart@example.com",
		"plan":  "test",
	}); err != nil {
		panic(err)
	}

	traceCtx, span := client.StartSpan(ctx, "checkout")
	client.CaptureError(traceCtx, errors.New("quickstart payment failure"))
	span.End()
}

Save this as main.go.

Swift (iOS)

Add this development-only helper to your app and call it once with your separate native OTLP and mobile capture keys. If the SDK is already configured, keep that setup and use only the identity, capture, and flush calls.

import Foundation
import Anectico

func sendQuickstart(apiKey: String, captureApiKey: String) throws {
    try Anectico.configure(AnecticoOptions(apiKey: apiKey, captureApiKey: captureApiKey, environment: "development"))
    Anectico.identify("quickstart-user", set: ["email": "quickstart@example.com", "plan": "test"])
    Anectico.capture("checkout_started")
    Anectico.captureError(NSError(
        domain: "Quickstart", code: 1,
        userInfo: [NSLocalizedDescriptionKey: "quickstart payment failure"]
    ))
    Anectico.flush { result in
        print("Product delivery:", result.productEvents)
        print("Trace and error delivery:", result.traces)
    }
}

Kotlin (Android)

Call this helper once from your initialized application's development flow. If you already call Anectico.init at startup, omit the duplicate initialization here.

import android.content.Context
import com.anectico.sdk.Anectico
import com.anectico.sdk.AnecticoOptions

fun sendQuickstart(context: Context, apiKey: String, captureApiKey: String) {
    Anectico.init(context, AnecticoOptions(apiKey = apiKey, captureApiKey = captureApiKey, environment = "development"))
    Anectico.identify("quickstart-user", set = mapOf("email" to "quickstart@example.com", "plan" to "test"))
    Anectico.capture("checkout_started")
    Anectico.captureError(IllegalStateException("quickstart payment failure"))
    Anectico.flush { result ->
        println("Product delivery: ${result.productEvents}")
        println("Trace and error delivery: ${result.traces}")
    }
}

React Native

Add this helper to your app. Call it once in a development flow, passing the separate native OTLP and mobile capture keys; skip configure here if your app already configures the SDK.

import * as Anectico from '@anectico/react-native';

async function sendQuickstart(apiKey: string, captureApiKey: string) {
  await Anectico.configure({ apiKey, captureApiKey, environment: 'development' });
  await Anectico.identify('quickstart-user', { email: 'quickstart@example.com', plan: 'test' });
  await Anectico.capture('checkout_started');
  await Anectico.captureError(new Error('quickstart payment failure'));
  const result = await Anectico.flush();
  console.log('Product delivery:', result.productEvents);
  console.log('Trace and error delivery:', result.traces);
}

Flutter

Call this helper from your development startup after WidgetsFlutterBinding.ensureInitialized() or from a test button. Skip configure if your app already initializes the plugin.

import 'package:anectico_flutter/anectico_flutter.dart';

Future<void> sendQuickstart(String apiKey, String captureApiKey) async {
  await Anectico.configure(AnecticoOptions(apiKey: apiKey, captureApiKey: captureApiKey, environment: 'development'));
  await Anectico.identify('quickstart-user', set: {'email': 'quickstart@example.com', 'plan': 'test'});
  await Anectico.capture('checkout_started');
  await Anectico.captureError(StateError('quickstart payment failure'), StackTrace.current);
  final result = await Anectico.flush();
  print('Product delivery: ${result.productEvents}');
  print('Trace and error delivery: ${result.traces}');
}

In each program the identifier is quickstart-user, a stable id, and the email address is a property. Anectico stores the identifier exactly as sent and stores the email as [REDACTED], so you find this customer by the id, never by the email. Keep that shape in your own code. See What Anectico redacts and withholds.

Run the program once

JavaScript / TypeScript

node quickstart.mjs

Python

python quickstart.py

Go

go run .

Swift (iOS)

Build and run your app in Xcode on a simulator or device, then invoke try sendQuickstart(apiKey: ...) once from your development flow. Handle any thrown configuration error.

Kotlin (Android)

Build and run your app in Android Studio on an emulator or device, then call sendQuickstart(applicationContext, ...) once with your development project key.

React Native

Rebuild and run the native iOS or Android app using your project's run command, then call await sendQuickstart(...) once. A JavaScript reload alone cannot install the SDK's native module.

Flutter

Run flutter run on an iOS or Android target and call await sendQuickstart(...) once. The mobile plugin is not supported on Flutter web or desktop.

Keep a mobile app running until the flush completion or future settles. Mobile flush reports productEvents, nullable logs and traces separately, including errors in traces. Inspect accepted, rejected, pending, unknown and sampled counts, warnings and unavailable reasons; an empty queue with zero accepted is not delivery proof. Then read the stored customer story. See your mobile SDK guide for the full delivery contract.

4. Ask your agent, then open the proof

Ask your connected agent about the test customer:

What happened to quickstart-user in the last hour? Give me a link I can open.

The agent finds the person, reads their timeline, and follows the error to its issue and trace. It uses the tools in this table. You can run the same reads yourself with the CLI.

Job MCP tool or action CLI command
Find the test customer search_persons anectico persons search
Read their story, newest first get_person_timeline anectico persons timeline
Read the error issue search_issues, get_issue anectico issues search, anectico issues view
Read the trace get_trace anectico traces get
Check the whole setup instrumentation_doctor anectico doctor instrumentation
Apply a starter recipe for a business journey apply_instrumentation_recipes anectico recipes apply

The timeline should contain your test error plus the checkout trace (server examples) or the checkout_started event (mobile examples). Select the same project and the development environment when you filter. Mobile SDKs do not automatically record full network traces. To add a backend trace, follow Mobile SDK propagation.

Open the proof

Each MCP tool result about one thing carries a link in its url field. (The CLI's reads print no link. Ask your agent to use the MCP tool when you want one.) For this test, open the person proof page (/view/person/...). It shows the customer's story: the error, the trace and the event, in time order. Open the issue and trace links from the same answer to see them. The pages are read-only. They name their project, and Copy link shares them with a teammate. See Proof pages.

If the agent gives no link, ask it which tool result supports each claim. A search that finds nothing has no proof page, and that is also an answer.

5. Record your first business journey

The error and trace above prove connectivity. A business journey (signup, activation, invitation, purchase) is what most teams want to measure next. Anectico ships a small catalog of starter recipes so you do not have to write them by hand. Each recipe is a named business event, an example SDK snippet, and one or more starter insights (a trend or a funnel) that read the event once you send it.

Ask your agent to apply the recipes your product uses, or do it with the CLI. The MCP tools are list_instrumentation_recipes, get_instrumentation_recipe and apply_instrumentation_recipes.

anectico recipes list
anectico recipes show signup
anectico recipes apply signup activation                          # preview only; writes nothing
anectico recipes apply signup activation --confirm-token "$TOKEN"  # apply

apply without --confirm-token previews the change and prints a confirmation token. Repeat the same arguments with that token to apply it. The API key needs mcp:read, mcp:write, tracking_plans:read, tracking_plans:write, insights:read and insights:write. The setup guide in the Console offers the same recipes as its last step.

Applying writes to one tracking plan per project, named "Recipes" (see tracking plans), and creates the recipes' starter insights as saved insights. Running apply again with the same recipes and nothing else changed is always safe: it reports what it would change or writes nothing.

Starter insights use the last seven days so you can run them on a project with seven days of retention. Edit the saved insight's window if you want to measure a longer period that your readable history supports.

Each recipe's snippet shows the exact call order that matters. identify and group come before the business event they attach to, so the event joins the right person and account timeline from the start rather than an anonymous one that gets stitched together later:

analytics.identify(userId, { email: userEmail, name: userName }); // before the event
analytics.capture('signed_up', { method: 'email', plan: 'starter' });

userId is your own stable id for the user. The email property is stored as [REDACTED]; name is stored as sent.

For invitation, attribute both invite_sent and invite_accepted to the same company, while identifying the inviter and invitee as their own people. Include the same opaque string invitation_id on both events; use an identifier rather than the invitation's secret token. The Companies accepting invitations starter counts companies with at least one matching invitation sent and then accepted within 24 hours. Each company enters and converts once, even if it sends several invitations. An acceptance for a different invitation cannot complete that chain. Missing invitation IDs or company attribution cannot enter or complete the funnel. Daily accepted invitations separately counts every invite_accepted event, including an acceptance whose send was outside the measured history.

Applying the updated catalog creates new starter insights. Older saved insights keep their definitions and any edits; use the new starter and update your captures with invitation_id to measure the matched company journey.

For purchase, capture the event server-side with a server API key. A browser can edit an amount or plan before a client-side capture reaches you; a server-issued event cannot be altered in transit the same way.

Once you have sent a few of these events from your own application, check that they match what the recipe declared: required fields present, types correct.

anectico --project "$PROJECT_ID" analytics tracking-plans drift "$PLAN_ID" --revision "$REVISION" \
  --event signed_up --start 2026-09-13T00:00:00Z --end 2026-09-14T00:00:00Z

The applied receipt names the plan ID and revision to fill in above. This is the same declared-vs-observed comparison used for any other tracking-plan event. Recipes add no new diagnostic engine, so a missing required property or an unexpected type shows up exactly the way it would for a hand-written plan. To also confirm a specific test customer's journey resolved correctly, add --tracking-plan-id and --tracking-plan-revision to anectico doctor instrumentation. See Compare a journey with a pinned tracking declaration.

If nothing appears

Most setup failures are an API key, project, environment, or shutdown or flush mismatch. Follow No data is appearing before changing sampling or transport settings.

Next