Reference
Python SDK API
Classes, methods, parameters, return values, configuration, and integrations for the Anectico Python SDK.
This is the application-developer API for anectico 0.1.x. The SDK supports Python 3.11+, synchronous
and asynchronous frameworks, OpenTelemetry signals, identity, diagnostic events, feature flags, and
LLM wrappers.
Use ingest:write for traces, metrics, logs, and errors. Add analytics:write for identity, groups,
events, and flag exposure events; add flags:read for flag decisions.
Create and run AnecticoClient
import os
import anectico
client = anectico.AnecticoClient(
api_key=os.environ['ANECTICO_API_KEY'],
service_name='orders-api',
)
client.start()
try:
run_application()
finally:
shutdown = client.stop()
if shutdown.success is False:
report_telemetry_delivery_failure(shutdown.errors)
| API | Parameters | Returns | Behavior |
|---|---|---|---|
AnecticoClient(...) |
core options below or config=AnecticoConfig(...) |
AnecticoClient |
Builds an unstarted client. A supplied config takes precedence over every other constructor argument. |
start() |
— | same AnecticoClient |
Validates configuration. Managed mode starts owned transports and the optional standard-library logging bridge; existing mode only enables helpers against application globals. Repeated calls are safe. |
stop() |
— | ShutdownResult |
Managed mode removes the log bridge and concurrently flushes/stops owned providers. Existing mode never touches application providers and returns an unattempted result. Repeated calls are safe. |
is_running |
property | bool |
Whether the client currently accepts telemetry. |
| context manager | with AnecticoClient(...) as client |
client | Starts on entry, captures an exception leaving the block, then stops. |
flush(timeout_ms=None) |
optional milliseconds | bool |
Flushes client-owned managed providers. Returns False in existing mode; the application must flush its providers. |
config |
property | AnecticoConfig |
Active configuration. Contains the API key; do not log or serialize it. |
stats |
property | dict[str,int] |
Counters for spans, metrics, logs, and captured errors. |
Keep one client per process. Framework middleware supplies request-scoped identity and spans; do not construct a client per request.
ShutdownResult has attempted, flush_succeeded, shutdown_succeeded,
success, and a tuple of sanitized errors. success is True only when an
attempted shutdown fully delivered and stopped every enabled provider. It is
False for a provider False return, exception, or timeout, and None when
the client was already stopped. Boolean conversion is true only for full
success. A Python context manager cannot return its exit outcome; use explicit
start()/stop() when the process must record delivery evidence.
Constructor and AnecticoConfig
The constructor directly accepts the most common fields. AnecticoConfig exposes the complete set.
| Field | Type | Default/environment | Purpose |
|---|---|---|---|
api_key |
str |
ANECTICO_API_KEY; required |
Project-scoped Anectico API key. |
service_name |
str |
OTEL_SERVICE_NAME; required |
Logical service name. |
service_version |
str |
OTEL_SERVICE_VERSION; 0.0.0 |
Deployed version. |
environment |
str |
ANECTICO_ENVIRONMENT; development |
Deployment environment. |
endpoint |
str |
ANECTICO_ENDPOINT; https://api.anectico.com |
HTTP requires an absolute http(s) URL. gRPC accepts an http(s) authority URL without a path or host:port. |
open_telemetry_mode |
managed | existing |
ANECTICO_OTEL_MODE; managed |
Provider ownership. Existing mode uses application-registered globals and does not configure or own their lifecycle. |
protocol |
http | grpc |
OTEL_EXPORTER_OTLP_PROTOCOL; http |
OTLP transport. |
insecure |
bool |
OTEL_EXPORTER_OTLP_INSECURE; False |
Disable TLS; local development only. |
enable_traces, enable_metrics, enable_logs |
bool |
corresponding ANECTICO_ENABLE_*; True |
Enable each signal pipeline. |
trace_sample_rate |
float |
OTEL_TRACES_SAMPLER_ARG; 0.1 |
Trace sampling in the inclusive range 0–1. |
error_sample_rate |
float |
ANECTICO_ERROR_SAMPLE_RATE; 1 |
Non-fatal captured-error sampling. |
batch_timeout_ms |
int |
OTEL_BSP_SCHEDULE_DELAY; 5000 |
Maximum batching delay. |
batch_size |
int |
OTEL_BSP_MAX_EXPORT_BATCH_SIZE; 512 |
Maximum export batch size. |
max_queue_size |
int |
OTEL_BSP_MAX_QUEUE_SIZE; 2048 |
Queue capacity; must be at least batch_size. |
export_timeout_ms |
int |
OTEL_BSP_EXPORT_TIMEOUT; 30000 |
Per-export deadline; also the total HTTP same-batch retry window. |
shutdown_timeout_ms |
int |
OTEL_BSP_SHUTDOWN_TIMEOUT; 5000 |
One aggregate graceful flush/shutdown deadline across enabled providers. |
metric_export_interval_ms |
int |
OTEL_METRIC_EXPORT_INTERVAL; 60000 |
Metric push interval. |
bridge_stdlib_logging |
bool |
ANECTICO_BRIDGE_STDLIB_LOGGING; True |
Export normal logging records through this client. |
log_level |
str |
ANECTICO_LOG_LEVEL; info |
Minimum bridged log level. |
log_redaction_fields |
tuple[str,...] |
ANECTICO_LOG_REDACTION_FIELDS; empty |
Additional comma-separated structured-log field names to redact. Extends, never replaces, built-in credential and financial-account protection. |
attach_stack_trace |
bool |
ANECTICO_ATTACH_STACK_TRACE; True |
Attach exception frames. |
max_stack_trace_frames |
int |
ANECTICO_MAX_STACK_TRACE_FRAMES; 50 |
Maximum exception frames. |
instrument_http_clients |
bool |
ANECTICO_INSTRUMENT_HTTP_CLIENTS; False |
Globally instrument requests/httpx. Opt in only for trusted traffic. |
propagate_trace_header_urls |
tuple[str,...] |
ANECTICO_PROPAGATE_TRACE_HEADER_URLS; empty |
Absolute trusted prefixes allowed to receive trace/identity headers. |
trust_incoming_identity |
bool |
ANECTICO_TRUST_INCOMING_IDENTITY; False |
Adopt inbound Anectico identity baggage. Enable only behind a sanitizing authenticated gateway. |
resource_attributes |
dict[str,str] |
OTEL_RESOURCE_ATTRIBUTES; empty |
Extra resource attributes. |
headers |
dict[str,str] |
OTEL_EXPORTER_OTLP_HEADERS; empty |
Extra export headers. |
debug |
bool |
ANECTICO_DEBUG; False |
SDK diagnostic logging. |
AnecticoConfig.from_env(**overrides) resolves environment variables and applies explicit overrides.
validate() raises on missing/invalid configuration. get_endpoint_for_signal(signal),
get_headers(), and get_log_level() support custom integrations.
open_telemetry_mode accepts exactly managed or existing (case-sensitive).
In existing mode the application must register providers before
AnecticoClient.start(). Anectico creates no provider, exporter, export processor,
metric reader, propagator, HTTP instrumentation, or standard-library logging
bridge. Managed resource, sampling, endpoint, batching, exporter, propagation,
and logging settings do not reconfigure application providers; signal enable
flags still gate the corresponding Anectico helpers.
The enabled signal endpoints are resolved before validation, so
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, and
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT can replace the base endpoint for their
signals. Endpoint errors never echo the configured URL, which may contain
sensitive deployment information.
HTTP exporters retain the same serialized batch for connection loss and
retryable 408/5xx responses throughout the configured
export_timeout_ms window. Jittered exponential backoff is bounded by the
remaining deadline, interrupted by shutdown, and exhausted once without a
nested retry loop. Certificate verification, TLS configuration, and
client-certificate failures are classified as permanent, attempted once, and
logged with a sanitized diagnostic. Certificate verification is never disabled
implicitly.
Traces, metrics, logs, and AI operations
| Method/property | Parameters | Returns | Behavior |
|---|---|---|---|
tracer |
property | OTel Tracer |
Underlying tracer for advanced use. |
meter |
property | OTel Meter |
Underlying meter for advanced use. |
start_span(name, **kwargs) |
name; arguments forwarded to Tracer.start_as_current_span |
context manager yielding OTel Span |
Makes the span current for the with block, so nested spans, captured errors, and correlated logs inherit its trace context; yields a non-recording span before startup. For manual lifetime control, use client.tracer.start_span(...). |
record_metric(name, value, labels=None) |
name; float; string labels | None |
Creates a gauge and records one value. |
log_event(level, message, attrs=None) |
debug/info/warn/warning/error/fatal; body; attributes |
None |
Emits a structured OTLP log; no-op when logs are disabled. |
record_llm_call(model, **options) |
required model; options below | None |
Emits one completed gen_ai client span. |
record_tool_call(name, **options) |
required tool name; options below | None |
Emits one completed internal tool span. |
start_agent_run(agent, **options) |
agent; optional IDs | context manager yielding AgentRun |
Makes the agent span current so nested calls become children. Call run.end(status, reason_code); normal exit defaults to completed and exceptions safely record failed/exception. |
record_llm_call accepts response_model, provider, operation, token counts, cost_usd,
finish_reason, is_error, start_time, and end_time. messages and output opt into sensitive
content. record_tool_call accepts tool_type, call_id, conversation_id, agent_name,
is_error, arguments, and result; arguments/results are also opt-in content.
Agent-run status is completed, failed, timed_out, cancelled, or max_steps. Reason codes are
lowercase [a-z][a-z0-9_]{0,63} values, not exception/provider text. The first valid end call wins;
later calls are no-ops. Calling run.span.end() directly bypasses the terminal contract and leaves
Anectico to use its legacy inferred status.
Managed mode bridges standard-library logging by default. Those records
inherit active OTel trace context; prefer ordinary logger.info(...) inside
application code. Existing mode installs no bridge: ordinary logs use the
application’s logging setup, while log_event() uses the registered global
Logger Provider and safely no-ops without a real provider. When a framework
logs the same exception after capture_error, the managed bridge links that log
with the canonical error.id: the log remains searchable without creating a
second Issue. Independent error logs still create Issues.
Application values supplied through logging(..., extra={...}) are exported as structured
attributes. Safe top-level strings, booleans, integers, floats, and homogeneous primitive sequences
retain their OpenTelemetry types. Nested mappings or mixed/nested sequences are recursively
sanitized, then stored as bounded canonical JSON because OpenTelemetry attributes do not support
nested objects. The bridge excludes Python’s reserved LogRecord fields and private keys.
Before export, field names such as password, authorization/Bearer, token/API key, cookie, secret,
bank/routing/account number, IBAN, card, and PIN are replaced with [REDACTED], including inside
nested mappings and sequences. Credential forms in the message and exception stack text are also
redacted. Add domain-specific names without weakening the built-ins:
client = AnecticoClient(
api_key=os.environ["ANECTICO_API_KEY"],
service_name="payroll",
log_redaction_fields=["payroll_reference"],
)
The equivalent environment value is
ANECTICO_LOG_REDACTION_FIELDS=payroll_reference,employee_private_code.
Errors, messages, users, and breadcrumbs
| Method | Parameters | Returns | Behavior |
|---|---|---|---|
capture_error(error, *, user=None, tags=None, extra=None, fingerprint=None, level='error') |
exception and optional context | str |
Captures the exception and returns its ID; '' before startup or when sampled out. fatal bypasses sampling. |
capture_message(message, level='error', *, user=None, tags=None, extra=None) |
message, severity, optional context | str |
Captures a message and returns its ID. |
add_breadcrumb(category, message, *, level='info', data=None) |
breadcrumb fields | None |
Adds to the 100-entry trail attached atomically to the next error. |
set_user(user) |
User |
None |
Sets global error user context. |
get_user() |
— | User | None |
Returns request-local user first, then global user. |
clear_user() |
— | None |
Clears global error user context. |
Capture tags keys are encoded as indexed anectico.tag.* telemetry attributes automatically.
Capture severity is also indexed as error.level for Issue filtering and context.
User fields are id, email, username, ip_address, segment, and data. Use
set_context_user(user)/get_context_user() for an async request-local error user. The cross-signal
person identity remains distinct_id, managed separately below.
Identity and groups
| API | Parameters | Returns | Behavior |
|---|---|---|---|
client.identify(distinct_id, properties=None) |
stable ID; person properties | None |
Switches shared identity and performs best-effort canonical-person sync. Raises ValueError for an empty ID. |
client.sync_person(distinct_id, properties=None) |
stable ID; person properties | None |
Performs best-effort canonical-person sync without an anonymous alias or any process-wide identity mutation. Use at trusted server authentication/profile boundaries. |
client.group(group_type, group_key, properties=None) |
type/key; group properties | None |
Associates the person with an account and sends a membership assertion. Empty type/key is ignored. |
client.reset() |
— | None |
Logout: creates a new anonymous identity and clears groups, global error-user context, and uncaptured breadcrumbs. Already-captured telemetry remains queued with its original attribution. |
shared_identity() |
— | IdentityManager |
Returns the process-wide identity holder shared by signals and analytics. |
set_context_distinct_id(id) |
stable ID | DistinctIDScope |
Sets async-safe request identity; reset with the returned token. |
reset_context_distinct_id(token) |
scope token | None |
Restores the prior request identity. |
resolve_distinct_id_for(context=None, identity=None) |
optional OTel context/manager | str |
Resolves request scope, baggage, then shared identity. |
adopt_distinct_id_from_baggage(context=None) |
OTel context | DistinctIDScope | None |
Promotes trusted baggage into request scope. Never call directly on untrusted public input. |
IdentityManager exposes get_distinct_id, get_anon_id, is_identified, identify, group,
get_groups, and reset. Use the module-level helpers for request scope.
Diagnostic events: AnalyticsClient
events = anectico.AnalyticsClient(
endpoint='https://api.anectico.com',
api_key=os.environ['ANECTICO_API_KEY'],
)
| API | Parameters | Returns | Behavior |
|---|---|---|---|
AnalyticsClient(endpoint, api_key, flush_at=20, flush_interval_s=5, sender=None) |
connection, batching, optional custom sender | client | Starts an optional daemon flush worker. |
capture(event, properties=None, *, distinct_id=None, session_id=None, timestamp=None) |
event and optional overrides | None |
Queues an event. Without an explicit ID it uses shared identity. |
identify(distinct_id, properties=None, *, anon_distinct_id=None) |
ID; properties; optional alias | None |
Queues identify, switches shared identity, and flushes. |
group(group_type, group_key, properties=None) |
group and properties | None |
Records shared membership and queues $groupidentify. |
flush() |
— | None |
Synchronously sends the current queue; transient failures are requeued. |
stop() |
— | None |
Stops the worker and flushes. Further calls raise a closed-client error. |
reset() |
— | None |
Rotates shared anonymous identity. |
Feature flags: anectico.feature_flags.FeatureFlags
Construct with endpoint, api_key, a capture(event, properties, distinct_id) callback, and
optional bootstrap response. The key needs flags:read; the callback normally sends exposure events
using analytics:write.
| Method | Parameters | Returns | Behavior |
|---|---|---|---|
reload(distinct_id, person_properties=None, groups=None) |
person and targeting context | None |
Calls /api/v1/decide and replaces cached decisions. Network/API failures raise. |
get_feature_flag(key, distinct_id) |
key and ID | decision or None |
Returns a decision and emits one deduplicated exposure. |
is_feature_enabled(key, distinct_id) |
key and ID | bool |
True for True or a non-empty string variant. |
get_feature_flag_payload(key) |
key | any | Returns the cached payload. |
get_all_flags() |
— | dict |
Returns a copy of cached flags. |
had_evaluation_errors() |
— | bool |
Whether the latest evaluation used a fallback. |
reset() |
— | None |
Clears exposure dedup after identity changes. |
refresh_local_evaluation() |
constructor project_id supplies scope |
"updated" | "not_modified" |
Fetches or conditionally revalidates the strict project snapshot; requires flags:read. |
evaluate_local(key, distinct_id, person_properties=None) |
flag key, exact identity, person properties | LocalEvaluationResult |
Uses only a fresh snapshot; successful reads use the constructor capture callback. |
Pass the exact canonical project_id to the same FeatureFlags constructor to enable server-side
local evaluation. refresh_local_evaluation() conditionally validates the versioned snapshot;
evaluate_local(key, distinct_id, person_properties=None) returns LocalEvaluationResult with a
value/payload or an explicit unavailable, stale, unsupported-target, or malformed-rule error. The
last-known-good snapshot is usable only through its advertised max-age. Successful local
matched/default reads use the existing capture callback to emit $feature_flag_called, deduped
per identity/key/value; reset() reopens both remote and local deduplication. That capture
path needs analytics:write when it sends to Anectico.
Framework and provider integrations
| Integration | Constructor/function | Behavior |
|---|---|---|
| FastAPI/Starlette | AnecticoFastAPIMiddleware(app, client=None, skip_paths=None, trust_incoming_identity=False, request_identity_resolver=None) |
Privacy-safe ASGI server spans, status/duration, fail-open errors, explicit cancellation outcomes, and optional sync/async server-authenticated identity. Matched operations/URL targets use the bounded route template; concrete path/query values are excluded. skip_paths=set() disables default exclusions. |
| Flask | AnecticoFlaskMiddleware(app, client, skip_paths=None, trust_incoming_identity=False) |
Registers request hooks without changing responses/error handlers. Matched operations and URL/target attributes use the bounded Werkzeug route; concrete path identifiers, query/fragment values, and unmatched paths are not exported. Unmatched operations use the HTTP method only. Unhandled exceptions are captured before Flask’s framework log and the server span ends once during teardown, keeping one linked Issue/log/trace. skip_paths=set() explicitly disables the default health/static exclusions. |
| Django | AnecticoDjangoMiddleware after Django authentication; ANECTICO settings mapping |
Creates route-normalized server spans, request-scoped authenticated identity, privacy-safe ORM child spans, status/duration, and deduplicated real-view exception capture. Full query strings, SQL/parameter values, usernames, and email addresses are not exported on spans. USER_ID_RESOLVER accepts a callable or dotted path and defaults to authenticated user.pk; put recognizable profile fields in sync_person. |
| Django lifecycle | get_django_client() / shutdown_django_client() |
Returns the process-local auto-created client / returns its ShutdownResult and detaches it. A repeated hook returns attempted=False, success=None. Use the shutdown helper from Gunicorn worker_exit. |
| Celery | AnecticoCeleryIntegration(app, client) / close() |
Strongly registers publish/task lifecycle receivers; restores Anectico log export after Celery’s default logger setup; injects and extracts W3C trace plus identity baggage through private broker headers; activates one consumer span per retry attempt for child/log/error correlation; records type-only retry diagnostics; and never copies task arguments, results, or retry messages. close() disconnects receivers but does not stop the application-owned client. |
grpc.aio unary client |
AnecticoAioUnaryUnaryClientInterceptor(client) |
Starts a client span and injects W3C trace/identity metadata only on channels where the interceptor is explicitly installed. Application messages, propagation values, and arbitrary metadata are not recorded. Non-OK transport spans remain visible but do not create generic Issues; capture one typed error at the domain handling boundary when needed. |
grpc.aio server |
AnecticoAioServerInterceptor(client, trust_incoming_identity=False) |
Continues an inbound unary-unary trace, records method/duration/status, and rejects caller-supplied Anectico identity by default. Enable identity trust only on a private sanitizing boundary. Non-OK transport spans remain visible but do not create generic Issues. |
| OpenAI | wrap_openai(client, anectico_client, capture_content=False) |
Idempotently instruments sync/async Chat Completions, including streams, in place and returns the same client. A stream records once on exhaustion; use stream_options={"include_usage": True} for token/cost fields. |
| Anthropic | wrap_anthropic(client, anectico_client, capture_content=False) |
Instruments sync/async non-streaming messages in place and returns the same client. |
Anthropic streaming calls pass through without automatic LLM spans. An OpenAI stream closed before exhaustion records one error-status call; a provider or iteration exception is preserved. Telemetry errors never replace a provider exception. Content capture is disabled by default.
Authentication and lower-level utilities
These exports support custom middleware and integrations. Application code should generally use
AnecticoClient and AnalyticsClient.
| API/type | Parameters or fields | Returns/behavior |
|---|---|---|
validate_api_key(key) |
string | None; raises InvalidAPIKeyError for an unsupported key shape. |
anectico.auth.is_api_key_format(value) |
string | Boolean shape check without throwing. |
mask_api_key(key) |
string | Log-safe prefix plus last four characters; never usable as a credential. |
User(...) |
id, email, username, ip_address, segment, data |
Error-user data class; to_otel_attributes() returns enduser.*/user.data.* attributes. |
set_context_user(user) |
User or None |
Sets async request-local error-user context; call with None when the scope ends. |
get_context_user() |
— | Request-local User or None. |
Breadcrumb(timestamp, category, message, level, data=None) |
canonical breadcrumb fields | to_dict() returns the JSON-compatible wire shape, omitting empty data. |
BreadcrumbBuffer() |
fixed capacity 100 | Thread-safe add, snapshot, serialize, drain, and clear; drain serializes and clears atomically. |
ErrorLevel |
DEBUG, INFO, WARNING, ERROR, FATAL |
String severity constants. |
ErrorOptions(...) |
user, tags, extra, level, fingerprint |
Data class for custom error-recording integrations. Normal capture calls accept these fields directly. |
IdentityManager() |
— | Thread-safe holder with get_distinct_id, get_anon_id, is_identified, observability_distinct_id, identify, group, get_groups, and reset. Use the module-level functions for request scope. |
shared_identity() |
— | Process-wide manager shared by signals and diagnostic events. |
BaggageIdentitySpanProcessor(identity=None) |
optional IdentityManager |
Identity-only span processor for application-owned providers. Defaults to shared_identity(); does not export/register/own lifecycle. Add before the export processor. |
BaggageIdentityLogRecordProcessor(identity=None) |
optional IdentityManager |
Identity-only log processor for application-owned providers. Defaults to shared_identity(); does not export/register/own lifecycle. Add before the export processor. |
BAGGAGE_DISTINCT_ID_KEY |
constant | The W3C baggage member name anectico.distinct_id. |
DistinctIDScope |
opaque token | Returned by set_context_distinct_id; pass it to reset_context_distinct_id. |
anectico.__version__ reports the installed package version. Lower-level stack/error serializer and
transport modules are implementation APIs and may change; use the public client methods above.