Skip to main content

virgo-observe

Four Python operations for Virgo: register a client, trace an operation, attach feedback, and publish an individual product metric. Traces use OpenTelemetry; feedback and metrics use unsampled HTTP channels authorized by the same Observe key.

Version 0.7.0 adds native Codex SDK turn/tool/usage observation and concurrent Pydantic AI plus direct OpenAI coverage. Registration automatically discovers installed supported integrations, reads saved bootstrap configuration, and drains telemetry on normal Python exit.

Install the extras for the application's supported agent harnesses, for example:

uv add "virgo-observe[codex,pydantic-ai]==0.7.0"

Then register once during startup:

from virgo_observe import register

register(project_name="my-project")

No framework selection is required. Required adapters must be installed and framework versions compatible. FastMCP needs its server-instance attachment; Semantic Kernel needs its native telemetry setup, as documented below. Standalone, non-agentic provider calls are optional for onboarding; add the openai or anthropic extra if that additional coverage is wanted. Calls made inside agent harnesses remain part of agent coverage.

Platform pins virgo-observe[codex,openai,pydantic-ai]==0.7.0, preserving Pydantic AI 2.15.0 and openai-codex 0.147.0. SDK contributors can install the checkout with uv pip install ./packages/virgo-observe-python.

Four operations

Choose coverage in Virgo's “Trace with Virgo-Observe” setup and run its bootstrap command. register() finds .virgo/observe.env from the working directory or its parents, stopping at the current Git repository boundary. No application load_dotenv() call is needed. Deployed runtimes can supply settings directly:

export VIRGO_API_KEY='<observe-key>'

Bootstrap saves the endpoint with the key. Saved settings are read only during registration, do not mutate os.environ, and never evaluate shell expressions or expand variable references. Only recognized Observe/OTel settings are read. The file must be a regular, owner-only file on POSIX; symlinks and duplicate settings are rejected. Explicit or process credentials select process/argument configuration without reading the saved file. Other process settings override saved values. The default endpoint is hosted Virgo; endpoint= and VIRGO_ENDPOINT support custom deployments.

Without a key, register() returns a client with enabled=False and registration_report.reason_code == "missing_api_key". It installs no framework instrumentation, starts no delivery workers and exports nothing. Manual spans are non-recording; feedback/metric calls return dropped receipts with instrumentation_disabled. Applications need no if VIRGO_API_KEY or None guards. Explicit blank keys and malformed configuration still raise validation errors. trace_export="existing" retains its credential-free behavior.

Reuse your application's existing configuration without adding an environment variable:

virgo = register(project_name="support-agent", environment=settings.environment)
# Or reuse your existing tracer provider's public resource:
virgo = register(project_name="support-agent", tracer_provider=provider)
# An SDK provider already installed globally is reused automatically:
virgo = register(project_name="support-agent")

Resolution uses the first configured label, in this order:

  1. VIRGO_ENVIRONMENT override.
  2. Explicit environment=... from application configuration.
  3. The supplied or globally registered SDK tracer provider's resource.
  4. OTEL_RESOURCE_ATTRIBUTES.
  5. APP_ENV, VERCEL_TARGET_ENV, then VERCEL_ENV.
  6. NODE_ENV only when it is development or test.
  7. unspecified when no deployment label is available.

Resource lookup prefers deployment.environment.name, then deployment.environment, then platform.environment. Custom labels and case are preserved; resource attribute values in the environment variable are percent-decoded. Blank variables fall through; the selected label must contain 1–80 Unicode characters without control/non-printable characters. An invalid override fails validation instead of silently using a lower-priority label. NODE_ENV=production describes build mode, so it does not prove a production deployment. CI flags and cloud host markers do not classify environments.

Set one override before starting the process, even when application code already specifies an environment:

export VIRGO_ENVIRONMENT=local
# Or VIRGO_ENVIRONMENT=prod for production, or VIRGO_ENVIRONMENT=evals for evaluation runs.

The label is resolved once at registration for traces, feedback, and metrics. local, prod, and evals stay exactly as supplied; custom labels remain valid. Evaluation runs can also use environment="evals" in their runner configuration. CI or NODE_ENV=test alone does not imply an evaluation run. prod and production remain distinct scopes, so keep your existing label when upgrading.

The same Observe key can send multiple environments to one workspace. The hosted Virgo endpoint does not identify where your agent runs. Use the Traces environment filter to inspect deployments separately, and Columns → Environment to show their labels in the table.

Upgrading: deployments that previously relied on the implicit production default must set or supply a production label to retain that scope. Historical traces are not relabeled. Keep delayed feedback and metric producers on the same environment as the execution they refer to.

from decimal import Decimal
from virgo_observe import MetricSubject, VirgoSubject, VirgoVersions, register

virgo = register(project_name="support-agent", product=True, metrics=True, release="release-7")

with virgo.agent_run(
    "support.resolve_ticket",
    run_ref="run-opaque-123",
    subject=VirgoSubject(account_ref="account-opaque-123"),
    versions=VirgoVersions(agent="agent-v4", prompt="prompt-v7"),
):
    # Run your agent here. Selected supported integrations emit child spans.
    with virgo.span("retrieval.context_pack", kind="RETRIEVER"):
        pass

    saved_execution = virgo.current_trace_ref()
    completed = virgo.metric(
        "resolved_ticket_value",
        observation_id="ticket-123-value",
        value=Decimal("12.34"),
        unit="USD",
        definition_version="resolved-ticket-v1",
        subject=MetricSubject("account", "account-opaque-123"),
        lineage={"producer": "ticket-service"},
    )

# Feedback may arrive later. Persist saved_execution with your own run record
# when the response/callback crosses a process boundary.
feedback = virgo.feedback(
    feedback_id="ticket-123-rating",
    trace=saved_execution,
    rating="down",
    kind="correction",
    correction="The answer should use the selected workspace.",
)

report = virgo.flush_report(timeout_seconds=5)
# Inspect report.feedback, report.metrics, and each receipt.status.

A saved TraceRef contains an external nonzero 32-character lowercase W3C trace ID and/or your opaque run reference, never a Virgo-internal ptr_… ID. An explicit reference wins over the active execution. Feedback requires one; metrics may remain deliberately unlinked. Subject references are opaque application IDs, not pre-hashed Virgo pseudonyms.

Feedback metadata accepts only environment, workflow, release, model_version, configuration_id, and provenance. Values must be non-null strings, booleans, or finite numbers. Omit missing values and keep arbitrary event fields in the application's own record. For feedback actually generated by a simulated user, use metadata={"provenance": "synthetic_feedback"}.

span() returns a native OpenTelemetry Span. kind is an optional AI role such as AGENT, LLM, or TOOL; otel_kind=SpanKind.CLIENT independently preserves native transport semantics. Generic spans are not inferred to be tools from parentage. agent_run(), get_tracer(), flush(), and instrumented_frameworks remain supported. Typed identity, run, release, and version arguments own their reserved attribute keys.

Point observations and real outcome windows

A metric without window is one observed event: it requires a non-null boolean/numeric value, revision 1, and no supersession. Its occurrence is captured once when called, or set explicitly with an aware occurred_at. It does not fabricate a time window or interpret False as a mature failure. Use an event KPI definition to aggregate these observations; precomputed custom KPI definitions consume windowed measurements only.

For a completed or censored outcome window, supply MetricWindow(start, end, mature_at) using timezone-aware datetimes. The order is start < end <= mature_at. An observed window must already be mature; occurred_at, if supplied, must equal its end. Supported statuses are observed, immature, proxy, right_censored, not_achieved, and reversed. Immature/right-censored values are null.

value accepts bool, int, finite float, finite bounded Decimal, or None where the status permits it. Decimal is serialized as exact decimal text, not a float. Arbitrary categorical strings are rejected. Subjects have exactly one grain: account, user, journey, conversation, session, or aggregate (without a ref). Approved lineage keys are source, source_version, definition_hash, export_id, and producer.

Corrections retain the logical observation_id, increment revision, and set supersedes_observation_id. Every revision gets a distinct stable HTTP idempotency key. Retrying an unchanged revision is a duplicate; changing its semantic value, timestamp, lineage, subject, release, versions, or execution claim is a conflict. New revisions never edit the previous record.

Privacy and integration ownership

Full content is the default: prompts, responses, tool inputs/outputs, and retrieval content. Observe onboarding also configures the server source for full content. Explicit capture_content=False remains available when an application intentionally needs metadata-only export. When the argument is omitted, VIRGO_CAPTURE_CONTENT=true|false can override the default. Explicit arguments win; the server's trace-source policy remains authoritative.

In explicit metadata-only mode, the exporter filters its own representation: unapproved attributes, events (including exception content), status descriptions, link attributes, and resource/scope attributes are removed. It does not mutate spans delivered to another exporter. Operational names and approved opaque IDs remain; do not put prompts, personal data, secrets, or arbitrary content in those fields. This trace setting does not erase explicitly submitted feedback text, which follows the feedback source's policy (full content for Observe onboarding).

Explicit metadata-only export retains vcs.ref.head.revision and platform.commit.sha only as strings of exactly 40 hexadecimal characters. Set the emitter commit on the OpenTelemetry Resource and provide platform.release.id (for example, via release=) for canonical trace source provenance. Span-only commit attributes do not establish that provenance. Other source-control fields and arbitrary evaluator or deployment metadata remain filtered. This does not reconstruct historical provenance.

product=True and metrics=True independently enable publication using the same key. Their default URLs use the trace endpoint's origin; the backend resolves the workspace from the key. Disabled channels are not configured. Ordinary legacy trace keys do not gain publication access: enable coverage through Observe setup. Rotating or revoking its trace-source key affects all selected channels. Existing explicit feedback/outcome tokens remain supported for older integrations; a shared key is never forwarded to a different origin.

Register before importing functions by value (such as from litellm import completion) and before constructing instrumented clients. Existing local aliases do not change when a framework module is instrumented. Install only the extras matching the application's actual frameworks and standalone provider calls. Omitting instrumentors discovers all installed supported integrations; an explicit list can contain multiple names in any order. Keep existing framework pins and resolve these extras through the application's existing lock.

FastMCP 3.x and 4.x use an instance middleware instead of the instrumentors selection. Full request and response content is enabled by default; credential, authorization, cookie, token, password, and _meta values are always excluded from the captured copy:

from fastmcp import FastMCP
from virgo_observe import register

virgo = register(project_name="customer-tools")
mcp = FastMCP("Customer tools")
virgo.instrument_fastmcp(mcp)

The adapter traces every MCP request and classifies tools/call, prompts/get, and resources/read as tool, prompt, and retrieval operations. Do not also pass fastmcp in instrumentors; FastMCP needs the concrete server instance. The older bundled mcp.server.fastmcp import is not part of this certified range. Stable transport session IDs are preserved when FastMCP provides one. FastMCP 4's modern protocol is sessionless, so Virgo keeps request correlation without fabricating a cross-request session.

Application path Adapter install for 0.7.0 Optional instrumentors selection
Codex SDK openai-codex==0.147.0 virgo-observe[codex]==0.7.0 ["codex"]
Vercel Python ai==0.5.2 (Python 3.12+) virgo-observe[vercel-python]==0.7.0 ["vercel_python"]
FastMCP 3.x/4.x virgo-observe[fastmcp]==0.7.0 virgo.instrument_fastmcp(mcp)
AutoGen AgentChat virgo-observe[autogen]==0.7.0 ["autogen"]
CrewAI virgo-observe[crewai]==0.7.0 ["crewai"]
LiteLLM virgo-observe[litellm]==0.7.0 ["litellm"]
LlamaIndex virgo-observe[llama-index]==0.7.0 ["llama_index"]
Agno virgo-observe[agno]==0.7.0 ["agno"]
LangGraph virgo-observe[langgraph]==0.7.0 ["langgraph"]
DSPy virgo-observe[dspy]==0.7.0 ["dspy"]
OpenAI Agents SDK virgo-observe[openai-agents]==0.7.0 ["openai_agents"]
Pydantic AI virgo-observe[pydantic-ai]==0.7.0 ["pydantic_ai"]
LangChain virgo-observe[langchain]==0.7.0 ["langchain"]
OpenAI SDK virgo-observe[openai]==0.7.0 ["openai"]
Anthropic SDK virgo-observe[anthropic]==0.7.0 ["anthropic"]

Codex and multiple frameworks

from virgo_observe import register
register(project_name="platform")

This single startup call activates installed Pydantic AI, Codex, and the certified OpenInference OpenAI adapter. An optional selection is instrumentors=["pydantic_ai", "codex", "openai"]. Codex is openai-codex==0.147.0, not OpenAI Agents SDK or Pi. The codex extra pins that tested event contract. One startup source location must execute in every actual API/worker process; a local call does not configure another deployment.

Observe watches the existing sync SDK request boundary (also used by AsyncCodex) and typed app-server notifications without consuming the application's stream. It preserves SDK return values, errors, subprocess isolation, credentials, Codex configuration, and existing native OTel exporters. Reader-thread notifications use the captured Python parent context and router/thread/turn IDs. Shutdown ends remaining observation spans without waiting for model work or closing the SDK. No manual roots, tool decorators, exporters, or subprocess telemetry settings are required in the application.

Captured evidence includes turn input/final output, explicitly supplied thread instructions, model identity, reported usage, tool item IDs, inputs/results, command output and exit codes, errors, and interruption/cancellation evidence. Native timestamps/durations are recorded when supplied; OTel span timing measures SDK observation. Cumulative thread usage becomes a turn delta only with an observed baseline; resumed/attached unknown baselines remain labeled thread cumulative. Waiter cancellation does not prove the subprocess was canceled.

Evidence boundaries are explicit on platform.codex.* attributes:

  • Exact provider requests/responses and individual model-request spans are unavailable from the turn event protocol. No synthetic LLM spans are created.
  • Parentage is captured at the Python SDK boundary; the adapter does not inject W3C context into Codex's subprocess or independent MCP servers. Existing native Codex OTel exports continue separately and are not claimed as joined.
  • A Codex item ID is the tool correlation ID. A distinct provider call ID, hidden runtime instructions, resumed history, tool internals, and file-change result text may be unavailable. Missing evidence is flagged, not fabricated.
  • Content is limited to 65,536 characters per field/terminal buffer and flagged when truncated. Existing OTel event/attribute limits still apply. Known secret keys are redacted from structured content; do not send credentials in prompts, terminal output, or free-text tool results. Metadata-only mode omits content.
  • Goal-generated turns without an observed SDK turn/start and other SDK versions are not covered. Verify every exercised execution family separately.

See verification and remaining gaps.

Vercel Python

from virgo_observe import register

virgo = register(project_name="ember", instrumentors=["vercel_python"])

Register once during normal process startup, before executing the agent. Normal Python exit flushes automatically. The integration configures Vercel's native experimental OpenTelemetry adapter with Virgo's provider and content policy. Existing Agent.run and SDK tool execution produce their own agent/model/tool spans; no manual root, tool wrapper, or per-call telemetry flag is needed. Model messages, system instructions, usage, tool arguments/results and handled errors are captured. Tool content retains its GenAI fields and is also mapped to the receiver's input/output fields. capture_content=False keeps metadata only.

The extra pins ai[otel]==0.5.2; keep the application's existing model-provider extra/configuration (for example, ai[openai]). Only this ai version is certified because its telemetry API is experimental. This is Python ai, not the Node Eve integration. Plain ai.stream provides model coverage; it does not invent an Agent span or observe tools executed outside the SDK. Temporal and serialized cross-process Vercel span restoration are not certified by this path.

An already-active external provider wrapper blocks Vercel activation with overlapping_model_instrumentation; preserve its ownership and inspect the report. When native Vercel is selected, additional provider/gateway adapters report the same overlap reason and are not activated: ai 0.5.2 model spans are not the ambient parent, so per-call suppression cannot safely identify those duplicates. Native Vercel agent/model/tool coverage remains active; this optional standalone provider gap must not block harness onboarding. Existing native Vercel OTel adapters are preserved and reported already_active_unverified, without adding another one. Other existing exporters on the shared provider continue receiving spans. Inspect registration_report for these cases.

Install virgo-observe[vercel-python]==0.7.0 from PyPI. See the live example and release verification.

Semantic Kernel 1.44.1 uses its native OpenTelemetry spans, so it needs no adapter extra. Set SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE=true before importing Semantic Kernel, install base virgo-observe==0.7.0, and use instrumentors=["semantic_kernel"]. Semantic Kernel's native tracer resolves through the global SDK TracerProvider; pass that same provider explicitly to register(). Virgo bridges the opted-in prompt/response log events onto the native model span so its trace exporter applies the same content policy.

Installing an arbitrary OpenInference entry point is not a support guarantee. Use auto_instrument=False for manual tracing.

Automatic selection activates framework, then gateway, then provider layers. With Pydantic AI, provider and gateway tracers suppress spans when the current native model span already owns that call. Pydantic/OpenAI concurrent requests, streaming, standalone Responses and embeddings, and provider calls inside tools are tested independently. Pydantic AI and Codex no longer disable standalone provider instrumentation across the registration. Other frameworks retain their existing provider/gateway overlap guards until per-call suppression is certified; registration diagnostics identify these optional provider gaps. Harness onboarding must continue without requiring standalone AI coverage. Existing external instrumentation is never reconfigured and is reported already_active_unverified, not healthy by inference.

Virgo-owned providers retain all span attributes by default so long message and tool histories do not evict the model identity or early prompts. Explicit OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT / OTEL_ATTRIBUTE_COUNT_LIMIT settings and application-owned provider limits remain authoritative. Exported spans preserve OpenTelemetry dropped-attribute, event, and link counters when upstream limits truncate data; privacy filtering is not counted as upstream data loss.

Inspect virgo.registration_report for each integration's distribution version, status, ownership, and safe reason code. Discovery/activation is not proof of server delivery. Native automatic metadata-only instrumentation requires patched Pydantic AI 2.27.1+; earlier versions are skipped because retry content can leak through their native instrumentation.

Each known integration report now includes compatibility: the package whose version gate is being checked (the OpenInference adapter for adapter gates), its installed version, supported range, blocked capability, and exact candidate commands for pip, uv, and Poetry. The standalone assess_integration_compatibility(name, installed_version, capture_content=...) also returns this information without importing or patching a framework. Missing version evidence remains unknown. Unsupported integrations do not prevent independent supported integrations from activating.

OpenInference reports also expose framework_dependencies: each upstream instrumentor requirement beside the actual installed framework version (or None when missing). On a dependency conflict, use these requirements to assess the framework change; reinstalling an already-certified adapter is insufficient.

Candidate upgrades remain unknown and are never applied by the SDK. The coding host must inspect the application's manifest, resolved lock, upstream framework and adapter requirements, extras and companion pins, release/migration notes, and affected call sites. It must run focused behavior checks in a disposable environment before calling an exact application upgrade verified-compatible. Known API/configuration changes are migration-required; installation success or a supported version number is insufficient. For pip requirements projects, update the existing requirements/constraints and regenerate the existing lock after upgrade approval. Preserve dependency groups and coordinate pydantic-ai with pydantic-ai-slim when both are present.

The reproducible integration matrix uses real SDKs and local fake responses, including model streaming and native tool/validator retries:

Layer Tested minimum Tested selected current
Vercel Python ai==0.5.2, OpenAI 2.34.0 ai==0.5.2, OpenAI 3.7.0
OpenTelemetry SDK/exporter 1.42.0 1.44.0 (CrewAI: 1.42.0)
Pydantic AI slim 2.27.1 2.37.0
OpenAI SDK (OI adapter 0.1.57) 1.69.0 3.7.0
Anthropic SDK (OI adapter 2.1.1) 1.0.0 1.3.0
LangChain Core (OI adapter 0.1.73) 0.3.50 1.6.1
LangChain OpenAI 0.3.12 1.6.0
AutoGen AgentChat (OI adapter 0.1.14) 0.7.5
CrewAI (OI adapter 1.1.15) 1.15.18
LiteLLM (OI adapter 0.1.40) 1.99.0
LlamaIndex Core (OI adapter 4.4.8) 0.14.24
Agno (OI adapter 1.0.6) 3.0.5
LangGraph (LangChain OI adapter 0.1.73) 1.2.11
DSPy (OI adapter 0.1.42) 3.3.1
OpenAI Agents SDK (OI adapter 2.2.0) 0.22.0
Semantic Kernel native OTel 1.44.1

Other versions are not individually certified. Install optional integrations alongside the application's existing dependencies; do not upgrade an application merely to silence an unsupported registration report.

Providers, configuration, and lifetime

register() uses an explicitly supplied SDK provider, then an existing global SDK provider, or otherwise a private provider. It never replaces the global provider. Compatible registrations share one export stream and sender with reference-counted lifetime; conflicting registrations on that provider fail. Closing one handle does not shut down another handle or the customer's provider. Final shutdown releases Virgo-owned framework wrappers only while their ownership still matches; externally installed or replaced wrappers are left untouched.

In pre-fork servers, create the provider and call register() inside each worker after it starts. Do not share a live Virgo handle or delivery receipt across a fork. Inherited handles reject operations instead of using stale threads/locks. Normal Python exit automatically drains traces, feedback and metrics, with one five-second total deadline across active registrations. This includes ordinary script completion and uncaught Python exceptions. The SDK starts its lifecycle workers during registration, so exit cleanup never needs to start new threads. Explicit shutdown() and context-manager cleanup remain supported and do not duplicate exports. Existing application-owned providers are not shut down.

Use explicit flush_report() before a serverless runtime freezes, or shutdown() in an application's existing graceful-stop lifecycle when it does not reach normal interpreter exit. SIGKILL, os._exit() and crashes cannot run exit hooks. Process exit is not a remote delivery receipt.

trace_export="existing" requires an existing SDK provider, needs no Virgo trace key, and attaches no Virgo exporter. The application's exporter and privacy policy own that path; Virgo's export-local content filter does not apply to it. The independent feedback/metric channels still work.

When those channels use an Observe key, including one supplied through explicit channel token arguments or environment variables, an existing exporter must carry the environment contract on every span's resource, including children exported before their root. Configure it before creating the provider:

from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider

provider = TracerProvider(resource=Resource.create({
    "deployment.environment.name": "local",
    "platform.observe.environment_contract": "observe-runtime-environment-v1",
}))
# Attach your existing exporter to this provider before registration.
virgo = register(
    project_name="support-agent",
    tracer_provider=provider,
    trace_export="existing",
    environment="local",
    product=True,
    metrics=True,
)

Registration rejects a missing contract or mismatched environment before starting delivery. It never mutates the existing provider or another exporter's resources. Trace-only existing-export registrations keep their previous behavior.

Explicit arguments take precedence over the channel environment variables. Trace compatibility also accepts OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_HEADERS/OTEL_EXPORTER_OTLP_HEADERS, and OTEL_SERVICE_NAME. VIRGO_ENDPOINT, VIRGO_ENVIRONMENT, and VIRGO_RELEASE override hosted defaults. The project display name is never used to guess a workspace publication URL. Missing channels are permitted at registration, but publishing to one raises a configuration error.

Each record channel has its own finite in-memory queue and worker (default 512 pending events each). Payloads, occurrence times, IDs, and operational W3C headers are captured before enqueueing. Network calls suppress recursive HTTP instrumentation. At most three attempts retry transport errors, 408, 429, and 5xx responses with bounded jitter/backoff and Retry-After. Other HTTP failures are terminal; redirects never forward credentials.

Receipts expose queued, accepted, rejected, conflict, failed, or dropped states. Queue overflow is visible as dropped, not silently successful. A 202 means accepted at ingress, not normalized, linked, or successfully analyzed. flush_report() reports cumulative failures and pending records; flush() is its boolean compatibility view. For Virgo-owned trace export, traces_flushed requires both a drained processor and successful exporter results. A rejected export remains a failure for that registration: a later empty queue cannot recover missing spans. Existing-provider mode reports the external provider's force-flush result only.

Default trace exports use gzip and size-aware batches with a 3.5 MB protobuf target. Content is never truncated to meet that target; an individual large span is sent intact and must fit the receiver's HTTP budgets (4 MB encoded / 8 MB decoded). Source/framework limits explicitly configured by the application still apply. Inspect platform.observe.delivery.events for channel traces and trace_export_failed warnings when delivery fails.

Flush and shutdown share a total caller deadline across channels. An exporter or in-flight HTTP call can finish after the caller's deadline; Python cannot safely cancel arbitrary third-party I/O. Shutdown marks undelivered receipts failed and closes owned resources. This queue is not crash-durable: persist important application events in your own outbox and reuse their IDs when retrying after a process restart. Explicit shutdown remains available for application-managed teardown; ordinary scripts use automatic exit cleanup.

Server contract and verification

Point metrics, explicit observation/release/version fields, and durable privacy-aware correlations require the accompanying Platform server changes and forward migration 0197. Upgrade via platform-migrate; never use an SDK client-side fallback against an older window-only endpoint.

Exact links require the same tenant, workspace, environment, and permitted pseudonym scope. Multiple candidates and contradictory references abstain. The Observe key selects the workspace; environment identifies the deployment within it and resolves as described above. Version 0.6.2 requires the accompanying server environment support. Deploy that server before upgrading the SDK. SDK 0.6.2 declares platform.observe.environment_contract=observe-runtime-environment-v1 on exported resources. Only Observe traces with that exact contract use their runtime environment; legacy Observe exports and payloads without an environment retain their shared source/workspace default. This keeps older clients' links working during an API-first rollout. Generic OTLP sources retain their existing resource-environment behavior. The API accepts metadata.environment on feedback and top-level environment on metrics. Observe keys permit these deployment labels within their workspace; legacy channel credentials require the workspace environment. Labels must be nonblank strings of at most 80 characters. Normal Unicode labels are preserved; control, format, private-use, unassigned, and surrogate characters are rejected before export or ingestion because they cannot identify a correlation scope. Late links live in a separate projection, not edits to immutable outcome rows. Pending claims receive bounded retries and a final expiry check; missing or sampled-out traces do not prevent observation acceptance.

From the Platform repository root:

uv run ruff format packages/virgo-observe-python
uv run ruff check packages/virgo-observe-python
uv run mypy packages/virgo-observe-python/src
uv run pytest packages/virgo-observe-python/tests
uv run python packages/virgo-observe-python/scripts/check_framework_matrix.py
uv build packages/virgo-observe-python
uv run python scripts/verify_virgo_observe_distribution.py

See docs/virgo/instrumentation/python.md, docs/observability.md, and docs/virgo/instrumentation/python-release.md for server inspection and the separately authorized publication procedure.

License

The virgo-observe Python SDK is licensed under the Apache License, Version 2.0. The full license is included in this package's LICENSE file and its wheel and source distributions.

This license applies only to packages/virgo-observe-python within the Platform repository. It does not license the rest of the Platform repository or Virgo's hosted services. Third-party dependencies retain their own licenses.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

virgo_observe-0.7.0.tar.gz (116.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

virgo_observe-0.7.0-py3-none-any.whl (72.4 kB view details)

Uploaded Python 3

File details

Details for the file virgo_observe-0.7.0.tar.gz.

File metadata

  • Download URL: virgo_observe-0.7.0.tar.gz
  • Upload date:
  • Size: 116.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for virgo_observe-0.7.0.tar.gz
Algorithm Hash digest
SHA256 7132c4f395b0fd03a4c7b09818e71ac45423ea49c7df5552e89da20b03c76fe2
MD5 1cdc36b9fb9085347d139f89119abeb6
BLAKE2b-256 70333015dea3c0885c48a45074b2b4062f2b7f72c46151bf8d270b81622d8645

See more details on using hashes here.

File details

Details for the file virgo_observe-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: virgo_observe-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 72.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for virgo_observe-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6ad9a5f4e8a5e02ac3a14b942bc4bd41bfb580da2a2bc2adade29e5029a73dc8
MD5 afdb41907668ac9c76745ef87ef42d01
BLAKE2b-256 b5def1685cd8f97398df4a517f916ec5d1f13e3e6dabb7ca080507ab98c3f723

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page