Skip to main content
This reference covers hue-run 0.15.0 on Python 3.10 or later, tested on 3.10 and 3.14 with OpenTelemetry 1.45.1 and on 3.10 and 3.12 with OpenTelemetry 1.40.0; the accepted range is >=1.40,<2. Start with the Python guide for installation and a runnable trace, and compatibility for supported runtimes and instrumentation. Use Quickstart for the available package release.

Imports

The SDK sends OpenTelemetry traces and correlated logs. Your application remains responsible for provider calls and the instrumentation that observes them. The tracing core depends only on the OpenTelemetry packages and requests.

Create a tracing client

Use the api_key= keyword when omitting the origin. The first positional parameter is base_url, so Hue("<key>") raises TypeError naming api_key=; existing Hue(base_url, api_key, ...) calls are unchanged. When enabled, the key is required and validated even though the signature permits None. Disabled clients do not require a key. The constructor does not load environment variables or an environment file automatically. Invalid options raise TypeError or ValueError. With a borrowed tracer or logger provider, your application owns that provider’s resource and other processors, and the provider Hue creates for the other signal reuses the borrowed provider’s resource, so spans and correlated logs report one service.name. Borrowed providers are not shut down by the client. Use one Hue instance for its provider lifecycle; OpenTelemetry has no public processor-removal API. See existing OpenTelemetry.

Spans and context

Use with for the context managers below. They are ordinary synchronous context managers that may surround work inside an async function.
endpoint takes the exported ToolEndpoint typed dictionary. Required fields are url: str and source: Literal["request", "client_config", "receipt"]. Optional fields are method: str and capture_query_parameters: list[str]. The URL must be the actual HTTP(S) endpoint used by the tool. With content capture enabled, Hue records it through the configured redactor, removing credentials, fragments and query parameters unless their non-secret names are allowlisted. The optional method has no default. This records application-supplied routing evidence without making a request or inferring a URL from labels. An exception escaping a Hue span records error type/status, then propagates unchanged. Python helpers always omit exception messages and stacks, including when capture is enabled. Initialize the client once, keep spans open until their work ends, and shut down when the process stops.

HueSpan

Attachment(data=None, *, path=None, content_type, name=None) from hue_sdk places a file in any value Hue records: a span() input or output, model() messages, a tool’s arguments or result, log_inference() messages, or a span attribute passed to span(attributes=...) or set_attribute. Give exactly one of data (bytes, or a base64 string or data: URL, up to 25 MiB) and path (a regular file up to 1 GB; over 25 MiB it is hashed when the attachment is created and streamed from disk when it uploads, only if it still has its recorded size and SHA-256). It is recorded as a GenAI blob part in digest form and its bytes upload after its record is sent; an invalid attachment is recorded as None and counted. See Attach a file anywhere. Choose logs or span attributes for the same content event to avoid duplicate storage. log_inference emits no record when content capture is disabled. hue.tracer, hue.tracer_provider and hue.logger_provider expose the configured OpenTelemetry objects for integrations that accept explicit instances.

Content policy

See Data privacy for runnable email-masking examples and the correct attachment point for each integration. capture_content=False omits input/output content from Hue’s helpers before it enters an OpenTelemetry queue and, at export, strips recognized GenAI, OpenInference, OpenLLMetry, Langfuse and Vercel AI SDK content attributes, legacy gen_ai.* message events, log bodies and status descriptions from every record on Hue’s export path, including spans from third-party instrumentors on a borrowed provider. The key list is identical to TypeScript’s contentPrefixes and is reproduced in the compatibility matrix. True permits that content. The policy does not classify arbitrary attribute names, span names, session identifiers or another exporter’s records; unrecognized custom keys pass through. Configure an external instrumentor’s own content policy before enabling it. When content is captured, export scrubs hosted-tool credentials (such as authorization, authorization_token, headers and api_key) in recorded tool definitions and raw requests. A span’s own string attributes over Hue’s inline limit upload separately, up to 1,000,000,000 bytes, and keep a 16 KiB prefix. Captured HTTP bodies follow the HTTP capture limit instead. Inline media in the span attributes and log records that automatic capture reads uploads and leaves its digest in place; text media over 64 KiB keeps a 16 KiB UTF-8 prefix. Resources, links and span events never upload: inline media there up to 64 KiB stays as recorded and larger media becomes its digest. An Attachment (up to 25 MiB) uploads at its position, and record_file uploads supplied data up to 25 MiB only with upload=True. Uploads run in the background after their record is sent. A value refused when its record is exported falls back to a cut, to the digest without a hue.blobs entry in recorded messages, or to the inline bytes elsewhere; one whose upload fails afterwards keeps its prefix or digest and its entry. Both count in export_status.upload_fallbacks. Nothing uploads with capture_content=False or a setup credential. When metadata-only capture removes tool definitions, the record keeps hue.tool.names and hue.tool.definitions.sha256. redactor(field, value) receives a bounded, detached content snapshot before helper JSON serialization. Supported inputs are ordinary built-in JSON-compatible scalars, dictionaries and lists, plus built-in tuples and scalar dictionary keys accepted by Python’s JSON encoder. Container shape and nested values are preserved without sharing mutable application containers. When uploads are available, helper snapshots and redactors accept supported values up to 1 GB and 1,048,576 visited values and keys. Otherwise, the snapshot is bounded to 4 MiB, depth 64 and 65,536 values and keys. The budget counts UTF-8 string bytes plus value overhead; it is not a process-memory limit. The initial snapshot also runs when no redactor is configured. A redactor’s returned value passes through a fresh snapshot with the same bounds before JSON encoding. For supported HTTP CLIENT spans, redactor also handles URL identity in Hue’s export copy, including metadata-only capture and spans from other instrumentation. Valid full URLs use url.full and any present http.url callback. Present http.target and url.path callbacks receive the pathname. Hue sanitizes callback results and omits URI attributes if a result fails or is invalid. Other exporters keep their original records. A snapshot, redaction or serialization failure omits that field and increments export_status.instrumentation_failures without raising into application work. A redactor may mutate its copy without changing application inputs or results, but must not mutate globals or objects obtained through captured references. When uploads are unavailable, fields over Hue’s inline value limit are cut to a UTF-8 prefix and listed under hue.truncated. JSON None, False, 0 and "" remain distinct from omitted content. Received content is stored by Hue; the SDK does not set a retention timer.

Delivery and shutdown

validate_project() returns a frozen Project with id, name, slug and organization_id. Authentication, connection or invalid-response failures raise ProjectValidationError; the exception does not contain the key. Validation sends no trace. force_flush() sends traces and logs, then waits within the same deadline for pending uploads. It returns False on timeout, a processor failure, a closed client, or any recorded failed export batch, dropped record or instrumentation failure during this client’s lifetime. Inspect export_status.failed_trace_batches, failed_log_batches, uploaded_values, upload_fallbacks and ok; upload fallbacks are warnings and do not make a flush fail. A flush timeout bounds how long the caller waits; it does not cancel network work already running in the background. Timeout values must be positive integers. Queues are bounded and in memory; termination or overflow can lose telemetry. A successful flush does not prove that every operation was instrumented or that all parents have arrived. shutdown() stops new helpers, drains and closes Hue-owned resources, then gives pending uploads up to 30 seconds more and abandons the rest, counted in upload_fallbacks. Borrowed tracer and logger providers and their other processors remain usable. A timeout returns False while shutdown continues; repeated calls wait for the same shutdown work. A with Hue(...) as hue: block calls shutdown_safe(timeout_millis=1000) on exit, but does not raise if that boolean is false. Use a checked flush when command success must require delivery:
Exports use the official OTLP HTTP/protobuf exporters and their retry policy. Request bodies are gzip-compressed and carry a hue-sdk-python/<version> User-Agent ahead of the exporter’s own token. HTTP errors, malformed acknowledgements and OTLP partial rejections count as failed batches. Partial rejections are not resent as a whole batch. Stop producing spans before shutdown; shared server clients should remain alive between requests.

Live spans

OpenTelemetry exports a span only when it ends, so a long agent turn or model call would otherwise stay invisible until it finishes. When a Hue helper span or an AI span is still open at the export worker’s next 0.5 s tick, Hue queues a placeholder: a standard OTLP span whose parent is the running span, with its name, kind, start time and current attributes and an end time of 0. Hue shows the span, and its trace, as running and replaces the placeholder when the finished span arrives. Input set right after entering, such as set_input, is included. A placeholder whose span ends before it is exported is not sent. A placeholder usually reaches Hue about 1.5 s after its span starts: up to 0.5 s until the next tick, then about 1 s while the export worker batches it. It arrives sooner when a batch is already scheduled and later while an earlier export is still in flight, because the worker runs the next tick and starts the next 1 s batch only after that export returns. A span shorter than about 1.5 s therefore usually never shows as running and appears only when it ends.
  • Only spans from hue.tracer (every helper) and spans with a gen_ai., ai., llm. or traceloop. attribute at start, or a name starting with ai., are announced. HTTP, database and other framework spans are not.
  • Placeholders follow the same capture_content policy as finished spans. Tool definitions, system instructions and any value over 64 KiB are left out; the finished span still carries them.
  • Placeholders carry the running span’s name and attributes as set when the export worker builds them, so a value you overwrite before the span ends can still reach Hue. capture_content=False strips recognized content keys from them, and redactor rewrites helper content before the helper sets it on the span. Scrub any other sensitive attribute where you record it, or pass live_spans=False.
  • Placeholders are advisory. A placeholder is queued only while the queue is under a quarter of its record and byte budgets and is skipped silently otherwise. While queued they count in queued_trace_records and queued_trace_bytes, but never as dropped or failed telemetry.
  • Export hands placeholders to a separate delivery slot, which holds at most 64 placeholders and 1 MiB outside the queue counters and sends one request at a time. Export skips placeholders while the slot is busy. force_flush() and shutdown() never wait for it, so a slow placeholder request cannot delay completed spans, and a successful flush does not confirm that a span showed as running.
  • Completed spans are exported in separate requests before placeholders, so their rejections stay visible. If the first trace acknowledgement lacks Hue-Pending-Spans: 1, the SDK sets export_status.live_spans_rejected, a warning that does not affect ok, and stops announcing spans; the receiver gets at most one placeholder request.
  • Pass live_spans=False to send none.
  • The SDK registers its span processor on the tracer provider itself and exports no processor to wrap. A provider that wraps it anyway never sees placeholders, so Hue still receives the running span’s name and attributes even when the wrapper later drops or edits the span; such a wrapper should forward on_end for every span whose on_start it forwarded. A placeholder already sent for a span whose finished record never reaches Hue, for example because the span never ends, a wrapper withholds its end or the process exits before flushing it, leaves the span shown as running until Hue marks the trace stalled.

Trace verification

Returns a typed TraceVerificationResult with verified, receipt: TraceReceipt | None and project: Project | None, set when Hue reported the trace missing to name the project the key searched. A TraceReceipt has trace_id, span_count, revision, fields, matched_span_ids, missing_span_ids, and trace_url. fields is a TraceReceiptFields dataclass with input, output, model, usage and session booleans; it reports the presence of received fields without exposing their captured values. verified requires a stored receipt, every supplied expected span, and every required field. Timeout returns verified=False with the latest partial receipt, or None if none arrived; a None receipt with project means no trace with that ID exists in that project, so check which key the process loaded. Other failures raise exported TraceVerificationError, with code and optional status_code, without response bodies or credentials. expected_span_ids and required_fields accept sequences. required_fields takes TraceReceiptField names: "input", "output", "model", "usage" and "session". Trace IDs are 32 lowercase hexadecimal characters; expected span IDs are 16. All IDs must be nonzero. Supply at most 100 unique expected span IDs and unique required field names. The timeout defaults to 10,000 ms and must be positive, finite, and at most 60,000 ms. The receipt response is limited to 64 KiB. Missing spans or required fields keep polling until the deadline. Only recognized trace-not-found responses, HTTP 429, and HTTP 503 are retried; connection failures, unsupported endpoints, redirects, and malformed responses raise a safe typed error. Verification reads stored normalized field presence across the trace, including supported correlated logs. It does not inspect values or prove that unlisted application operations were instrumented. Flush the owning providers before verification; this method never flushes implicitly. An in-flight network read may finish in the background after the caller times out.

Evaluation client

EvaluationClient(base_url: str = "https://app.hue.run", api_key: str | None = None, *, timeout_seconds: float = 10, max_attempts: int = 4) requires a valid Read and write project service key. Use api_key= for Hue Cloud or retain EvaluationClient(base_url, api_key) for an explicit origin; a bare key in the first position raises TypeError naming api_key=. Timeouts must be positive and finite. Client methods are synchronous and return dictionaries. Arguments use snake_case; response fields and low-level completion payloads use HTTP camelCase. check_connection() returns the current project. List methods accept keyword-only after=None, limit=100; limits are 1–100. Responses contain items and nextCursor. list_eval_sets, list_evaluators, list_datasets and list_scorers also accept tags, which keeps items carrying any of the named tags. Evaluation responses are limited to 4 MiB. list_cases(version_id, ...) includes case content, so a valid row limit can still produce an oversized response when cases are large. Request a smaller page, such as limit=1, and pass each non-null nextCursor as after. The client does not automatically split or retry an oversized page.

Eval sets, evaluators, runs and scoring

Use these product-named methods in new code. They call the same v1 endpoints as the dataset, scorer, experiment and evaluation-run methods in the next sections, accept product-named arguments such as eval_set_version_id and evaluator_version_ids, and return dictionaries with product fields, such as evalSetId, evalSetVersionId, evaluatorVersionId, runId and scoringId, alongside the v1 fields. The earlier method names are deprecated but remain callable for at least two more 0.MINOR releases. A run ID and a scoring ID identify different records.

CI evaluation invocations

An invocation freezes the selected cases, evaluator versions, configuration and gate policy for one CI check. Use the CI runner for the complete execution and recovery flow. The same CLI can launch a Python agent; it ships in the TypeScript npm package. These low-level client methods require a Hue server with invocation support. Creation requires a key of 1–128 characters and deadline_at, an ISO 8601 timestamp with a timezone. Other keyword arguments are name, evaluator_ids, evaluator_version_ids, config, policy, ci and baseline_run_id. The policy dictionary carries absolute thresholds and optional baselineComparisons, each naming a pinned evaluator version and metric. The ci dictionary has provider: "github" or "local" and optional repository, commit and workflow identifiers. These nested dictionaries use camelCase keys. Use a stable key for each control operation. Retry with the original key and body, including the original deadline. Every method returns a dictionary with id, runId, runUrl, deadlineAt, state, manifest and receipt. The manifest holds the frozen inputs and their digest. receipt is None until the server records an authoritative decision; otherwise its verdict is pass, fail, incomplete, error or cancelled, with the original scoring pass, execution IDs, results and reasons. Read that saved verdict instead of deriving a new one from later scores.

Tags

Tags group eval sets, evaluators and runs, for example by the area of the agent they test. Methods take tag names: a name the project has no tag for creates one, and names match without case. create_eval_set, create_evaluator and create_run accept tags; update_eval_set, update_evaluator and update_run replace an item’s tags with the names you pass ([] clears them); list_eval_sets and list_evaluators keep items carrying any of the named tags; and list_tags() returns the project’s tags, each with id, name and color. Responses carry each item’s tags. A run also shows its eval set’s tags in evalSetTags; they are not its own, so update_run leaves them unchanged. The dataset, scorer and experiment methods take the same tags.

Datasets and scorer definitions

Use MISSING or omit expected to declare no reference. None is a present JSON-null reference. Freeze the dataset and publish scorer definitions before creating an experiment.

Scorer declarations and metrics

Scorer definition dictionaries use camelCase keys, even when supplied to a Python method. Import the built-in bundle as from hue_sdk.evals import builtin_scorers. builtins remains an alias, but it shadows the standard-library module of the same name in any file that imports it. builtin_scorers.json_schema needs the optional hue-run[evals] extra (jsonschema and referencing); without it the helper raises ImportError and stored schema scorers report SchemaValidatorUnavailable. Each metric definition has a name and type: boolean, text, number (optional min/max), or category (required categories, a list of strings). An optional description (1–500 characters) is shown with the metric’s check in Hue’s run view. Results must match the pinned definitions exactly. Hosted config requires model, provider, rubric, bindings (a list of dictionaries with name, path, required), maxOutputTokens and timeoutMs; temperature is optional. The declaration states the requested policy; the server validates supported values and project execution settings when it is used.

Experiments, saved subjects and results

complete_execution accepts a camelCase payload: required idempotencyKey and terminal state (succeeded, error or cancelled), with optional output, error, expectedTraceRevision, traceEvidence (required or omit) and omissionReason. It returns executionId, subjectId, traceSnapshotId and evaluationItemId. Each submitted result requires evaluationItemId, scorerVersionId and the Score fields described below; a local-code result also carries sourceDigest. A scored result has metrics entries with name, value and optional passed, plus a nonempty explanation or an evidence value. Error results contain error with type and optional message; skipped results contain an explanation. A read, an update that sets given fields (update_eval_set, update_evaluator, update_run and their dataset, scorer and experiment forms), or a mutation the server deduplicates by the idempotencyKey in its body, is sent again after a connection failure, a timeout or a 408 or 5xx without Retry-After, up to max_attempts (default 4, range 1–10) times with a jittered backoff; is_transient_api_error(error) names those failures. Any other mutation is sent once: preserve idempotency keys and returned IDs across retries after a lost response. HueApiError.status is the HTTP status when available, HueApiError.diagnostic Hue’s X-Hue-Diagnostic code when it sent one, and HueApiError.reason is malformed_response for a body the client refused; errors do not echo server bodies. The client rejects invalid JSON before writes, does not follow redirects, and limits request/response bodies to 1 MiB/4 MiB. Runner target outputs and built-in JSON Schema declarations are limited to 200,000 serialized bytes. JSON validation also enforces nesting depth 32 and 20,000 nodes; for an HTTP write, those structural limits apply to the complete request body. Values must use finite JSON numbers, valid Unicode without NUL, string dictionary keys, lists and dictionaries without cycles. Python integers outside -(2**53 - 1) through 2**53 - 1 are rejected; use strings for larger exact integers. The server can apply additional field-specific limits.

Hosted judge jobs

get_judge_budget() reads the hosted judge configuration and the organization’s monthly AI budget. Call create_judge_jobs(run_id, *, idempotency_key, jobs) with jobs entries containing evaluationItemId and scorerVersionId; the result contains ids. Inspect list_judge_jobs(run_id, ...) or get_judge_job(job_id), and request cancellation with cancel_judge_job(job_id, *, reason). Submitting hosted jobs is explicit and draws on that budget. Method availability does not establish that the project has a configured provider or that the budget has room. Local runners leave hosted and manual pins for their owning workflows.

Recorded media

client.media is a MediaClient that reads recorded files back by SHA-256 with a Read or Read and write key; a snapshot’s pinned copy needs Read and write. See Read recorded media back. The client also exposes the artifact methods that case files use: reserve_artifact, request_artifact_upload, upload_artifact_bytes, complete_artifact, get_artifact and download_artifact, which raises ArtifactSizeError for bytes past the size its caller expected.

Run locally and rescore

Both are exported from hue_sdk.evals and are synchronous entry points. They support sync or async target/scorer callbacks inside worker threads. From an async application, call the runner through asyncio.to_thread. Telemetry and evaluation clients must use the same project and origin. rescore requires an evaluation run created from saved subject IDs and has no target callback. RunnerReport exposes run_id, subject_ids, result_ids and deferred_scorer_version_ids. The native Python local runner downloads pinned input files but does not automatically upload files its target generates or provide a with_files result helper. For generated documents, use the shared CLI with a Python command, or the separate managed target adapter with ManagedOutputFile. Rescoring can read files already attached to saved subjects. Returning MISSING means unavailable output; returning None is JSON null. With persist_result_content=False, completions and local checkpoints omit raw output, target error messages, scorer evidence and arbitrary explanations. Typed metric values, including custom text values, remain stored. Existing dataset inputs/references are independent of this setting. Historical scoring skips unavailable output without invoking a scorer callback.

Local scorer exports

ScoreContext contains inputs, has_output, has_expected, optional output/expected, metadata, execution_state and, when the case or subject has files, files. A Score is scored with declared metrics and explanation/evidence, error with a typed error, or skipped with an explanation. A false quality verdict remains a scored result, with passed: False. The source digest binds an explicitly supplied source declaration to the local scorer; it does not attest closures or installed dependencies. Custom callbacks have no general execution timeout or side-effect cancellation. JSON Schema uses an isolated subprocess with a deadline and no remote schema fetches. Hosted pins require judge-job dispatch; score_locally does not run a hosted judge.

Recovery errors

Use one checkpoint directory per experiment or rescore run. Checkpoint files contain allowed result content and are private local files, not encrypted storage. Resume an upload failure with the same run, directory and options so saved payloads and idempotency keys are reused. After a process crash, confirm its recorded owner has stopped before removing .lock; removing the lock never authorizes another target invocation. For uncertain work, investigate side effects before starting another attempt. The low-level start_execution method requires the latest previous_execution_id for a replacement attempt and allow_uncertain_retry=True to replace a still-started attempt. Restarting a runner does not grant either permission or automatically adopt an externally created attempt. Use a new experiment for an intentional fresh target run after investigating. Required evidence waits for both signals after the root span ends. Omission is an explicit policy, never an automatic fallback after export failure. For a runnable example, see the public Local evaluations.

World client

hue_sdk.world.WorldClient uses the canonical World and instance routes; hue_sdk.environment.EnvironmentClient below keeps the original routes. Both require a Hue deployment serving their routes. create_instance accepts world_version_id where the compatible create_run accepts environment_version_id; get_instance and finish_instance read and finish that runtime instance. WorldInstance and WorldCoverage are canonical names for EnvironmentRun and EnvironmentCoverage. HueWorldError is the same class as HueEnvironmentError. WorldCreationError identifies a failed instance creation before the agent acts. WorldSealTimeoutError and the compatible EnvironmentSealTimeoutError identify a wait_for_seal timeout after the completion grace.

Reconstructed Worlds

hue_sdk.world.WorldModelClient reads the retained history of a WorldEntity, a dictionary with namespace and full id, scoped to the project key. A WorldModel records that identity, its committed evidenceCutoff and its status. WorldModelAccount describes one app account binding, including its full accountId, connection generation and optional scope; multiple accounts can belong to the same app. Results are typed dictionaries with the API’s camelCase keys. When Hue reports progress, WorldModel.processing contains WorldModelProcessing: its indexing state, retained and ready evidence cutoffs, and whether evidence is pending. StartingWorldResult.preparation and HueWorldError.preparation optionally contain WorldPreparationProgress, whose state is a WorldPreparationState and which also names the selected evidence cutoff. These dictionaries retain the API’s camelCase keys. Error progress includes only validated fields from at most 16 KiB of response data; unrelated response content is discarded. If a response carries world_insufficient_evidence or world_processing_limit, the client stops retrying that request. Other transient diagnostics retain the retry behavior below. Materialization, instance creation and reproduction wait up to 120 seconds only after HTTP 503 with X-Hue-Diagnostic: world_preparing, separately from ordinary max_attempts. Retries preserve the serialized body and idempotency identity. Pass a threading.Event as cancel_event to cancel the wait or an active HTTP read. Other failures retain the configured attempt limit; a preparing or incomplete World is not a usable starting state.

Compatible environment client

hue_sdk.environment is a synchronous client for Hue’s simulated instances. Pass a Read and write project service key as api_key=; base_url defaults to Hue Cloud, and a bare key in the first position raises TypeError. timeout_seconds (default 10) bounds each request and max_attempts (default 4, integer 1–10) bounds retries. It creates, drives, seals and reads instances of published World versions; it does not publish Worlds, bind tools or run your agent. run_simulation has no Python counterpart. Responses are typed dictionaries that keep the API’s camelCase keys, with the same fields as the TypeScript types: EnvironmentRun, RunState, ActionResult, ActionDefinition, ActionParameter, ActionSchema, Observation (OkObservation or ErrorObservation), Effect, Step, StepPage, SealedRun, CoverageGap, CoverageGapReporter, CoverageGapResult and EnvironmentCoverage. Json, RunStatus and FinishStatus are the matching aliases. Unlike EvaluationClient, this client retries every call, including mutations, because each carries an identity Hue deduplicates. It retries transport failures and HTTP 408, 429, 500, 502, 503 and 504 with backoff, and waits Hue’s Retry-After on 429 and 503, at most 10 seconds. Failures raise HueEnvironmentError, whose message never includes response text or credentials; status is the HTTP status or None, and retry_after is the bounded wait in seconds. Responses are limited to 4 MiB and request bodies to 1 MiB.

World handoff

Where Hue’s simulation gateway serves an instance, create_run also returns its handoff: a world token, one mirror URL per pinned provider surface, environment variables and an MCP configuration. Hand these to the agent instead of the project key. world_handoff returns None for an instance created while a deployment’s gateway is off.
world_handoff and mcp_config_file accept HTTP MCP server entries only. They retain each entry’s type, url and headers, drop other fields, and reject a non-HTTP transport with ValueError. WorldHandoff has id, token (a hue_world_ credential that lives as long as the instance), expiresAt, lifecycle (WorldLifecycle: pending, live, completing or sealed), completingUntil, traceparent, baggage, surfaces (WorldSurface entries with provider, surface, providerInstanceKey, url and alias), env (HUE_WORLD_ID, HUE_WORLD_TOKEN, BAGGAGE, TRACEPARENT and one HUE_SIM_<SURFACE ID>_URL per surface) and mcpConfig (WorldMcpConfig, the common mcpServers shape of WorldMcpServer entries with the token as a bearer). RunState of a gateway instance adds advisory flags (WorldFlag: no_calls or fingerprint_differs) and never returns the token; WorldEvidenceSection names the evidence sections. A WorldSurface may add an account-scoped token and connection: WorldSurfaceConnection. Prefer the surface token when present. The connection describes root (url, optional replaces), accepted auth placements (header, scheme, format) and optional replaces, accountIds, versions, headers and clients. Token placeholders refer to the surface token when present, otherwise the world token. Older servers may omit connection. WorldClientHint entries in clients identify the client package, language, credential option credential and options (name and value). Optional note and unavailable (alias_host, account_id or https_only) explain why a configuration cannot be used. Finishing a gateway instance answers lifecycle: "completing" with sealedAt: None; the seal follows a 5-second grace. get_evidence needs the project key, and an open instance answers 409 until it is sealed. Nothing in these helpers logs the token. Keep the handoff out of your own logs and checkpoints.

Managed target adapter

ManagedTargetHandler from hue_sdk.managed requires machine_credential, a synchronous target callback and flush_telemetry. Optional arguments are tracer, base_url, max_execution_millis (default 90000, at most 90000) and finalization_millis (default 30000, at most 30000). Pass tracer=hue.tracer with a Hue-owned client; without it the handler falls back to the global tracer, its span is not recorded and every invocation returns uncertain. handle(payload, headers) accepts bounded raw JSON bytes or a dictionary and returns ManagedResponse with status_code, body and headers. The target receives a ManagedTargetContext with execution_id, attempt, input, config, input_files, the cancelled event, deadline_monotonic and trace_id; input_files is a tuple of ManagedInputFile entries with artifact_id, filename, content_type, byte_size, sha256, role and the verified data bytes. It returns ManagedTargetResult; generated files use ManagedOutputFile, with one of the 22 content types TypeScript lists as outputContentTypes. Any other type, such as audio/pcm, records the invocation as an error before any upload; before 0.10.0 Python accepted any valid media type. Calls use the existing tracing providers. A false flush result leaves telemetry pending. See managed runs for framework integration, cancellation and recovery.

Serving lifecycle

Import create_hue_safe from hue_sdk. It accepts the same constructor arguments as Hue, catches ordinary initialization failures and returns a disabled client with an instrumentation failure. enabled=False needs no API key and does not attach to a supplied provider. Initialize once per serving process after fork; inherited clients no-op instead of reusing parent worker locks. force_flush_safe(timeout_millis=1000) and shutdown_safe(timeout_millis=1000) return booleans without raising. Observe export_status; it includes instrumentation_failures, dropped_trace_records, dropped_log_records, queued_trace_records, queued_log_records, queued_trace_bytes, queued_log_bytes, uploaded_values and upload_fallbacks. Queued counts include in-flight records; health is cumulative. Constructor options max_queue_size=2048 and max_queue_bytes=8388608 bound each signal’s retained telemetry; up to 128 MiB of large values and inline files can be held separately while awaiting upload. Encoded bytes are not total process RSS. HTTP acknowledgements are capped at 64 KiB; 429 and Retry-After are honored within the transport budget. One retained network worker per signal, and one for live-span placeholders, bound blocked network work, although Python cannot forcibly cancel every blocked system call. After a request timeout, each worker may retain up to 1 MiB of encoded request data outside queue counters. Later batches stay queued within their limits until transport recovery; shutdown counts any queued records it must discard. See Python production setup.