Skip to content
anecticoDocsDashboard
Browse documentation
Reference

Python SDK API

Classes, methods, parameters, return values, configuration, and integrations for the Anectico Python SDK.

On this page

This is the application-developer API for anectico 0.1.x. The SDK supports Python 3.10+, 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 and the pending identity-event queue. True only when nothing was left unaccepted. 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, captured errors, and identity_events_dropped.

flush() combines two halves and never turns an unknown into a success. The identity-event queue is owned by the SDK end to end, so it reports real acceptance: a permanently rejected identify batch makes flush() return False and increments stats['identity_events_dropped'], and a rejected final batch makes stop() report a failed ShutdownResult rather than a silent success. The telemetry half reports its provider flush outcome — buffered signals drained and exported — which is not a per-request acceptance, and is passed through rather than reinterpreted.

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. Unknown override names raise ValueError. Queue sizes and stack-frame limits must be integers; timeouts must be finite and positive. An explicitly empty service name is invalid even when the environment contains a name. Authentication headers override custom headers case-insensitively. 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.

start_agent_run(..., agent_version="checkout-agent@2026.08.24") optionally declares the release that produced the run. It is recorded as the standard gen_ai.agent.version span attribute. Leave it unset when the release is unknown; Anectico reports that as undeclared rather than treating it as an error or silently filtering the run away.

Context assembly events

The run handle exposes record_context_assembly(value), record_context_compaction(value), and record_context_cache(value). Call them while a recording model span is current and carries gen_ai.operation.name = chat | text_completion | generate_content | embeddings | fetch_response. The SDK raises ValueError for the run span, a tool span, an ended span, or no active span. It validates every field before adding the one event, so a rejected value records nothing.

with client.start_agent_run("support-planner") as run:
    with client.tracer.start_as_current_span(
        "chat gpt-4o",
        kind=SpanKind.CLIENT,
        attributes={"gen_ai.operation.name": "chat"},
    ):
        run.record_context_assembly(
            ContextAssembly(
                budget_tokens=8192,
                reserved_output_tokens=1024,
                assembled_tokens=6144,
                overflow="none",
                assembly_sha256=assembly_sha256,
                sources=[ContextSource(
                    kind="memory", id="memory:item-7", sensitivity="confidential",
                    tokens=512, position=3, visibility="included",
                )],
            )
        )

See Context events for exact bounds. Never send compaction ratio; the server derives it. OpenAI and Anthropic wrappers add cache hit/miss events when cache fields are present. A reported zero is a miss, while an absent field produces no event.

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

Breadcrumbs snapshot nested JSON data when added. If optional data cannot be serialized, the breadcrumb is retained without that data so error reporting can still include the trail.

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

Capture snapshots event properties when enqueueing. Later mutations do not change queued events. Properties must be JSON-serializable; invalid events are rejected before they enter the queue. The built-in analytics and feature-flag HTTP clients do not follow redirects: configure the final API endpoint directly so project credentials stay at that endpoint.

events = anectico.AnalyticsClient(
    endpoint='https://api.anectico.com',
    api_key=os.environ['ANECTICO_API_KEY'],
    release=os.environ.get('MY_APP_RELEASE'),
    app_version=os.environ.get('MY_APP_VERSION'),
)

release and app_version are stamped as the reserved $release/$app_version string properties on every capture()'d event when set; the SDK never auto-detects a server deployment's version, so set them yourself from your own deploy pipeline (for example, reading your own environment variable in application code — this module never reads the environment itself). Leave them unset and the properties are omitted entirely, never sent as "". See Reserved event properties.

API Parameters Returns Behavior
AnalyticsClient(endpoint, api_key, flush_at=20, flush_interval_s=5, sender=None, on_delivery_error=None, release=None, app_version=None) connection, batching, optional custom sender, optional dropped-batch handler, optional release identifiers 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 and switches shared identity after enqueue; normal batching controls delivery.
group(group_type, group_key, properties=None) group and properties None Records shared membership and queues $groupidentify.
flush() — bool Validates complete indexed acknowledgements. Returns True for all attempted events queue-acknowledged (or an empty queue), False for explicit refusals without pending retries, and raises RuntimeError while uncertain events remain.
stop() — bool Stops the worker and flushes, returning what that final flush returned. Raises while retryable events remain queued. Further capture calls raise a closed-client error.
disable() — None Immediately closes analytics collection and discards pending work without a final flush; active delivery settles separately.
stats() — dict[str,int] recorded, delivered, dropped, queued. delivered counts validated queue acknowledgements; dropped counts explicit refusals/local overflow; queued includes in-flight and uncertain events.
reset() — None Attempts to flush, then rotates shared anonymous identity even if delivery raises; retained events keep their original attribution.

Capture uses the versioned indexed acknowledgement contract. HTTP status alone never proves delivery or refusal. The SDK validates the version, request UUID, original indices, all outcomes and totals before changing counters. Queue acknowledgement does not prove a unique stored row, query visibility or a completed identity mutation.

flush() raises while uncertain events remain, including network errors and malformed responses at any HTTP status. A flush can report explicit drops and also retain an uncertain remainder; inspect stats() and on_delivery_error when it raises. Only uncertain original positions and unsent later chunks retry, preserving message IDs, identity, timestamps and payloads. Retries wait at least one second and honor Retry-After up to 60 seconds. Accepted and refused siblings are never automatically retried.

stop() performs a final flush. For collection withdrawal, call disable() instead: collection closes immediately and pending events are discarded with collection_disabled. Further capture/identify/group/sync_person calls raise the closed-client RuntimeError. Disable is nonblocking and safe in a delivery callback; call flush() outside callbacks to wait for an active request to settle, then inspect stats. A chunk already admitted to delivery may still reach the server; its validated acceptance/refusal counts remain, but uncertain positions and later chunks are never retried. A flush that discards work returns False. After settlement, queued is zero. Repeated disable is safe; new consent requires a new AnalyticsClient. This does not erase stored events or disable separate telemetry clients. Custom synchronous senders must supply a finite I/O deadline; the SDK cannot cancel arbitrary Python code. Gate collection before initialization where your application requires it.

Explicit refusals are reported once per affected chunk through on_delivery_error(DeliveryError(status, dropped, reason)), stats()["dropped"], and a warning. Reasons include invalid_event, quota_exceeded, mixed_rejection, bad_request, unauthorized, forbidden, payload_too_large, queue_overflow and collection_disabled (local discards use status 0). Uncertainty alone does not fire a drop callback. A handler that raises is swallowed. Response bodies larger than 64 KiB or inconsistent with HTTP framing remain uncertain, even with a valid JSON prefix.

events = anectico.AnalyticsClient(
    endpoint='https://api.anectico.com',
    api_key=os.environ['ANECTICO_API_KEY'],
    on_delivery_error=lambda err: my_alerting.warn(
        f'anectico dropped {err.dropped} events: {err.status} {err.reason}'
    ),
)

Capture resolves its explicit ID, request-local identity, W3C baggage, then shared identity. Shared $groups are inherited only for that shared person; explicit event $groups take precedence. Request-scoped group assertions do not change another person's shared memberships. Identity/group changes follow successful enqueue even when immediate delivery fails. reset() clears identity even during a delivery outage, while queued events keep their original attribution.

Custom senders must return anectico.analytics.SendResult(status, body, retry_after_s=None). body contains the exact response bytes, including typed failures. An integer status or an assumed accepted count is insufficient evidence and leaves the batch queued. Custom transports must bound their network operations and preserve complete response framing; the default urllib sender uses a 10-second socket timeout, a bounded body read, and checks declared content length. Both use the same acknowledgement validator. Analytics and feature-flag endpoints must be absolute HTTP(S) base URLs without credentials, query strings, or fragments.

Feature flags: anectico.feature_flags.FeatureFlags

Bootstrap data and returned payload containers are copied. Exposure deduplication distinguishes identity, flag name, and the response's type and value. Remote decision responses must contain one JSON document of at most 16 MiB, with boolean or string flag values. Invalid responses preserve the last valid cache; overlapping reloads allow only the latest invocation to replace it.

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 a deep copy of 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.

FastAPI, Flask, and Django strip URL userinfo, query strings, and fragments. HTTP attributes are bounded independently and receive a .truncated=true sibling when shortened, so one oversized request does not invalidate an exporter batch. Managed child spans also preserve the sampled or unsampled flag of a valid incoming trace parent; local ratios apply only to new roots. | 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; isolates each consumer attempt in its execution context, including overlapping deliveries with the same task ID, 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 messages, including streams, in place and returns the same client. Token and cache counts need no extra request parameter. |

A stream is recorded once, when it is exhausted, fails, or is abandoned. Closing a stream before exhaustion — or leaving its with block early — is not an error: the span keeps its normal status and carries anectico.gen_ai.stream.abandoned = true, so early exits stay out of your error rate while remaining distinguishable. Its token counts are the provider's last reported values and are partial by construction. A provider or iteration exception records an error-status call and is preserved unchanged.

Stream telemetry retains the identity and trace context present when the provider call began, even if a different request or task later consumes the stream.

Neither wrapper changes your request; stream_options={"include_usage": True} is never added for you, because it inserts an extra empty-choices chunk into your loop and is rejected outright by some OpenAI-compatible gateways. A count the provider never reported is recorded as absent, never as zero. Anthropic's messages.stream() helper is not covered — it issues its own request rather than going through messages.create — so use messages.create(..., stream=True) for an instrumented stream. 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.