Browse release notes for the HoneyHive Python SDK, TypeScript API SDK, TypeScript Control Plane SDK, and CLI. Stay current with new features, bug fixes, and breaking API changes.
Added --data-plane-api-key and HH_DATA_PLANE_API_KEY for fine-grained data plane API keys (hh_fgdp_...). Create one in the HoneyHive app under project, workspace, or organization Settings → API keys, on the Data Plane tab.
Added --project-id to charts list, charts create, charts get, and charts update. With --project-id, the command calls the project-scoped route and authenticates with the data plane API key. Pass --project-id even when the key is rooted at that project. Without it, the command calls the legacy route with the project API key, even when a data plane key is configured. A project API key cannot stand in for a data plane key on the scoped route.
Added data-plane-api-keys create, which creates a data plane API key. It takes --project-id, --name, --permissions (a JSON array such as ["project.chart.get"]), --expires-at (ISO 8601), and an optional --description.
Added ingestion-api-keys create, which creates an ingestion API key. It takes --project-id, --name, and an optional --description.
charts create and charts update now accept five_minute and auto for --bucketing.
An error for a missing API key now names the key the command needs and the flag and environment variable that supply it. For data plane and control plane keys, the error also says where in the app to create one. An error for a malformed key names the flag or environment variable the bad value came from.
--verbose on data plane commands now logs all three data plane keys (project, ingestion, and data plane), and prints (none) for any that are unset. A masked ingestion or fine-grained key shows its prefix and key id with the secret replaced by ******, which matches the masked form in the HoneyHive app.
Calling charts commands without --project-id is deprecated. --project-id becomes required in the next major version. Pass it with a data plane API key.
The CLI now checks every typed key you have configured (ingestion, data plane, control plane) when a command starts, including keys that command does not use. A key of the wrong type or an incomplete key in HH_INGESTION_API_KEY, HH_DATA_PLANE_API_KEY, or the matching flag now fails the command before it sends a request. The error names the flag or environment variable that holds the bad value. Fix or unset the stale value.
The CLI no longer checks the format of the project API key (--project-api-key / HH_PROJECT_API_KEY) locally. It sends the value as given, and the server decides whether to accept it.
HoneyHive(...) accepts data_plane_api_key=, also read from HH_DATA_PLANE_API_KEY, for fine-grained hh_fgdp_ keys. It is exposed as client.data_plane_api_key. A value that is set but is not a complete hh_fgdp_ key raises ValueError at construction.
Project-scoped chart operations
Every client.charts method (list, get, create, update, delete and their _async variants) accepts an optional keyword-only project_id. With project_id, the call targets that project and is sent with the data plane API key. It never falls back to api_key.
MissingApiKeyError
New exception, importable from honeyhive. It subclasses ValueError and has a key_kind attribute. An operation raises it before sending a request when no key it accepts is configured, and the message names the key and environment variable to set.
HTTPException raised by API calls now includes the server’s error message, and a 404 adds a hint that the resource does not exist or the key lacks access to it. New server_message and error_code attributes expose the parsed error body. The exception type, status_code, and the message prefix are unchanged, so existing handlers keep working.
Missing keys fail before the request is sent
An operation called with no usable API key now raises MissingApiKeyError locally, instead of sending an unauthenticated request and failing at the API.
events.update_event() accepts a model
update_event() now accepts an UpdateEventRequest as well as a dict. A dict is validated into the model.
Calling a client.charts method without project_id still uses the project API key, but now emits a DeprecationWarning. These calls stop working in v2.0. Pass project_id and configure a data plane API key.
Unused error-handling helpers in honeyhive.utils
ErrorHandler, get_error_handler, handle_api_errors, ErrorContext, ValidationError, HoneyHiveConnectionError, RateLimitError, and AuthenticationError can still be imported from honeyhive.utils and honeyhive.utils.error_handler, but importing them now emits a DeprecationWarning.
New dataPlaneApiKey client option and HH_DATA_PLANE_API_KEY environment variable for a fine-grained data plane API key (a value beginning with hh_fgdp_). The client sends this key on operations that are scoped to a project, which today are the chart operations.
Every client.charts method (list, create, get, update, delete) now accepts an optional project_id. With project_id, the call goes to the project-scoped chart endpoints and authenticates with the data plane API key. client.charts.list() now takes an optional request argument, a new GetChartsRequest type.
New client.dataPlaneApiKeys.create() creates a fine-grained data plane API key rooted at a project. New client.ingestionApiKeys.create() creates an ingestion API key for a project. Both return key_value once, and you cannot get it again.
New exported request and response types: CreateDataPlaneApiKeyRequest/Response and CreateIngestionApiKeyRequest/Response.
New exported error classes MissingApiKeyError and MalformedApiKeyError, both subclasses of HoneyHiveError, and the ApiKeyKind type. Each error has a keyKind property ('project', 'ingestion' or 'dataPlane'). MalformedApiKeyError also has a source property that names the option or environment variable the bad value came from.
The chart bucketing option now accepts five_minute and auto.
Verbose logging now prints a Data plane API key: line. The line shows hh_fgdp_, the key id and none of the secret, and shows (none) when no key is set.
An operation whose required key is not configured now throws a MissingApiKeyError before it sends a request. The error names the key that the operation needs. Previously, some operations sent the request without a key and failed with a 401.
An ingestionApiKey, HH_INGESTION_API_KEY, dataPlaneApiKey or HH_DATA_PLANE_API_KEY value that is not a well-formed key of that kind now throws a MalformedApiKeyError when the client is constructed. The error never echoes the value.
Calling a client.charts method without project_id is deprecated. It becomes required in the next major version. These calls still use the legacy route and the project API key. Each method logs a one-time deprecation warning to stderr. To migrate, pass project_id and configure a data plane API key.
A call with project_id needs a data plane API key and never falls back to the project API key. A data plane API key cannot send traces, so keep an ingestion key or a project key for ingestion.
A client with no API key configured now constructs successfully. The first operation that needs a key throws a MissingApiKeyError. Previously, the constructor threw a Missing API key error. If your code catches the missing-key error at construction, also handle it at the first call.
A client that has custom middleware or its own Authorization header never throws MissingApiKeyError. Authentication is left to the middleware or the header.
New exported error classes MissingApiKeyError and MalformedApiKeyError. Both extend HoneyHiveError.
Client construction now throws MissingApiKeyError when no API key and no middleware are configured, and MalformedApiKeyError when apiKey or HH_CONTROL_PLANE_API_KEY is not a well-formed fine-grained control plane key. Before this release, both cases threw a plain Error. You can now catch these with instanceof checks. MalformedApiKeyError.source names the option or environment variable that held the bad value. The error never echoes the key.
Added --ingestion-api-key and HH_INGESTION_API_KEY for the commands that send traces and events: sessions create, sessions create-event-batch, events create, events update, and events create-batch. These take an ingestion API key (hh_ingst_...), created at project scope on the API Keys page under Settings. They still accept a project API key, so a shell that exports only HH_PROJECT_API_KEY keeps working. Give ingestion its own key in a new setup. Every other command is unchanged.
Added --slug to workspaces create and virtual-dataplanes create. A slug takes letters, digits, and underscores only, and must be globally unique. Omit it and the server derives a slug from the name with a random suffix, exactly as before. Supply it when the identifier has to match a value maintained outside HoneyHive, such as an identity provider group that grants access to the scope. A slug already in use fails with a 409 naming the slug.
API keys are now trimmed before the CLI checks their shape. A key pasted with surrounding whitespace or a trailing newline is no longer rejected locally when the API would have accepted it.
The pre-flight key check now judges the exact credential each command sends, rather than assuming one key per API. Its error names the key and the flag or environment variable that command needs.
metrics run no longer fails with a 400 when the metric reads ground_truth and the event carries none. The command now exits 0 and prints success: false with result: null and the reason in explanation. A script that read the non-zero exit code as the signal must read success in the printed JSON instead.
Every command now gets a 404 where the API used to answer a permission failure with 403 or a rejected API key with 401. A rejected key is one that is invalid, revoked, or expired. The response does not say which case applies, and the error no longer names the check that refused. A script that branched on 401 or 403 must read the not-found error as covering all three cases. These are server changes, so they apply to every CLI version.
--needs-ground-truth and --no-needs-ground-truth on metrics create and metrics update are deprecated and ignored, and now log a deprecation warning to stderr. The server infers ground-truth use from the metric definition. A Python metric that reads ground_truth needs it, and so does an LLM metric whose template references it. The same field inside a metric-versions create --content payload, and inside any --filename payload, is likewise accepted and ignored. The flags will be removed in the next major version. Stop passing them.
workspace_id inside the --event payload of metrics run is deprecated and ignored. The workspace whose provider credentials run the metric is derived from the authenticated key’s scope, so naming a different workspace has no effect.
The bundled YAML parser used for --filename input now bounds recursive merge aliases. A YAML file with deeply chained merge keys no longer expands unchecked.
New ingestionApiKey client option and HH_INGESTION_API_KEY environment variable for supplying an ingestion API key (a value beginning with hh_ingst_). The client sends it on the operations that send traces and events: client.sessions.create(), client.sessions.createEventBatch(), client.events.create(), client.events.update(), and client.events.createBatch(). The client sends the project API key on everything else.
An ingestion API key is now a credential on its own. A process that only sends traces and events can construct a client with the ingestion key and no project API key. Every other operation on such a client behaves as it does with no project API key configured.
An ingestionApiKey or HH_INGESTION_API_KEY value that is not a well-formed ingestion key throws when the client is constructed. The error names the option or variable the value came from and never echoes the value.
Verbose logging now prints an Ingestion API key: line next to the project key. The line shows hh_ingst_, the key id, and none of the secret. This is the form HoneyHive displays, so you can match the line against the key in your account. A credential that is not configured logs as (none).
client.metrics.run() now derives the workspace whose provider credentials run the metric from the caller’s authenticated scope rather than from the request body. Previously a workspace_id in the request event was forwarded as-is. That let an authenticated caller run an ad-hoc LLM metric against another tenant’s configured provider credentials.
A metric run that needs ground truth the event does not carry is now skipped instead of failed. client.metrics.run() returns 200 with success: false, a null result, and an explanation. It previously threw a 400 with ground_truth_missing. Adding ground truth to the event re-enqueues it, and the metric computes on that pass.
The error thrown when no credential is configured now reads Missing API key and names the four current sources: projectApiKey, ingestionApiKey, HH_PROJECT_API_KEY, and HH_INGESTION_API_KEY.
A client configured with a project API key and no ingestion key still sends the project key on the ingestion operations.
HH_INGESTION_API_KEY is read at client construction for the first time in this release. A process that already sets it to a non-empty value that is not a well-formed ingestion key now fails to construct a client. Unset the variable, or set it to your ingestion key, before upgrading.
needs_ground_truth is deprecated and ignored on every metric request and response type, including CreateMetricRequest, UpdateMetricRequest, MetricItem, MetricVersionContent, and the metric passed to client.metrics.run(). The API now infers the need for ground truth from the metric definition. The property remains in the type definitions so existing code keeps compiling, and reads still return the stored value.
workspace_id on the event passed to client.metrics.run() is deprecated and ignored. It remains accepted, so existing code keeps compiling. Remove it and rely on the key’s scope.
Scope creation accepts a caller-supplied identifier: an optional slug on CreateWorkspaceRequest and CreateVirtualDataplaneRequest. Omit it and the server derives one from name with a random suffix, as before. Supply it when the identifier has to match a value maintained outside HoneyHive, such as an identity provider group that grants access to the scope. A slug already in use gets a 409 that names it.
The client validates the API key at construction. A value in apiKey or HH_CONTROL_PLANE_API_KEY that is not a well-formed fine-grained control plane key (hh_fgcp_…) throws when you build the client. The error names the option or the environment variable the value came from, and it does not echo the key. Before this release the same value failed on the first request as an authentication error.
Every control plane endpoint answers an authorization failure with 404 instead of 403. The status no longer reveals whether a resource you may not touch exists. The control plane does not emit 403 at all any more.
An authentication failure on a fine-grained control plane key also answers 404 instead of 401. This covers a missing Authorization header and a key that is invalid, revoked, or expired.
A 404 now means “not found”, “not permitted”, or “not authenticated”, and the response does not say which. Code that refreshes a credential on 401 or branches on 403 no longer sees either status.
A 404 body carries the fixed message"Not found" and the fixed errorCode"not_found". ApiError.message and parseError() no longer name which check refused. The server logs carry that detail.
The three status changes above are control plane changes, so they apply to every SDK version, not only 1.2.0.
The axios runtime dependency moves from 1.19.0 to 1.20.0.
HoneyHive(...), HoneyHiveTracer.init(...), and evaluate(...) accept ingestion_api_key=, also read from HH_INGESTION_API_KEY. The ingestion key is sent only on the routes that create sessions and write events, including OTLP trace export; every other route keeps using api_key. When it is unset, api_key is used for ingestion too, so existing setups are unchanged. A value that is set but is not an hh_ingst_ key raises ValueError at construction rather than failing later at request time.
Connection settings resolve the same way in every entry point
The client, the tracer, evaluate(), and the CLI now resolve api_key, ingestion_api_key, and the API URL through one resolver, so a single process can no longer authenticate with one key in evaluate() and another in a tracer. An explicit argument beats the environment, and a blank value counts as unset.
HH_API_KEY and HH_API_URL are the preferred variables and win when more than one is set. HONEYHIVE_API_KEY, HONEYHIVE_SERVER_URL, and HH_SERVER_URL still work but are deprecated and emit a DeprecationWarning once per process. If you set both HONEYHIVE_API_KEY and HH_API_KEY to different values, evaluate() and the CLI now use HH_API_KEY; they previously preferred HONEYHIVE_API_KEY.
Tracer: RecursionError from trace.get_tracer() after tracer shutdown
Shutting down the main HoneyHiveTracer reset the global OpenTelemetry provider to a fresh ProxyTracerProvider, which delegates back to the global provider — itself. Any subsequent opentelemetry.trace.get_tracer(...) call (including module-level calls made when importing libraries such as mcp) raised RecursionError. Shutdown now clears the global provider so OpenTelemetry returns its own proxy.
Events API: retry config now controls events.export()
HoneyHive(retry_config=...) and HH_MAX_RETRIES were accepted and ignored. They did not reach events.export() / export_async(), which fell back to a fixed budget of 3 retries. Both configuration methods now set the retry budget for events.export() / export_async().
honeyhive[openinference-anthropic], honeyhive[traceloop-anthropic], and the bundles that include them now require anthropic<1.0.0, and the OpenInference extras also require openinference-instrumentation-anthropic<2.0.0. A mismatched pair either raised ModuleNotFoundError on import or logged a dependency conflict and skipped instrumentation. The SDK already implicitly depended on anthropic<1.0.0 as that was the only version available, which worked until Anthropic recently published v1.0 of their SDK.
LangChain extras now install langchain-openai
honeyhive[openinference-langchain] and honeyhive[traceloop-langchain] pull in langchain-openai>=1.0.0 alongside langchain. These dependencies were always required for tracing to work correctly with LangChain but they weren’t declared before.
Added workspaces subcommands for managing workspaces: workspaces create, workspaces get, workspaces update, and workspaces delete. workspaces create takes --virtual-dataplane-id and --name, plus optional --description and --workspace-creator (the email of the user to grant workspace-creator membership to, for API key callers).
Added virtual-dataplanes subcommands for managing virtual data planes: virtual-dataplanes create, virtual-dataplanes get, virtual-dataplanes update, and virtual-dataplanes delete. virtual-dataplanes create takes --org-id and --name, plus optional --cluster-id (required when the organization has no virtual data planes yet, or its virtual data planes span more than one cluster) and --dataplane-creator.
workspaces delete and virtual-dataplanes delete accept --dangerously-delete-child-scopes to archive a scope that still has active children, archiving those children too. Without the flag, deleting a workspace with active projects — or a virtual data plane with active workspaces — fails with a 409 and changes nothing.
Like projects and alerts, both new command groups talk to the HoneyHive control plane: they take a fine-grained control plane API key (hh_fgcp_...) via --control-plane-api-key / HH_CONTROL_PLANE_API_KEY and honor --control-plane-url / HH_CONTROL_PLANE_URL. Data plane commands are unchanged and still use --project-api-key / HH_PROJECT_API_KEY.
client.metrics.run() now distinguishes failure classes: 400 when the request is invalid or is missing inputs the metric needs (e.g. ground truth the event doesn’t carry), 422 when evaluation itself failed (execution_error, compilation_error, template_render_error, llm_response_parse_error, …), and 500 for internal errors. ApiError.parseError() returns the errorCode along with the evaluator’s detailed failure text in message.
Empty or whitespace-only name values passed to client.experiments.createRun() and client.experiments.updateRun() are now rejected with a 400, and accepted names are trimmed before storage. Such names previously created runs with a blank display name.
Composite metrics are no longer supported. child_metrics is marked deprecated on every metric request and response type and is now ignored by the API, and creating or updating a metric with type: 'COMPOSITE' returns a 400. Both remain in the type definitions so existing code keeps compiling; replace composite metrics with standalone metrics.
Workspace management via the new workspaces namespace: create(), get(), update(), and delete(), with matching CreateWorkspaceRequest/Response, GetWorkspaceRequest/Response, UpdateWorkspaceRequest/Response, and DeleteWorkspaceRequest/Response types.
Virtual data plane management via the new virtualDataplanes namespace: create(), get(), update(), and delete(), with matching CreateVirtualDataplaneRequest/Response, GetVirtualDataplaneRequest/Response, UpdateVirtualDataplaneRequest/Response, and DeleteVirtualDataplaneRequest/Response types.
Deleting a workspace or virtual data plane archives everything inside it, so a resource with active children is rejected with a 409 unless the request sets dangerously_delete_child_scopes: true.
Creating a project with project_creator now marks that user’s sessions for refresh, so they no longer have to sign out and back in to see the new project. The change is in the control plane, so it applies to any SDK version. The refresh takes effect on their next request to the control plane, so an idle browser tab may still need a page reload.
Fixed the Homebrew formula published for each release so brew install honeyhive and brew upgrade honeyhive resolve the current CLI version. The formula no longer declares an explicit version that recent Homebrew versions reject as redundant during validation.
Installing a stable release via Homebrew now requires Homebrew 6.0.14 or newer, which reads the version from the release URL. An older client that installs without updating first — most commonly HOMEBREW_NO_AUTO_UPDATE=1 in a Docker or CI image — records the wrong version and will not report the install as outdated afterwards. Run brew update before installing, or reinstall once Homebrew is current. npm and npx installs are unaffected.
Added projects subcommands for managing projects: projects create, projects get, projects update, and projects delete.
Added alerts subcommands: alerts list, alerts create, and alerts get.
Added --control-plane-api-key / HH_CONTROL_PLANE_API_KEY and --control-plane-url / HH_CONTROL_PLANE_URL. The new projects and alerts commands talk to the HoneyHive control plane, which takes a fine-grained control plane API key (hh_fgcp_...) created at workspace or organization scope — not a project API key. Every other command is unchanged and still uses --project-api-key / HH_PROJECT_API_KEY; you only need the key for the commands you actually run.
The CLI now checks what kind of API key you supplied before sending a request. Passing a control plane key to a data plane command (or the reverse) fails immediately with a message naming the key kind the command needs and the flag or environment variable the wrong key came from, instead of an unexplained 401 from the server.
--verbose now reports the URL and key for whichever API the command talks to (Control plane URL: for projects and alerts), and masks a fine-grained control plane key exactly as the HoneyHive app displays it, so you can match a log line to a key in your account.
Composite metrics are no longer supported. metrics create and metrics update now fail with a 400 when passed --type COMPOSITE, existing composite metrics and their versions have been deleted, and --child-metrics no longer has any effect on a metric’s score.
First stable release of the HoneyHive TypeScript Control Plane SDK (@honeyhive/control-plane-sdk). Functionally identical to 1.0.0-rc.1 — no code changes, so upgrading from the release candidate requires no migration.
Tracing: root SERVER spans get an automatic session_id
When HoneyHiveTracer is initialized with skip_backend_session_creation=True and no session_id, the SDK now generates a session_id for each root SERVER span (SpanKind.SERVER, no parent) and propagates it via baggage. Previously these root spans were dropped and their children appeared orphaned in the Sessions tab — common with FastAPIInstrumentor, where the root span is created before any middleware runs. Existing single-session and client-span behavior is unchanged.
Experiments: evaluate() normalizes run names
evaluate(name=...) now trims surrounding whitespace, and a blank or whitespace-only name falls back to the default experiment-<id> name instead of being submitted as-is. The backend also now rejects empty run names.
Composite metrics removed from the metric API surface
The child_metrics field and the generated *ChildMetricsItem models have been removed from the metric request/response models in honeyhive.models, completing the composite-metrics deprecation. Composite metrics are no longer part of the product, so any remaining code referencing them can be safely cleaned up and removed.
Existing code that passes child_metrics=... keeps working — metric models accept unknown fields (extra="allow"), so the value is still accepted without error. The API already ignored and dropped child_metrics, so this change aligns the client with the backend behavior. The only difference: child_metrics is no longer a declared field, so reading metric.child_metrics off a response now raises AttributeError instead of returning None.
New client.events.get({ event_id }) method for GET /v1/events/{event_id}, fetching a single event by ID.
All SDK methods now accept an optional options?: FetchOptions second argument for cancelling in-flight requests via AbortController. New exported FetchOptions type ({ signal?: AbortSignal }). Example: await client.events.search(request, { signal: controller.signal }).
New projectApiKey client option and HH_PROJECT_API_KEY environment variable for supplying the project-scoped API key. These replace the previous apiKey option and HH_API_KEY environment variable.
Experiment run objects now include a dataset_name field alongside dataset_id.
The outputs field on update-event requests is now typed as an object or null (previously unknown). Passing a non-object value (array, string, or scalar) previously corrupted the stored event and broke downstream consumers such as the Python SDK; such values are now rejected. Passing null preserves the existing outputs.
The apiKey client option and HH_API_KEY environment variable are deprecated and will be removed in the next major version. They continue to work but log a one-time deprecation warning to stderr on client construction. Migrate to projectApiKey / HH_PROJECT_API_KEY.
Added events get --event-id <id> to fetch a single event by its ID.
Added the --project-api-key flag and HH_PROJECT_API_KEY environment variable as the primary way to authenticate the CLI. Verbose output now labels the key as Project API key: (previously API Key:).
experiments list-runs, experiments get-run, and experiments get-summary output now includes the linked dataset_name, and get-summary now reports dataset_id for offline (EXT-*) datasets that previously returned null.
events update --outputs now requires an object or null (where null preserves the existing outputs); non-object values (strings, arrays, scalars) are rejected up front. These values were previously accepted but corrupted the stored event, which could break other consumers reading it back.
The --api-key flag and HH_API_KEY environment variable are now deprecated aliases for --project-api-key / HH_PROJECT_API_KEY. They still work but log a deprecation warning to stderr and will be removed in the next major version. Migrate to the new names.
New honeyhive.adapters.copilot_studio.copilot_studio_records_to_spans() converts Azure Application Insights diagnostic-export records from a Copilot Studio agent into OpenTelemetry spans you can forward to HoneyHive via OTLP. Maps user/agent messages, tool calls, and errors using GenAI semantic conventions, preserves parent/child trace correlation, and groups a conversation into a single HoneyHive session. Set COPILOT_STUDIO_ADAPTER_KEEP_TOPIC_SPANS=1 to retain internal orchestration spans (dropped by default) and COPILOT_STUDIO_ADAPTER_DEBUG=1 to attach the raw source record for debugging.
dataset_name on experiment runs
ExperimentRunObject now includes a dataset_name field alongside dataset_id, so the linked dataset’s name is available when listing or fetching experiment runs. The field is optional and resolves to None for offline (EXT-*), deleted, or unset datasets.
UpdateEventRequest.outputs and LegacyUpdateEventRequest.outputs are now typed as Dict[str, Any] instead of Any. Update calls accept only normalized (object-shaped) outputs; previously an array could slip through and corrupt the stored event. If you were passing a list when updating an event, wrap it as {"value": [...]}. Event creation and OTEL ingestion continue to normalize arrays automatically.
HoneyHive(timeout=...) now sets the per-request timeout, in seconds, for standard API client calls. You can also set HH_API_TIMEOUT; the explicit timeout= argument takes precedence. The default remains 5 seconds, so existing clients keep the same timeout unless you opt in.
Event lookup by ID
The generated sync and async event services now include GET /v1/events/{event_id} as getEvent(..., event_id=...), returning GetEventResponse / GetEventResponseEvent models exported from honeyhive.models.
Custom tracer export HTTP sessions
HoneyHiveTracer.init(requests_session=...) and TracerConfig(requests_session=...) now accept a caller-owned requests.Session for OTLP span export. Use this when you need custom proxies, retries, TLS settings, or connection pooling. The SDK does not close a session that you provide.
Self-host: GET /v1/events/{event_id} requires backend v1.3.0+
Self-hosted deployments must run a HoneyHive backend on version 1.3.0 or greater before calling GET /v1/events/{event_id}. Older self-host backends do not expose this route, so event-by-id calls will fail until the backend is upgraded. HoneyHive Cloud users are unaffected.
New client.metric_versions.list(metric_id), .create(metric_id, request), and .deploy(metric_id, version_name) methods (plus *_async variants) for managing a metric’s immutable version history, backed by /v1/metrics/{metric_id}/versions. Each metric keeps a history of versions with one deployed at a time; pass deploy_immediately=True on create to atomically deploy the new version. Version request/response models are exported from honeyhive.models.
OTLP JSON exporter: serialize numeric fields as JSON strings
Integer span attributes (intValue) and uint64 timestamp fields
(startTimeUnixNano, endTimeUnixNano, timeUnixNano) were emitted as
raw JSON numbers. The protobuf JSON mapping spec requires these to be JSON
strings; values above 2^53 could otherwise lose precision silently through
float64 rounding. Now matches native opentelemetry-exporter-otlp-proto-http
behavior.
Decorator input capture: remove truncation of serialized list/dict values
List and dict span attributes are serialized to strings and
previously were truncated to 1000 characters in length. The arbitrary limit
of 1000 characters has been removed.
New client.metricVersions namespace with list, create, and deploy methods for managing snapshot versions of a metric’s definition via /v1/metrics/{metric_id}/versions and /v1/metrics/{metric_id}/versions/{version_name}/deploy.
New exported request/response types: GetMetricVersionsRequest/Response, CreateMetricVersionRequest/Response, and DeployMetricVersionRequest/Response.
Added metric-versions subcommands for managing snapshot versions of a metric’s definition: metric-versions list, metric-versions create, and metric-versions deploy. Use these to review history, create new draft or immediately-deployed versions, and roll between versions without losing history.
Added a dataPlaneUrl client option and HH_DATA_PLANE_URL environment variable for configuring the data plane URL. These replace the previous serverUrl option and HH_API_URL environment variable.
The verbose logging output now labels the resolved URL as Data plane URL: (previously API URL:).
Environment variables set to the empty string (e.g. HH_API_KEY=, HH_DATA_PLANE_URL=) are now treated as unset and fall back to defaults, rather than being propagated as a literal empty string.
The serverUrl client option and HH_API_URL environment variable are deprecated and will be removed in the next major version. They continue to work but log a one-time deprecation warning to stderr on client construction. Migrate to dataPlaneUrl / HH_DATA_PLANE_URL.
Added --data-plane-url flag and HH_DATA_PLANE_URL environment variable for pointing the CLI at a specific HoneyHive data plane (e.g. self-hosted or staging deployments). Verbose output now labels this value as Data plane URL: instead of API URL:.
The --base-url flag and HH_API_URL environment variable are deprecated and will be removed in the next major version. They still work as aliases for the new names but now log a deprecation warning to stderr on each invocation. Migrate to --data-plane-url / HH_DATA_PLANE_URL.
Error output for failed API requests now includes the server’s error message. All CLI commands that hit the API previously printed only API error <status>; they now print API error <status>: <message> with the actionable detail from the server.
New client.charts.create(), .list(), .get(chart_id), .update(chart_id, request), and .delete(chart_id) methods (plus *_async variants) backed by POST /v1/charts, GET /v1/charts, GET /v1/charts/{chart_id}, PUT /v1/charts/{chart_id}, and DELETE /v1/charts/{chart_id}. Chart request and response models are exported from honeyhive.models.
The CrewAI example (examples/integrations/crewai_integration.py) has been rewritten with three realistic customer-support scenarios (single-agent with tool calls, sequential two-agent crew, and @trace escalation). Crews are now named for clearer span labels, and teardown properly flushes remaining spans.
Tracer init: project / HH_PROJECT no longer required
HoneyHiveTracer.init() previously required project and treated a missing value as degraded mode. Since the backend determines the project from the API key, only api_key is actually needed. Callers that followed the v1.0.1 deprecation guidance and removed project were silently running in degraded mode — this is now fixed. project and HH_PROJECT remain accepted for backwards compatibility (deprecated, to be removed in v2.0).
Duplicate model spans in evaluate()
evaluate() could occasionally emit two model spans for a single LLM call when running multiple datapoints concurrently. The underlying race condition in instrumentation setup has been fixed.
cp_base_url= parameter and HH_CP_API_URL env var removed
These options were vestigial configuration for an incomplete Control Plane integration that was never wired up or shipped. No customer code could have depended on them. They have been removed to clean up the public API surface. If you happen to pass cp_base_url= or set HH_CP_API_URL, simply remove them — HH_API_URL / base_url= is the only base-URL setting.
New client.charts namespace with create, list, get, update, and delete methods for managing charts via /v1/charts and /v1/charts/{chart_id}.
New client.experiments.getSummary() method for GET /v1/runs/{run_id}/summary, returning pass/fail results, metric aggregations, per-datapoint results, and the experiment run object.
New client.sessions.createEventBatch() method for POST /v1/sessions/{session_id}/events/batch, accepting a batch of events scoped to a single session (the session_id from the path overrides any value in the event body).
New exported request/response types: CreateChartRequest/Response, GetChartRequest/Response, GetChartsResponse, UpdateChartRequest/Response, DeleteChartRequest/Response, GetExperimentSummaryRequest/Response, and CreateSessionEventBatchRequest/Response.
Experiments: client-side evaluator scores now flow end-to-end in evaluate()
Scores returned by evaluators in evaluate() are now written to the correct user-function chain span via enrich_span(metrics=…), exported over OTLP, and surfaced in server-side run comparison’s per-event metric_deltas. Previously, evaluator scores were duplicated into run.metadata.evaluator_metrics and onto the per-datapoint session event, but neither path actually populated the per-event surface that run comparison requires — client-side evaluator scoring and comparison did not work end-to-end.
The two legacy write paths have been removed now that the scores are correctly written to the chain span as the single source of truth.
API Client: event_id typed as required on POST /events responses
PostEventResponse.event_id was incorrectly typed as Optional[str] in the OpenAPI spec; the backend always returns the field on a 2xx response. The spec was corrected and the generated SDK now reflects the runtime guarantee, removing the need for defensive if event.event_id: guards. No runtime behavior change, but strictly typed mypy codebases with warn_unreachable = True or pyright with reportUnnecessaryComparison enabled may produce “unnecessary comparison” or “redundant Optional guard” warnings, depending on exact usage patterns.
ID = "id" was never a valid backend wire value and has always been rejected on the wire. Use "string" for UUID-shaped fields such as session_id. The alias is preserved so existing imports continue to resolve and will be removed in the next major.
honeyhive Python CLI entry point removed from pyproject.toml
The shipped Python honeyhive console script was non-functional (dead code) and shadowed the official TypeScript CLI on $PATH. CLI functionality is now provided by the official honeyhive TypeScript CLI; removing the Python script entry point lets honeyhive resolve correctly when both packages are installed globally.
Default API URL fallback corrected to https://api.dp1.us.honeyhive.ai
The fallback value for the base API URL in the v1.0.0 release was incorrect. Any callers who relied on the implicit default would fail. The default now points at the host the SDK is built against, though self-hosted / non-default Data Plane deployments will still need to set HH_API_URL explicitly. Callers that explicitly set base_url= / server_url= or HH_API_URL are unaffected.
project argument and HH_PROJECT environment variable
The SDK’s public surface has accepted project= on HoneyHive() and HoneyHiveTracer.init() and the HH_PROJECT env var for historical reasons. These arguments and env vars have no influence on the backend and they were maintained purely for backwards compatibility of callers. This release sweeps the stale references out of the example scripts, README, and docstrings, and adds a DeprecationWarning at the remaining call sites that previously didn’t emit one. The argument and the HH_PROJECT env var alias remain accepted for backwards compatibility and will be removed in v2.0.
First stable GA release of the HoneyHive Python SDK. Public APIs follow semver from this release forward — breaking changes only on major versions, additive on minor and patch.The changes below are relative to 1.0.0rc22. For the full picture of what shipped during the release-candidate cycle, see the 1.0.0rc1–1.0.0rc22 entries.
Tracing: skip_backend_session_creation=True now works without an explicit session_id
Previously the flag only opted out of the init-time backend roundtrip when a session_id was also supplied. Setting the flag alone is now supported: the SDK skips the roundtrip, does not mint a UUID, and per-request create_session(session_id=..., skip_api_call=True) calls emit spans that ingestion materializes into Session rows on first arrival.
Tracing: create_session(skip_api_call=True) propagates session_name into baggage
When session_name is supplied, it now travels with session_id across async / threaded boundaries.
Internal query-params type that was exported but unused — no public method accepted or returned it. The public client.metrics.delete(id=...) signature is unchanged.
Was this page helpful?
Assistant
Responses are generated using AI and may contain mistakes.