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:
- sign up;
- connect your agent with one command;
- send a test error and a trace (server SDKs) or a diagnostic event (mobile SDKs) for a test customer; and
- 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:
- 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.
- Stores the secret in your operating system keychain, not in your terminal history and not in any file you commit.
- Merges the Anectico server into your agent's MCP configuration (
.mcp.jsonfor Claude Code,~/.codex/config.tomlfor Codex,.cursor/mcp.jsonfor Cursor,~/.gemini/settings.jsonfor Gemini CLI,~/.config/muse/settings.jsonfor Muse Code), leaving every other entry as it was, and installs the Anectico skills. - 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_ingestandserver_capturekeys (usebrowser_capturefor a browser ormobile_capturefor 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-userin 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.